Routines to access the text editor
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.
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).
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_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_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 cannot 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.
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.
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).
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_WRAP | Set 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_COLON | When 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_COMMANDS | When 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_ARROWS | Set 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_ELLIPSES | Set 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_SELECT | This 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_CURSOR | This 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_LENGTH | This flag is an internal flag. It is set for text editors opened with TE_openFixed. Do not set this flag. |
TE_CHANGED | This 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_FOCUSED | This 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_ANS | Set 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_ONLY | When 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. |
See also: 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 cannot 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
cannot 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_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.
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_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).
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.
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).
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).
#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
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
typedef struct TextEditStruct {
|
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.