The <textedit.h> Header File

Routines to access the text editor

Functions

TE_checkSlack
Reallocates the text editor buffer if there is not much space left in it.
TE_close
Closes the text editor.
TE_empty
Empties the text editor buffer.
TE_focus
Highlightes the selected text in the editor, and gives the focus to it.
TE_handleEvent
Dispatches an event to the text editor to be processed by it.
TE_indicateReadOnly
Indicates read-only mode of the editor.
TE_isBlank
Check whether the editor buffer is empty.
TE_open
Initializes the text editor.
TE_openFixed
Initializes the text editor, with fixed buffer.
TE_pasteText
Pastes a text into the editor.
TE_reopen
Re-opens the text editor.
TE_reopenPlain
Re-opens the text editor (plain).
TE_select
Selects a block of text in the editor, or positions the cursor.
TE_shrinkWrap
Shrinks the text editor buffer.
TE_unfocus
Removes the focus from the selected text in the editor.
TE_updateCommand
Updates the command byte in the current line of the text.

Constants

TE_FAR_RIGHT
A constant defining the last cursor position in TE_open.

Predefined Types

Bool
An enumeration to describe true or false values.
ETE_FLAGS
Enumerates optional features for the TE_open function.
EVENT
A structure describing an event message.
HANDLE
Represents a handle associated with an allocated memory block.
SCR_RECT
A scructure for defining a rectangular area.
SCR_STATE
A structure for saving the state of the graphics system.
size_t
A type to define sizes of strings and memory blocks.
TEXT_EDIT
A structure used to coordinate all text editor operations.
WIN_RECT
A structure for defining a rectangular area.
WINDOW
The main window-describing structure.

TE_checkSlack

void TE_checkSlack (TEXT_EDIT *te);

Reallocates the text editor buffer if there is not much space left in it.

TE_checkSlack checks how much free space is present in the text editor buffer (associated with the structure pointed to by te). If there is not much space left, then the buffer is reallocated (expanded). Note that the editor will expand buffer if necessary during normal processing of keypresses using TE_handleEvent, so the user need not to call this function, except if it is necessary to check and eventually expand the buffer independently of event dispatching procedure. Of course, the editor must not be opened with TE_openFixed if you want to use this function.


TE_close

void TE_close (TEXT_EDIT *te);

Closes the text editor.

TE_close closes the text editor structure pointed to by te. I am not sure whether calling this routine is necessary: it performs mainly some irrelevant operations (like calling TE_unfocus). I also know that TE_close tries to free the memory occupied by the buffer (by calling HeapFreeIndir) if the editor was opened using TE_openFixed, and if the buffer was allocated dinamically. So, it seems that it tries to close out a text edit record and to release its memory automatically. It seems better to me to release the memory manually (it is more safe anyway).


TE_empty

void TE_empty (TEXT_EDIT *te);

Empties the text editor buffer.

TE_empty empties the text editor buffer (associated with the structure pointed to by te). Note that this routine turns off cursor blink before emptying the edit buffer, but does not repaint the edit region. It only makes its parent window dirty (i.e. clears its WF_DIRTY bit) so, the edit region will be eventually updated when the next paint message arrives.


TE_focus

short TE_focus (TEXT_EDIT *te);

Highlightes the selected text in the editor, and gives the focus to it.

TE_focus is usually called after TE_select. It highlightes the selected text in the editor (associated with the structure pointed to by te), and gives the focus to it, so the selected text will become active (after this, any keypress will replace selected text with the newly pressed key). Returns TRUE if focusing was performed, and returns FALSE if not (for example, if the text was already focused).

Note: TE_focus also enables the cursor using CU_start if it was disabled. So, it is sometimes used after calling TE_select with Low == High, just to display the cursor.


TE_handleEvent

short TE_handleEvent (TEXT_EDIT *te, EVENT *event);

Dispatches an event to the text editor to be processed by it.

The text editor is an event driven application (see events.h for more info about events). It does not have a "main loop" in which keypresses are collected and processed. Instead, the user need to collect keypresses, and to dispatch them to the editor using TE_handleEvent. The editor will then process the keypress (for example, it will insert a new character, delete a character, scroll the editor area upwards/downwards etc. depending of the concrete keypress). In other words, the "main loop" is part of the user program. This approach is much more flexible, because the user may decide which keys will be processed and which will not be, and the user may program a lot of special actions which are not pre-programmed in the editor. For example, the user can redefine keys, forbid all keys except uppercase letters, etc. TE_handleEvent returns TRUE if the event was sucessfully processed by the editor, else returns FALSE.

TE_handleEvent needs a pointer to the editor control structure te, and a pointer to the EVENT structure event which represents the event to be processed. Basically, after calling TE_open, the program should enter a loop which does keyboard reading, and sending (wanted) keypress events to the editor using TE_handleEvent. The keyboard may be read using ngetchx, but this requires manual converting of integer keycode to an event structure. It is better idea to use EV_getc which is similar to ngetchx but in addition to the returned keycode, it also fills as an event structure. So, the text editor operations should be programmed as follows:

EVENT ev;
TEXT_EDIT te;
HANDLE h = HeapAlloc (200);                     // initial buffer size
memset (HeapDeref (h), 0, 200);

TE_open (&te, DeskTop, MakeWinRect (30, 30, 130, 70), h, 0, 0, 3);

CU_start ();                                    // Enable the cursor

while (EV_getc (ACTIVITY_BUSY, &ev) != KEY_ESC) // Get keypress and translate it to
  {                                             //   the event (until ESC pressed)
    TE_handleEvent (&te, &ev);                  // Send the event to the editor
  }                                             //   to be processed

In this example, all keypresses are passed to the editor. This need not to be always true; in fact, the main loop may contain whatever the user wants. The editor can handle a lot of special keypresses, like marking with shift+arrows, cut, copy and paste operations etc, not only inserting, deleting and scrolling (note that you can later access the clipboard using CB_fetchTEXT and CB_replaceTEXT if necessary). However, TE_handleEvent can not handle keypresses which represents tokens (like "sin" etc.) nor system keypresses which open menus like "CHAR" etc. Fortunately, this problem can be solved easily (see the next example).

The example given above is not a typical example of event driven program. All events in this example are restricted to simple keypresses. Typical event driven program uses EV_eventLoop function, which is an endless loop in which all timers, I/O ports etc. are checked for every possible event, and when an event appears, it is dispatched to the active application. The program need to install an event handler using EV_captureEvents function, which will capture all events, and which need to decide what to do with every particular event. This approach is used in the following example, which is written in typical "event driven" maneer. In this example (extracted from the "Text Editor" example), all events are dispatched to the text editor, except pressing the ESC key (this event will exit the event loop), and all events which were not processed sucessfully by the editor are dispatched to the default event handler (see EV_defaultHandler) which for example split tokens to single characters, open menus, etc:

TEXT_EDIT te;

CALLBACK void EventHandler(EVENT *ev)
{
  if (ev->Type == CM_KEYPRESS && ev->extra.Key.Code == KEY_ESC)
    ER_throw (1);
  if (!TE_handleEvent (&te, ev))
    EV_defaultHandler (ev);
}

void _main(void)
{
  HANDLE h = HeapAlloc (200);
  ...
  memset (HeapDeref (h), 0, 200);
  TE_open (&te, DeskTop, MakeWinRect (30, 30, 130, 70), h, 0, 0, 3);
  CU_start ();
  EV_captureEvents (EventHandler);
  TRY
    EV_eventLoop ();           // The only way to exit from "EV_eventLoop" is
  ONERR                        //   to throw an error from the event handler
    EV_captureEvents (NULL);
  ENDTRY
  ...
}

So, event driven programs using the text edit manager typically process events in three phases. First, the application event handler examines the event for action it needs to take. Either the application handler handles the event and returns to the event manager or it proceeds further. Second, the application event handler calls TE_handleEvent to allow the text edit manager to process the event. Either TE_handleEvent handles the event and returns TRUE, or it does not understand the event and returns FALSE. If TE_handleEvent does not handle the event, the application proceeds further. Third, the application calls EV_defaultHandler to let the event manager have one last try at handling the event. System-wide default behavior is implemented in EV_defaultHandler. Programs may drive the text editor by calling TE_handleEvent with their own created event messages (as in previous example), but in practice, the application just forwards events it received from the event manager (i.e. from the EV_eventLoop loop). Also note that calling TE_handleEvent may cause the heap compression.

Beware that EV_eventLoop is an endless loop, so the only way to exit from it is to throw an error from the event handler. This error will be captured later by a TRY...ONERR...ENDTRY construction.

Note: For the most of applications, you need not to use any text editor functions except TE_open (or TE_openFixed) and TE_handleEvent, because TE_handleEvent can do even relatively complicated operations like cut/copy/paste, etc. Other text editor functions are needed only if the user wants to program some special actions.


TE_indicateReadOnly

void TE_indicateReadOnly (TEXT_EDIT *te);

Indicates read-only mode of the editor.

TE_indicateReadOnly indicates read-only mode of the editor (associated with the structure pointed to by te) by disabling commands "Cut", "Paste", "Clear" and "Del" in all menus registred with the current applications (see EV_registerMenu), and setting the status line (using ST_readOnly). Note that this command works only if the editor is opened in read-only mode (i.e. if TE_READ_ONLY is set in the parameter Flags of the TE_open function). Also note that you need to call ST_readOnly manually later, when you decide to remove the read-only indicator from the status line.


TE_isBlank

short TE_isBlank (TEXT_EDIT *te);

Check whether the editor buffer is empty.

TE_isBlank returns TRUE if the text editor buffer (associated with the structure pointed to by te) is empty, else returns FALSE. Note that the content of the editor is regarded as "blank" if there is no characters in it, or if all characters in it are blanks (spaces).


TE_open

short TE_open (TEXT_EDIT *te, WINDOW *w, WIN_RECT *rect, HANDLE BufHandle, unsigned short cur_offset, unsigned short ReadOnly, unsigned short Flags);

Initializes the text editor.

TE_open initializes the text editor and displays the initial contents of the editor. All text editor operations are controled using a structure of type TEXT_EDIT. TE_open will initialize such a structure pointed to by the parameter te, which later needs to be passed to all text editor operations (i.e. te must be allocated statically to maintain state between calls to the text edit routines). It returns TRUE if the edit buffer could be allocated, or FALSE if there is insufficient memory to allocate the edit buffer. This routine always returns TRUE if BufHandle is passed in with the handle to a text buffer.

Note: The window w must already be open. The handle BufHandle must not be locked.

This routine may cause heap compression.

w is a pointer to the parent window of the editor: you can create a new window to be the parent using WinOpen, or you can pass DeskTop as the parameter, if you are happy with its settings (which is usually the case). rect is a pointer to the WIN_RECT structure which describes the actual dimensions of the rectangular text editor area (You can pass NULL to use entire client rectangle of the window w for the edit region). Note that if you use your own window as a parent window, this window must not be "dirty" (i.e. it must not have the WF_DIRTY flag set). Windows created by WinOpen are "dirty" by default, so you need to clear the "dirty" flag manually before calling TE_open. For example, you can do

w->Flags &= ~WF_DIRTY;

BufHandle is the handle of the text editor buffer, which may be pre-filled with the text (if you want to edit existing text), or filled with zeros (if you want to create a new text). BufHandle may be, for example, the result of a HeapAlloc operation. BufHandle can also be H_NULL, in this case TE_open will allocate a new handle and initialize it with no text. Note that contrary to what I said in the documentation of TIGCCLIB releases prior to 2.2, it cannot be a handle of a text variable, because text variables contain additional system data on the begining, and the editor expect raw data (see the Frequently Asked Questions to learn how you can pass a text variable to the editor though).

The contents of the text buffer are a standard zero-terminated string, in which lines of text are separated with '\r' characters (0xD). The size of the buffer is managed automatically by the editor: it will be expanded if necessary to add more text, so you need not to worry about the allocated size.

The parameter cur_offset is the initial position of the cursor (counted from the begining of the buffer). Position 0 is to the left of the first character. If the contents of the text edit buffer are too long to display entirely in the edit region, the text is scrolled to make sure the cursor is visible. Set cur_offset to TE_FAR_RIGHT to place the edit cursor after the last character in the edit buffer.

The parameter ReadOnly is the count of characters at the begining of the buffer which can't be modified (i.e. which are read-only). ReadOnly is usually set to zero, except in some special applications. The ReadOnly characters are considered to be part of a prompt (or of command characters as in the text editor) so the user cannot change the text of the ReadOnly characters nor move the edit cursor into them.

Flags is a set of binary flags which controls the editor. Each bit specifies optional features of the text editor. Some of these flags are changed automatically during the operation of the editor. The flags are defined in the ETE_FLAGS enumeration and have the following meanings:

TE_WRAPSet this flag for multiline edit regions. Reset it for single-line edit regions: the editor will operate in "compact" mode, in which the editor is only one character high, and where the contents of the editor will scroll left/right when necessary (such a mode is used in request boxes in dialogs). In "compact" mode, the contents of the editor buffer must not contain '\r' characters, else the editor will be fooled. In multiline edit regions, text can wrap around the end of the line to the beginning of the next line. The program editor is an example of a multiline edit region. The Home screen entry line is an example of a single-line edit region.
TE_COLONWhen set, each line of the editor will be preceded with a colon (":"), like in the "Text editor" or the "Program editor". When TE_COLON is reset, there will not be a preceding colon. The program editor uses this flag to mark the beginning of each line of the program.
TE_COMMANDSWhen set, the first character of each line will be regarded as "command character", and it will be displayed before the colon. The "Text editor" application uses this mode to store editor commands (like "P" = "PrintObj" etc.). Note that when this flag is set, the parameter cur_offset must not be zero (it is usually set to 1 in this case).
Note: This flag includes the TE_COLON flag (as needed by the AMS).
TE_MORE_ARROWSSet this flag to display arrows at the left and right ends of a single-line edit region to indicate when more text is to the left or right of the edit region.
TE_MORE_ELLIPSESSet this flag to display ellipses (...) at the left and right ends of a single-line edit region to indicate when more text is to the left or right of the edit region.
Note: This flag includes the TE_MORE_ARROWS flag (as needed by the AMS).
TE_SELECTThis flag is an internal flag. It is set if there currently is a selection in the text editor. It is clear if nothing is selected. Do not set this flag.
TE_CURSORThis flag is an internal flag. It represents the current blinking state of the cursor: it is set if the blinking cursor is currently visible. Do not set this flag.
TE_FIXED_LENGTHThis flag is an internal flag. It is set for text editors opened with TE_openFixed. Do not set this flag.
TE_CHANGEDThis flag is an internal flag. It is a status flag which, if 1, indicates the contents of the edit buffer have changed. Do not set this flag.
TE_FOCUSEDThis flag is an internal flag. It is set if the text editor currently has the focus, i.e. if the cursor is currently in the text editor. See TE_focus and TE_unfocus. Do not set this flag.
TE_AUTO_ANSSet this flag to 1 to cause "ans(1)" to be inserted automatically when the edit buffer is empty and an arithmetic operation is typed.
TE_READ_ONLYWhen set, the editor enters read-only mode. In this mode, the editor displays text and allows arrow keys to navigate through the edit buffer, but it does not allow changing the text, i.e. you can't insert, delete or change any characters.

Note: TE_open just initializes the editor, displays the intial content of it and exits. It does not enter the editor loop in which keypresses are processed. In fact, there is no such loop: you need to get keypresses manually (using ngetchx or, even better, using EV_getc, or using the default event loop EV_eventLoop) and to pass them to TE_handleEvent which will process them. Such an approach gives much more flexibility. See TE_handleEvent for an example of usage.

See also: TE_openFixed


TE_openFixed

short TE_openFixed (TEXT_EDIT *te, WINDOW *w, WIN_RECT *rect, char *buffer, unsigned short maxlen, unsigned short Flags);

Initializes the text editor, with fixed buffer.

TE_openFixed is very similar to TE_open, except it uses a fixed allocated buffer pointed to by buffer instead of dinamically created buffer associated with handle. So, the text buffer can not expand automatically when necessary. The parameter maxlen determines the length of the buffer (the editor will not accept more characters than specified). That's why functions TE_checkSlack and TE_shrinkWrap can not be applied to text editors opened with TE_openFixed.

Note: After opening text editor using TE_openFixed, it is recommended to manually set position of the cursor using TE_select (TE_openFixed has not a parameter for initial cursor position in opposite to TE_open), else strange things may happen.


TE_pasteText

void TE_pasteText (TEXT_EDIT *te, const char *text, unsigned long len);

Pastes a text into the editor.

TE_pasteText inserts len bytes of the text pointed to by text into the text editor buffer (associated with the structure pointed to by te) at the current cursor position. These functions may be used together with CB_fetchTEXT and CB_replaceTEXT if necessary. Also, this function may be used for implementing various (very useful) functions like TE_printf which works like printf but "prints" the formatted output into the text editor. Among various ways of implementing such functions, I suggested the following one (which uses the unusual but powerful function vcbprintf):

CALLBACK void TE_pasteChar(char c, TEXT_EDIT *te)
{
  char str[2] = {c, 0};
  TE_pasteText (te, str, 1);
}

void TE_printf(TEXT_EDIT *te, char *format, ...)
{
  va_list arglist;
  va_start (arglist, format);
  vcbprintf ((vcbprintf_callback_t)TE_pasteChar, (void**)te, format, arglist);
  va_end (arglist);
}

This example is not so simple, so you need to be familiar with (standard) C to understand it.


TE_reopen

void TE_reopen (TEXT_EDIT *te, unsigned short Focus);

Re-opens the text editor.

TE_reopen first checks free space in the text editor buffer (associated with the structure pointed to by te) by calling TE_checkSlack, selects all characters in the editor buffer using TE_select, and eventually gives the focus to them if Focus is TRUE (Focus is Boolean parameter). This function is a good method to re-open previously edited text on such way that all text is selected and focused, so the eventual keypress will replace the selected text. It is usually used to reopen a text edit record which has been closed by TE_shrinkWrap.


TE_reopenPlain

void TE_reopenPlain (TEXT_EDIT *te, unsigned short Focus);

Re-opens the text editor (plain).

TE_reopenPlain is similar like TE_reopen, but it doesn't call TE_select funciton. I am not very sure about usage of this function.


TE_select

void TE_select (TEXT_EDIT *te, unsigned short Low, unsigned short High);

Selects a block of text in the editor, or positions the cursor.

If Low != High, then TE_select selects all character in the text editor described by structure pointed to by te, starting from the character with offset Low up to character with offset High (counted from the begining of the text buffer). This is the operation which editor usually performs when the user uses shift + arrows. Note that you don't need to call TE_select often; usually TE_handleEvent will perform wanted job. This is only needed if you want to select a block of text in the editor independently of pressing of shift + arrows. Note that selected text will not automatically get a focus: you need to call TE_focus to achieve this.

If Low is equal to High, then TE_select positions the cursor to the position Low (counted from the begining of the text buffer).


TE_shrinkWrap

HANDLE TE_shrinkWrap (TEXT_EDIT *te);

Shrinks the text editor buffer.

TE_shrinkWrap shrinks the text editor buffer (associated with the structure pointed to by te) to the minimal possible size. After calling this function, the size of the buffer will be equal to the actual number of characters in the buffer. This function must not be applied to text buffers opened with the TE_openFixed function. TE_shrinkWrap returns the handle of the text editor buffer as the result. In addition, this function cancels selection highlight and turns off the cursor. The edit buffer memory is not freed. Use this routine to prepare the edit buffer for further processing or to be stored as a variable.

If NULL is passed as an argument, TE_shrinkWrap creates a new handle for the text editor buffer.


TE_unfocus

short TE_unfocus (TEXT_EDIT *te);

Removes the focus from the selected text in the editor.

TE_unfocus cancels the effect of TE_focus. Returns TRUE if unfocusing was performed, and returns FALSE if not (for example, if the text was already unfocused).


TE_updateCommand

void TE_updateCommand (TEXT_EDIT *te, unsigned char cmd);

Updates the command byte in the current line of the text.

TE_updateCommand sets the first byte of the current line (i.e. the line in which the cursor is located) of the text editor associated to the structure pointed to by te to cmd, i.e. sets the "command byte". This function works correctly only if the editor is opened in "command byte" mode, i.e. if if b2 = 1 in parameter Flags of the TE_open function).


TE_FAR_RIGHT

#define TE_FAR_RIGHT (0xFFFF)

A constant defining the last cursor position in TE_open.

Set the parameter cur_offset in TE_open to TE_FAR_RIGHT will place the edit cursor after the last character in the edit buffer.

See also: TE_open


ETE_FLAGS

typedef enum ETE_FLAGS {TE_WRAP = 0x0001, TE_COLON = 0x0002, TE_COMMANDS = 0x0006, TE_MORE_ARROWS = 0x0008, TE_MORE_ELLIPSES = 0x0018, TE_SELECT = 0x0020, TE_CURSOR = 0x0040, TE_FIXED_LENGTH = 0x0080, TE_CHANGED = 0x0100, TE_FOCUSED = 0x0200, TE_AUTO_ANS = 0x0400, TE_READ_ONLY = 0x0800} TE_FLAGS;

Enumerates optional features for the TE_open function.

Enumerates optional features for the TE_open function. The meaning of these flags is given in TE_open.

See also: TE_open


TEXT_EDIT

typedef struct TextEditStruct {
WINDOW *Parent; /* Pointer to the parent window */
unsigned short ReadOnly; /* Number of bytes at start that are read only */
WIN_RECT Rect; /* Editor area descriptor */
unsigned short BufSize; /* Number of currently allocated bytes */
unsigned short CurSize; /* Current number of characters in the editor */
unsigned short CursorOffset; /* Offset of the cursor */
unsigned short StartOffset; /* ScrollX, position at which text is displayed */
union {
unsigned short SelStart; /* Position of the start of the selection, if any */
unsigned short PreChars; /* Deprecated old name of SelStart */
};
unsigned short CharWidth; /* Width in characters */
unsigned short CharHeight; /* Height in characters */
unsigned short LineNum; /* Line number: cursor is on 0..CharHeight-1 */
unsigned short CursorX; /* Horizontal char position */
unsigned short Flags; /* Editor flags */
union {
HANDLE h; /* Handle of the editor buffer, if opened with TE_open */
const char *p; /* Ptr to the editor buffer, if opened with TE_openFixed */
} Text;
} TEXT_EDIT;

A structure used to coordinate all text editor operations.

Note: StartOffset is the first shown character of the entry line, but it may be covered by an arrow or ellipsis if the corresponding flag is set. SelStart is the position of the non-extensible end of the selection. This may be either the beginning or the end of the selection, depending on whether it expands to the right or to the left. Its value is undefined if there is no selection. CursorX is the horizontal character position in the line, or position relative to StartOffset.


Return to the main index