The <textedit.h> header file


  
This header file contains the following functions:
TE_checkSlack      TE_close              TE_empty           TE_focus
TE_handleEvent     TE_indicateReadOnly   TE_isBlank         TE_open
TE_openFixed       TE_pasteText          TE_reopen          TE_reopenPlain
TE_select          TE_shrinkWrap         TE_unfocus         TE_updateCommand
and the following predefined types:
Bool               EVENT                 HANDLE             SCR_RECT
size_t             TEXT_EDIT             WIN_RECT           WINDOW

Functions


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 content of the editor. All text editor operations are controled using a structure of type TEXT_EDIT. TE_open will initialize such structure pointed to by parameter te, which later need to be passed to all text editor operations. It returns TRUE if the initialization was successful, else returns FALSE.

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 actual dimensions of the rectangular text editor area. Note that if you use your own window as a parent window, this window must not be "dirty" (i.e. it must not have WF_DIRTY flag set). Windows created by WinOpen are "dirty" by default, so you need to clear "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, a result of HeapAlloc operation. Note that in contrary what I said in the documentation of TIGCCLIB releases prior to 2.2, it can not be a handle of a text variable, because text variables contain additional system data on the begining, and the editor expect a raw data (see Frequently Asked Questions to learn how you can pass a text variable to the editor however).

The content of text buffer is a standard zero-terminated string, in which lines of text are separated with '\r' character (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. Parameter cur_offset is the initial position of the cursor (counted from the begining of the buffer), and 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.

Flags is a set of binary flags which controls the editor. Some of these flags are changed automatically during the operation of the editor. As I currently know, the following bits have sense for usage in parameter Flags of this function (maybe there are more of them, but I am not sure; keep all other bits to zero): 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) and to pass them to TE_handleEvent which will process them. Such approach gives much more flexibility. See TE_handleEvent for an example of usage. See also very similar command TE_openFixed.

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, all events are dispatched to the text editor, except pressing on 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 = {};   // Global data must be initialized in "nostub" mode

void EventHandler (EVENT *ev)
{
  if (ev->Type == CM_KEYPRESS && ev->extra.Key.Code == KEY_ESC)
    ER_throwVar(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 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.

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.

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).

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.

short TE_unfocus (TEXT_EDIT *te);

Removes the focus from the selected text in the ediror.

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).

void TE_pasteText (TEXT_EDIT *te, const char *text , unsigned short 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 unusual but powerful function vcbprintf):
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 ((void(*)(char, void**))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.

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.

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).

void TE_checkSlack (TEXT_EDIT *te);

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

TE_checkSlack checks how many 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.

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 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.

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.

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.

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).

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 b11 = 1 in 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.

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).

Predefined types


enum Bool

Bool is enumerated type for describing true or false values. It is defined as
enum Bool {FALSE, TRUE};

type size_t

size_t is a type proposed in ANSI C for defining size of strings and memory blocks. It is defined here as
typedef unsigned long size_t;

type HANDLE

HANDLE is a type which represents handles associated to allocated memory blocks. It is defined as
typedef unsigned short HANDLE;

type TEXT_EDIT

TEXT_EDIT is a structure necessary to coordinate all text editor operations. It is defined as:
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
    unsigned short PreChars;     // Number of characters to display before ":"
    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;
NOTE: CursorX is the horizontal character position in the line, or position relative to StartOffset.

type EVENT

EVENT is a structure which describes an event message which is used in event driven applications. It is defined as
typedef struct EventStruct
  {
    unsigned short Type;         // ID code of the message, see EventIDs
    unsigned short RunningApp;   // Task ID of the sender of the message
    unsigned short Side;         // Side from which message is send
    unsigned short StatusFlags;  // Status line flags
    union
      { // Message-dependent extra information: see EventIDs
        WINDOW *w;
        WIN_RECT *r;
        char *pasteText;
        HANDLE hPasteText;
        struct
          {
            unsigned short Mod;  // Key modifiers (SHIFT, etc.)
            unsigned short Code; // Key code
          } Key;
      } extra;
    unsigned char StartType;     // Used only in CM_STARTTASK message
  } EVENT;

See events.h header file for more info about this structure and dispatching of event messages.

type WINDOW

WINDOW is the main window-describing structure which is used in all window-based TIOS functions. It is defied as
typedef struct WindowStruct
  {
    unsigned short Flags;      // Window flags
    unsigned char CurFont;     // Current font
    unsigned char CurAttr;     // Current attribute
    unsigned char Background;  // Current background attribute
    short TaskId;              // Task ID of owner
    short CurX, CurY;          // Current (x,y) position (relative coordinates)
    short CursorX, CursorY;    // Cursor (x,y) position
    SCR_RECT Client;           // Client region of the window (excludes border)
    SCR_RECT Window;           // Entire window region including border
    SCR_RECT Clip;             // Current clipping region
    SCR_RECT Port;             // Port region for duplicate screen
    unsigned short DupScr;     // Handle of the duplicated or saved screen area
    struct WindowStruct *Next; // Pointer to the next window in linked list
    char *Title;               // Pointer to the (optional) title
  } WINDOW;
See wingraph.h header file for more info.

type SCR_RECT

SCR_RECT is a scructure (more precise, an union) for defining a rectangular area using psysical screen coordinates. It is defined as
typedef union
  {
    struct
      {
        unsigned char x0, y0, x1, y1;
      } xy;
    unsigned long l;
  } SCR_RECT;
Instead of giving four coordinates x0, y0, x1 and y1, it is possible to give all together using a field l which is a packed long number. See graph.h and wingraph.h header files for more info.

type WIN_RECT

WIN_RECT is a scructure for defining a rectangular area using logical screen coordinates. It is defined as
typedef struct
  {
    short x0, y0, x1, y1;
  } WIN_RECT;
NOTE: TIGCC is a GNU C, so it allows cast constructors. That's why, constructions like
TE_open (&te, DeskTop, &(WIN_RECT){30, 30, 130, 70}, h, 0, 0 3);
are legal (see TE_open). See also graph.h and wingraph.h header files for more info.

Return to the main index