Routines for event-driven programming and for mode settings
Note: Event-related functions are intended mainly for
flash applications, although some of them may be useful even in user programs.
Anyway, they are intended for serious programmers, not for beginners.
Don't try to make an event-driven application if you don't understand this file really well!
If your program uses functions from this header file, you may have to
define SET_FILE_IN_USE_BIT
.
void ABT_dialog (void); |
Starts "ABOUT" dialog "applet".
The "ABOUT" dialog is an event driven "applet", which works exactly like "CATALOG" dialog applet.
See CAT_dialog for more info about event driven dialogs.
Note: If your program uses this function, you have to
define SET_FILE_IN_USE_BIT
.
void CAT_dialog (void); |
Starts "CATALOG" dialog "applet".
The "CATALOG" dialog is an event driven "applet". CAT_dialog draws the dialog on the screen, installs its own event handler, then exits (without stopping the caller program). It does not enter into a loop (like normal dialogs do) which ends only on pressing ENTER or ESC. Its event handler restores the previously installed handler after the user presses ENTER or ESC, but if the pressed key was the ENTER key, the selected command from the catalog is send as a CM_STRING message after restoring the user handler (which need to be captured via user event handler). That's why it is not so easy to use CAT_dialog in user programs, but this is also not very hard. Here is an example, which opens the "CATALOG" dialog, and displays in the help screen a message which tells what the user selected from the catalog (called "Catalog"):
// Display the catalog and let the user select something #define USE_TI89 // Compile for TI-89 #define USE_TI92PLUS // Compile for TI-92 Plus #define USE_V200 // Compile for V200 #define OPTIMIZE_ROM_CALLS // Use ROM Call Optimization #define MIN_AMS 100 // Compile for AMS 1.00 or higher #include <tigcclib.h> // Include All Header Files const char *ptr; HANDLE handle; CALLBACK void Handler(EVENT *ev) { if (ev->Type == CM_STRING) ptr = ev->extra.pasteText; else if (ev->Type == CM_HSTRING) handle = ev->extra.hPasteText; ER_throw (1); } void _main(void) { EVENT ev; char buffer[100]; ptr = NULL; handle = H_NULL; EV_captureEvents (Handler); CAT_dialog (); TRY EV_eventLoop (); ONERR EV_captureEvents (NULL); ENDTRY if (handle != H_NULL) ptr = HLock (handle); if (ptr != NULL) { sprintf (buffer, "You selected \"%s\".", ptr); ST_helpMsg (buffer); } else ST_helpMsg ("You pressed ESC."); if (handle != H_NULL) HeapFree (handle); ev.Type = CM_UNFOCUS; // This is more due to some EV_sendEvent (AP_CURRENT, &ev); // aesthetical reasons }
Note that it is important that EV_captureEvents must be called
before calling CAT_dialog. This example is a good test whether you understand the principles of
event handling or not.
Note: If your program uses this function, you have to
define SET_FILE_IN_USE_BIT
.
EVENT_HANDLER EV_captureEvents (EVENT_HANDLER NewHandler); |
Sets the event message handler (i.e. installs an event driven application).
EV_captureEvents sets a new event message handler to the routine pointed to by NewHandler,
overriding any current handler. NewHandler is the pointer of type EVENT_HANDLER,
which is the pointer to a void function (i.e. procedure) which accepts one parameter of
EVENT type. If NewHandler is NULL,
EV_captureEvents restores the standard event handler (which depends on the current application
like "Home Screen", "Graph", etc.). EV_captureEvents returns the pointer to the previous installed
event handler.
Any event handler is, in fact, an event driven application. All built-in flash applications like
"Home screen", "Graph", "Text editor", "Geometry" etc. and all add-in flash applications are event driven applications. Also,
"About" and "Catalog" dialogs and "Error message" dialogs are also event driven applications
(maybe the word "applets" is better for them). The whole idea of event driving is as follows:
instead of having an application which has an internal "main loop" in which all processing are
performed, an event driven application accepts a message (or event), checks the type of the
event (a keypress is, for example, one type of the event), process it, then exits immediately
after processing the event. So, the user needs to make a loop in which necessary events are
collected and dispatched (using EV_sendEvent) to the application.
The main advantage of such an approach is in the fact that the main loop is under the control of
the user, even if the application itself may be written by somebody else. So, the user can
decide in the loop what events will be sent to an application etc. This would not be possible
if the "main loop" is the part of the application itself. For example, if the user makes a
loop in which events are dispatched to two or more applications, it is easy to estabilish a
kind of multitasking. Note that each modern operating system (for example Windows or UNIX) is
based on such event dispatching/handling mechanism!
To understand more about event driven applications, you need to read about all other
functions in this header file (especially EV_eventLoop,
EV_sendEvent and EV_defaultHandler
may be very useful in user programs). Probably the most frequent usage of these functions in
user programs will be to access the text editor
application (see textedit.h header file), which is event driven.
In this header file, there is also a good example about using some event functions.
Note: If you want to "hook" on the existing event handler instead to complete overriding the
current handler, it is better to use EV_hook.
void EV_centralDispatcher (void); |
Enters the main controlling loop of the TIOS.
As the name suggests this is the main controlling loop of the entire TIOS. This
functions initializes all installed applications by sending CM_INIT
event to them, starts the "Home screen" application, then calls EV_eventLoop
under an error handler, so if any error appeared during execution of the event loop, it will
be catched by the error handler, which will first dispatch the error code to
ERD_process then restart the event loop.
Note: As far as I know, there is no any need to call this function from your program. This
will enter the endless loop, which can not be broken even by throwing an error from the
event handler (the method used to exit from EV_eventLoop), because
the event loop is now executed under the internal error handler (maybe the only method to exit
from such loop is using longjmp from the event handler, but
I don't believe that such barbaric method would leave the system in a stable state).
void EV_clearPasteString (void); |
Clears the event paste buffer.
EV_clearPasteString clears event paste buffer, i.e. clears the static pointer to the paste buffer (see default action for CM_STRING message in EV_defaultHandler), and eventually frees the memory occupied for dynamically pasted string (sent via CM_HSTRING message).
void EV_defaultHandler (EVENT *event); |
Processes an event message using the default handler.
EV_defaultHandler performs some default actions with most common messages (event is the
pointer to the message which need to be processed). This function is very useful in user event
handlers, and it is often called to process any unhandled messages in handlers. Not all
messages are supported in EV_defaultHandler. This is a list of supported message types (unsupported
types are simply ignored) together with the description of the action performed by EV_defaultHandler:
CM_ACTIVATE | Registers and starts the menu for the running application (see EV_registerMenu). |
CM_DEACTIVATE | Ends custom and normal menus. |
CM_KEY_PRESS | Handles tokens, system and mode keys. This is maybe the most useful action performed by EV_defaultHandler. If the keypress is a simple key (i.e. a single character), nothing will happen. If the keypress is a token (like "sin", "ln" etc.), the appropriate string is sent (as a CM_PASTE_STRING message) to the application. The summary effects will be that the application will receive token as a sequence of single keypresses. So, tokens are all sent via EV_sendString and do not have to be processed as single keypresses (note that this will not cause problems if called from user event handlers, although it may cause recursion; see textedit.h header file for an useful example). If the keypress is system or mode key (see QSysKey and QModeKey), the corresponding action associated with the key (for example, opening a menu or a dialog) will be performed (see the example below this table). The chosen menu item is then sent as a CM_PASTE_STRING message to the current application (note however that VAR-LINK uses a CM_PASTE_HANDLE message instead), except for toolbar menus, where an appropriate menu ID is send as a message. Command keypresses STO, RCL, SWITCH, MODE, APPS, MEM, INS, CUT, PASTE etc. and OFF key (code 4363) are also handled via this handler, and all of them cause usual actions (keypresses like CUT, PASTE etc. only send an appropriate message to the application). |
CM_PASTE_STRING | Pastes the string in the event paste buffer. More precise, it sets an internal static pointer to points to event->extra.pasteText and does not nothing more. The event loop (see EV_eventLoop) will then send the string as individual keypresses to the current application. This means that the paste buffer is exported from the code, so this allows pasting large amounts of text. |
CM_PASTE_HANDLE | Frees the memory associated with handle event->extra.hPasteText. |
CM_STO | Sends CM_KEY_PRESS event filled with key code 22 (right arrow) to the current application. |
CM_RCL | Performs usual actions for the RCL key (open Recall dialog, etc.). After execution of the Recall dialog, the content of the variable is sent to the current application as a CM_PASTE_STRING message. |
EVENT ev; ... ev.Type = CM_KEY_PRESS; ev.extra.Key.Code = KEY_CHAR; EV_defaultHandler (&ev);
After execution of the menu, the selected character will be sent as the event to the current application (it may be captured through an user event handler).
void EV_eventLoop (void); |
Enters the loop in which main event messages are collected and dispatched.
EV_eventLoop enters the (endless) loop in which main events are collected and dispatched to
the current application. In the normal operation of the calculator (i.e. when no user
program is running), the TIOS is just in this loop. Calling this function in the user program
makes sense (and may be very useful if you are happy with set of events which are processed in
this function) only if the program installs a custom event handler using
EV_captureEvents function, so the events may be trapped by
the user program.
Here is the exact description what happens in the each iteration of this loop (not in
exact order, but this is not important):
If there are no activities (keypresses etc.) for a long time, and if the timer APD_TIMER expires (see OSRegisterTimer), the calculator is turned off.
If a key is pressed, the event CM_KEYPRESS is send (using EV_sendEvent) to the current application. Note if the current application is "Home screen", this may cause evaluation of the input line (if the pressed key was ENTER key), including execution of user programs, etc. This may also cause changing of the current application (for example, if the user pressed APPS key).
If there is a string in the event paste buffer (see EV_sendString), the content of the buffer is processed exactly as if all codes in the buffer are typed from the keyboard (i.e. a sequence of CM_KEYPRESS events are send to the current application).
If there is no keypress, if the cursor is enabled (see CU_start) and if CURSOR_TIMER expires (see OSRegisterTimer), CM_BLINK event is send to the current application.
If a global variable which contains the error code is non-zero, an error dialog is displayed (using ERD_dialog).
If there are twin symbols (see SymAddTwin) in the VAT table, they are deleted. This performs cleaning up the RAM after executing of archived programs.
If painting is enabled (see EV_suspendPainting and EV_restorePainting), event CM_WPAINT is send using EV_paintOneWindow function.
If there are no other activities, CM_IDLE event is send to the current application, and the function idle is called.
Note that when an user ASM program is started, the current application is always "Home screen",
until the user changes the current application using EV_startApp or
installs thier own event driven "task" using EV_captureEvents.
So, if you simply call EV_eventLoop in the your program, without previous usage of
EV_captureEvents or EV_startApp,
you will have an illusion that you are not in the your program but in the home screen, because
all collected events will be dispatched to the "Home screen" application. Note that in this
case, there is no way to exit this loop, and your program will stay "resident" and
"locked" in the memory forever, although you will not be aware of the fact that your program
is still "running" - you will be able to execute everything,
including running other programs etc.
As EV_eventLoop enters the endless loop, the only method (and this is the proposed method in
TIOS) to exit the loop is to throw an error from the user event handler installed using
EV_captureEvents. This is possible because in the event loop
there are no error handlers in place, so ER_throw passes
control to the previous level of error handler. In terms of normal operation (i.e. while you
are typing in the home screen) this is handled
by EV_centralDispatcher, which restarts the event loop.
However, in custom event handling it is used to return from the event loop to the calling code.
To achieve this, you need to catch errors using ER_catch
or using TRY...ONERR...ENDTRY
construction. So, the typical usage of EV_eventLoop function in user programs is:
EV_captureEvents (UserHandler); TRY EV_eventLoop (); // The only way to exit from this is ONERR // to throw an error from the event handler! EV_captureEvents (NULL); ENDTRY
Of course, user handler must decide what to do with events dispatched by EV_eventLoop. Very nice example of usage of this methodology is given in textedit.h header file. Another example may be found with the description of CAT_dialog function. These principles are used often in the TIOS. For example, error dialogs are principally implemented as follows (although there are no obvious reasons why events are used in this example):
void ERD_EventHandler(EVENT *ev) { if (ev->Type == CM_KEYPRESS) switch (ev->Key.Code) { case KEY_ENTER: ER_throw (1); // Exit from event loop: ENTER key pressed case KEY_ESC: ER_throw (2); // Another exit: ESC key pressed case KEY_OFF: EV_defaultHandler (ev); // OFF key pressed: allow the machine to be switched off } } short ERD_dialog(short err_no, short prog_flag) { EV_captureEvents (ERD_EventHandler); // Display the dialog TRY EV_eventLoop(); ONERR switch(errCode) { case 1: // Restore the screen and return KEY_ENTER code case 2: // Restore the screen and return KEY_ESC code } ENDTRY }
To exit from EV_eventLoop, the best idea is to throw error codes less than 8, as they are never used as error codes in normal error handling.
short EV_getAppID (const char *TaskName); |
Finds a task ID number for an application.
EV_getAppID returns a task ID number for the task/application whose internal name is
TaskName, or returns -1 if the application is not found.
Each application (including both built-in applications and external
Flash applications) has a unique internal name (max. 8 characters). This function
is introduced for compatibility with all AMS versions, because
task ID numbers are inconsistent between AMS versions. On AMS 1.xx, built-in flash
applications have fixed ID numbers attached to them, but on AMS 2.xx the task ID is
simply the handle of the application control block (this is why it is quite hard to
add flash applications on AMS 1.xx). So, always use EV_getAppID to determine the
task ID number for an application. Internal names of built-in applications are given
in the following table:
Application name | Internal name |
Home screen | TIHOME |
Y=Editor | TIEQUED |
Window Editor | TIWINDED |
Graph | TIGRAPH |
Table | TITABLED |
Data/Matrix Editor | TIDMED |
Program Editor | TIPRGMED |
Text Editor | TITEXTED |
Numeric Solver | TIINSLVR |
Self Test | TISLFTST |
unsigned short EV_getc (unsigned short busy, EVENT *event); |
Waits for the keypress, then fills an event structure with the keypress.
EV_getc is a function similar like ngetchx. It waits for
a keypress, and returns the keycode of the keypress. But, in addition to
ngetchx, it also fills the structure pointed to by event
with appropriate CM_KEYPRESS event. Parameter busy
may be ACTIVITY_IDLE, ACTIVITY_BUSY, ACTIVITY_PAUSED or ACTIVITY_NORMAL (these
constants are defined in enum ST_ACTIVITIES). This
parameter determines the indicator in the status line which will be displayed
(see ST_busy for more info).
If there is no keypress and the cursor timer expires (cca 0.5 seconds), the
message CM_BLINK is stored in the event structure
instead, and the function returns zero (no keypresses). Also, this routine
puts the calculator into low power mode until a character is available,
and it will automatically power down the calculator if a key has not
been pressed after a few minutes.
WIN_RECT *EV_getSplitRect (unsigned short Side); |
Gets the screen rectangle for a given side.
EV_getSplitRect consults various calculator mode settings ("Split Screen": "FULL", "LEFT-RIGHT" or "TOP-BOTTOM" and "Split Aspect Ratio": "1:1", "1:2" or "2:1") to determine dimensions of the rectangular area in which the application will be executed. Parameter Side determines wanted side, and it needs to be 0 or 1 (0=left or top side, 1=right or bottom side). EV_getSplitRect returns the static pointer to the WIN_RECT structure which describes the determined rectangular area.
void EV_notifySwitchGraph (void); |
Notify appropriate applications of graph switching.
EV_notifySwitchGraph does nothing if the calculator is not in "two-graph" mode, else sends CM_SWITCH_GRAPH message to "Graph", "Window Editor", "Table" and "Y= Editor" applications (these applications are the so-called "multigraph" applications).
short EV_paintOneWindow (void); |
Repaints the topmost window.
EV_paintOneWindows searches through a linked list of windows (see
wingraph.h header file) for the first window
which has WF_DIRTY flag set. If the found window
is visible (i.e. if WF_VISIBLE flag is set), the
CM_WPAINT message is sent to the application which
is the owner of the window (note that WinOpen
stores the task ID of the current application in TaskID field of the
WINDOW structure). See also notes about
EV_sendEvent. After sending this message,
WF_DIRTY flag of the window is cleared, and this flag is
set in all other windows in the linked list of windows which overlap with this
window (because repainting of this window may cause trashing of another windows).
EV_paintOneWindow returns TRUE if the window was "painted"
(more precise, if CM_WPAINT message is sent), otherwise it
returns FALSE (i.e. if none to paint).
Here is an example which ilustrates that painting of all TIOS windows is "event
driven". Suppose that you make very simplified loop which "simulates" normal behaviour
of the calculator when it is in the home screen:
while (TRUE) { EV_getc (ACTIVITY_NORMAL, &ev); EV_sendEvent (AP_CURRENT, &ev); }
If you try this program, you will notice that although you can type in statements, execute user programs etc. from this loop, nothing happens on the screen when you type in 2 + 3 <ENTER> (i.e. result 5 is not displayed). This is because the "Home screen" application didn't receive a message which forces redrawing of the Home screen. You can see that everything will be correct if you make the following loop:
while (TRUE) { EV_getc (ACTIVITY_NORMAL, &ev); EV_sendEvent (AP_CURRENT, &ev); EV_paintOneWindow (); }
void EV_paintWindows (void); |
Repaints all windows.
If painting is enabled (see EV_suspendPainting), EV_paintWindows repeatedly calls EV_paintOneWindow until it returns FALSE (no more to paint). So, the effect will be "repainting" of all "dirty" windows.
void EV_registerMenu (void *MenuPtr); |
Attaches a menu to an application.
Applications can register toolbar menus with the system event handler. EV_registerMenu
registers the toolbar menu pointed to by MenuPtr with the current application.
MenuPtr is exactly the same pointer as expected in MenuBegin
function. Note that registering the menu will not automatically display nor activate the menu.
The application will draw the menu (using MenuBegin) on
receipt of CM_ACTIVATE message. So if you, for example, attach a new
menu to the "Home screen" application, you need to send CM_ACTIVATE
message to it too. Also, before calling EV_registerMenu, a CM_DEACTIVATE
message should to be sent to the application.
When a menu is attached to the application, each keypress event (a CM_KEYPRESS
message) which represents keys F1, F2 etc. activates the menu (more precise, it is dispatched
to the MenuKey function). After execution of
MenuKey, the value returned from it (this is the ID
of the selected item, see MenuAddText) is sent as an event
to the application. So, the ID value for each menu item must be carefully planned: if you
want to have the "Cut" option in the menu, its ID needs to be 0x720
(CM_MENU_CUT). Options which represent tokens (as in "Algebra" and
"Calc" submenus) have ID less than 0x500, because tokens are send as XR strings
(see XR_stringPtr). If you plan to create a serious
event driven application which has toolbar menus (a flash application for example), it must
behave in the same way (i.e. its event handler must process F-key events as described), and
it must respond on CM_ACTIVATE message as described above. Of course, how to
put an application in Flash ROM without TI certificate and TI professional SDK is greater
problem...
To restore the original menu after termination of the program, you need to
get a pointer to the original menu first, and before termination, you have to
call EV_registerMenu again passing this pointer to it. The pointer can be
obtained by calling OO_GetAppAttr
like this:
void *oldmenu = OO_GetAppAttr (EV_runningApp, OO_APP_DEFAULT_MENU);
Note: Sending NULL to EV_registerMenu unattaches the toolbar menu from the application. Here is a dirty example which first removes the menu from the "Home screen" application, then changes parameters of "Home screen" parent window to expand the "Home screen" stack area into the menu area (but note that only a reset would restore the original state after execution of this program):
EVENT ev; ev.Type = CM_DEACTIVATE; EV_sendEvent (AP_CURRENT, &ev); EV_registerMenu (NULL); ev.Type = CM_ACTIVATE; EV_sendEvent (AP_CURRENT, &ev); FirstWindow->Client.xy.y0 = 0; FirstWindow->Window.xy.y0 = 0; FirstWindow->Clip.xy.y0 = 0;
short EV_restorePainting (short blockPaint); |
Restores previous state of window painting.
EV_restorePainting suspends or enables window painting, depending on whether blockPaint is PAINTING_ENABLED or PAINTING_SUSPENDED (these constants are defined in enum PaintFlags). The main purpose of this function is to restore previous state after usage of EV_suspendPainting function. EV_restorePainting also returns previous state of painting enable flag (PAINTING_ENABLED or PAINTING_SUSPENDED) before calling this function.
void EV_sendEvent (short TaskID, EVENT *event); |
Sends an event message from the current side.
EV_sendEvent sends the event message described in the structure pointed to by event
to the task/application with ID number TaskID (see below for more info about task
IDs). Note that the user needs to pre-fill only Type field of the event structure
and eventually extra field (if the message has extra information attached). All
other fields will be filled by EV_sendEvent function before sending the message.
The Type field of the event structure is interpreted as following:
If Type >=0x700, the message is an event command message (like CM_KEYPRESS, CM_WPAINT, etc. These codes are defined in enum EventIDs. These messages are the most common messages, and such messages are the most usable messages in user applications. See EventIDs for detailed description of the meaning of such messages.
If 0x500 <=Type < 0x700, the message is a custom command message. The interpretation of such messages is strictly task-dependent. The TIOS uses such messages in dialogs, etc.
If Type < 0x500, XR_string (see XR_stringPtr) is sent as the message. This is used for internal purposes in TIOS.
Here is the description what EV_sendEvent exactly does:
If EV_hook pointer is not NULL, then a routine pointed to by it is called, passing event to it.
If there is an user event handler installed (using EV_captureEvents), the user handler is called, and event is passed to it. In this case, parameter TaskID is ignored. The only exception is when the message is CM_WPAINT. In this case, the user handler is called only if TaskID is AP_NULL.
If there is no user event handler installed, the message event is sent to the default application-dependent event handler, which is determined by parameter TaskID. Note that default application-dependent event handler will not be called if there is an user event handler installed. The exception is when the message is CM_WPAINT. This message is always dispatched to the default application-dependent handler, except if TaskID is AP_NULL.
Note that task ID numbers are inconsistent between AMS versions, so always call
EV_getAppID before to determine an appropriate task ID,
or use special task IDs AP_CURRENT,
AP_RUNNING and AP_NONE,
which are AMS-independent.
If you want to send an event from the user event handler, you can enter into
an infinite recursion. Here is an example how to avoid this. The following program will
change the behaviour of the ENTER key to behave like pressing DIAMOND+ENTER.
So, run the following program (called "Approximation Mode"). After this, the ENTER key
will behave like DIAMOND+ENTER
(note that the program is "resident": it is active for whole time, although you have
feeling that you are in "Home screen" for example). The ENTER key will remain redefined
until the user press DIAMOND+ENTER. After this, the original function of the ENTER key
is restored, and the program finishes working.
// Run Home Screen in approximation mode #define USE_TI89 // Compile for TI-89 #define USE_TI92PLUS // Compile for TI-92 Plus #define USE_V200 // Compile for V200 #define OPTIMIZE_ROM_CALLS // Use ROM Call Optimization #define MIN_AMS 100 // Compile for AMS 1.00 or higher #define SAVE_SCREEN // Save/Restore LCD Contents #include <tigcclib.h> // Include All Header Files volatile EVENT_HANDLER Old_Handler; CALLBACK void Handler(EVENT *ev) { if (ev->Type == CM_KEYPRESS) { if (ev->extra.Key.Code == KEY_DIAMOND + KEY_ENTER) ER_throw (1); if (ev->extra.Key.Code == KEY_ENTER) ev->extra.Key.Code = KEY_DIAMOND + KEY_ENTER; } /* Send the event to the default application handler, but be careful to avoid infinite recursion! */ EV_captureEvents (Old_Handler); EV_sendEvent (AP_CURRENT, ev); Old_Handler = EV_captureEvents (Handler); } void _main(void) { Old_Handler = EV_captureEvents (Handler); TRY EV_eventLoop (); ONERR EV_captureEvents (Old_Handler); ENDTRY }
Of course, this program is not extremely useful: the much easier method to achieve the same
functionality is to set the calculator to "APPROX" mode. But, note that this is just an
example, which should give you an idea how to redefine the keyboard.
Note: The destination application does not have to be started or active to receive
messages. You should first start the application using EV_startApp
if it is important that the application be on the screen before it receives an event.
void EV_sendEventSide (short TaskID, EVENT *event, unsigned short Side); |
Sends an event message from the given side.
EV_sendEventSide is very similar to EV_sendEvent. The only difference is in the fact that EV_sendEventSide fills the field Side of the event structure with the value of parameter Side. EV_sendEvent fills this field with the current side number (0=left or top side, 1 = right or bottom side). This field allows the message handler to determine which side (of course, in split screen mode) the message is sent from, so it allows a primitive kind of multitasking.
void EV_sendString (unsigned short XR_String); |
Sends XR string to the running application.
EV_sendString is an internal function which sends the XR string (see XR_stringPtr) to the running application via a CM_STRING message. XR_String is the code of the XR string which will be sent.
void EV_setCmdCheck (unsigned short ID, short State); |
Checks/unchecks a menu item in the current application.
This function sets or clears the check mark on a menu item in the current
application. It is related to MenuCheck
from the menus.h header file.
EV_setCmdCheck checks or unchecks the item with the specified ID
(see EV_registerMenu).
State should be one of the following values as defined in the
MenuCheckCmds enum:
MC_CHECK | Display a check mark next to the menu item. |
MC_UNCHECK | AMS 2.00 or higher: Remove the check mark. |
MC_FLIP | Invert the status of the check mark. |
void EV_setCmdState (unsigned short cmd, short State); |
Changes the status (active/inactive) of a menu command in the current application.
EV_setCmdState is similar to EV_setFKeyState, but works with command pulldown menus associated with the main toolbar menu which belongs to the current application. EV_setCmdState changes the status of the command item which has its ret_val (see EV_registerMenu) equal to the cmd. For example, if you execute
EV_setCmdState (CM_MENU_CUT, FALSE);
in your program, you will see that the "Cut" command in the "Home screen" menu will be disabled (note that "Home screen" is the current application if you didn't use EV_startApp in your program). CM_MENU_CUT is, of course, the code of the "Cut" menu command.
See also: MenuSubStat
void EV_setFKeyState (unsigned short Item, short State, short Redraw); |
Changes the status (active/inactive) of a toolbox in the menu associated with current application.
EV_setFKeyState changes the status of the toolbox Item (0 = first, 1 = second
etc.) which belongs to the menu associated with the current application
(see also MenuTopStat).
State is a Boolean value: when it is TRUE, the toolbox will be
active, and when it is FALSE, the toolbox will be inactive (i.e. it will be
dimmed, and it can not be selected).
EV_setFKeyState can also force redrawing of the menu after changing state: to do this,
set Boolean parameter Redraw to TRUE.
Avoid menu redraw flicker when enabling/disabling several
function keys by specifying FALSE for redraw in all but the
last call to this routine.
See also: MenuTopStat
void EV_startApp (HANDLE TaskID, unsigned short StartType); |
Starts an application from any state.
EV_startApp is dedicated to "start the application". It changes current application to
TaskID and sends a sequence of messages to it (how they will be interpreted
depends on the concrete application), so this command may be used for changing the
current application.
It is not likely that following information will be very useful for you (except if
you are an expert who wants to make a new high perfomance flash application), but anyway
here is the pseudo-code which describes what exactly EV_startApp does:
if TaskID is equal to the current application if StartType is AP_START_CURRENT send CM_START_CURRENT to the current application else {change task} send CM_UNFOCUS, CM_DEACTIVATE and CM_ENDTASK to the current application call EV_startTask, passing StartTask to it send CM_ACTIVATE and CM_FOCUS to the current application endif else {new application} send CM_UNFOCUS and CM_DEACTIVATE to the current application if TaskID is equal to the application on the other side and if the calculator is in "two-graph" mode or TaskID is not "Graph", "Window Editor", "Table" nor "Y= Editor" set current application to TaskID invert current side call EV_notifySwitchGraph if StartType is not AP_START_CURRENT send CM_ENDTASK to the new application call EV_startTask, passing StartTask to it endif else send CM_ENDTASK to the current application set current application to TaskID call EV_startTask, passing StartTask to it endif send CM_ACTIVATE and CM_FOCUS to the new application endif
Under normal circumstances, you should start another application with
StartType set to AP_START_CURRENT.
Note: Task ID numbers are inconsistent between AMS versions (see EV_getAppID for
more info). So, if you, for example, want to start the "Numeric Solver" application, the AMS-independent
way to do this is
EV_startApp (EV_getAppID ("TIINSLVR"), AP_START_CURRENT);
Also, some common applications (like "Graph", "Table" or "Home screen") may be started safely using some commands from bascmd.h header file.
void EV_startSide (short *saveTaskID, HANDLE TaskID, unsigned short Side); |
Starts the given side.
EV_startSide first sends CM_STARTTASK message to the application with ID number TaskID. Field StartType of the event structure will be set to AP_START_CURRENT, and field r (in extra field) of the event structure will be filled from the result of executing EV_getSplitRect function (with Side given to it as the parameter). See EV_startTask. This is all if the current side is not equal to Side, else messages CM_ACTIVATE and CM_FOCUS will also be sent to the task TaskID and side Side (using EV_sendEventSide). EV_startSide also fills the variable pointed to by saveTaskID with TaskID (I don't know what the purpose of this is).
See also: EV_startApp
void EV_startTask (unsigned short StartType); |
Starts a particular task in the running application.
EV_startTask sends CM_STARTTASK message to the running application. Field StartType of the event structure will be filled from StartType parameter of this function (this is the only message in which StartType field is significant). Field r (in extra field) of the event structure will be filled from the result of executing EV_getSplitRect function (with current side given to it as the parameter). How StartType will be interpreted depends on the concrete application. Usually, three types of "starting" are supported: AP_START_CURRENT, AP_START_NEW and AP_START_OPEN (these constants are defined in enum StartTypes. For example, Text and Data/Matrix editor may be started in three submodes: "Current", "Open" and "New". Under normal circumstances, you should start another task with AP_START_CURRENT.
short EV_suspendPainting (void); |
Suspends window painting.
EV_suspendPainting sets a flag which indicates that window painting is suspended (see EV_eventLoop and EV_paintWindows). Returns PAINTING_ENABLED or PAINTING_SUSPENDED depending on whether painting was enabled or disabled before calling this function (these constants are defined in enum PaintFlags), so the returned value may be later used in the EV_restorePainting function.
void EV_switch (void); |
Performs switching of sides.
EV_switch performs side switching. It does nothing if the current "Split Screen" mode is "FULL".
Else, it sends CM_UNFOCUS and CM_DEACTIVATE messages,
inverts current side, sets the current application to the application on the other side, calls
EV_notifySwitchGraph, and finally, sends
CM_ACTIVATE and CM_FOCUS messages to the
new application.
Note: In AMS 2.xx, this function is extended to allow switching between the current application
and the application which last ran before the current application.
void handleRclKey (short CRstatus); |
Displays the standard "Recall Variable" dialog.
handleRclKey is the default handler for the 'RCL' key (called from
EV_defaultHandler when processing
a CM_RECALL message).
A pop-up dialog box is displayed requesting the name of a variable. The
contents of the variable are converted to text and pasted to the current
application as a CM_HSTRING message. Nothing is
pasted if the user pressed 'ESC' to cancel the dialog.
CRstatus is a boolean parameter. If it is
TRUE, carriage returns are converted to
colons after the contents of the variable have been converted to text. The
variable itself is not changed. If it is
FALSE, carriage returns remain unchanged.
Note: This function may cause heap compression and may throw errors.
See also: handleVarLinkKey
void handleVarLinkKey (short type); |
Displays the standard "Var-Link" dialog.
handleVarLinkKey shows the "Var-Link" screen and allows the user to select a
variable of type type. Valid values for type are described in the
enum SystemDataTypes. In addition to those,
you can OR type with 0x8000 to forbid the user to change (i.e. delete, copy,
rename, etc.) any variables. The name of any variable or folder selected is
sent back to the currently active application as a
CM_HSTRING message.
This routine may cause heap compression.
See also: handleRclKey, GetDataType, SmapTypeStrings
void MO_currentOptions (void); |
Fills in options structure from current mode settings.
MO_currentOptions fills the structure pointed to by ModeSettings and MO_option from current mode settings. It should always be called before using MO_digestOptions.
void MO_defaults (void); |
Sets default mode settings.
MO_defaults resets options structure (i.e. fills the structure pointed to by ModeSettings and MO_option with default settings), then calls MO_digestOptions to dispatch these settings to applications.
void MO_digestOptions (short Folder); |
Updates system mode settings from options structure.
MO_digestOptions "digests" options from the ModeSettings
structure (in other words, the MO_option array)
into the various TIOS system variables. It should be called after each change of the options
structure to notify the calculator about changes. This routine may change the status line
indicators. It also notifies all applications about eventual changes, if there was any
essential changes (using MO_notifyModeChange). If new
mode settings need a change of current application or side, it may also quit an application
(see MO_sendQuit), switch sides, start a new applications/tasks
etc. which in fact means sending a sequence of messages to applications (see
EV_startApp etc.).
Parameter Folder is the index (ordinal number) of the current folder in the folder
list. Under normal conditions, you should always pass zero to this parameter. The mode dialog
box calls MO_digestOptions with non-zero argument to indicate which folder name is highlighted
in the "Current Folder" popup menu.
short MO_isMultigraphTask (short TaskID); |
Checks whether a task is multigraph task.
MO_isMultigraphTask returns TRUE if the task with ID number TaskID is "Y= Editor", "Window Editor", "Graph" or "Table" (these tasks are tasks which may be doubled in two different part of the screen), otherwise it returns FALSE.
void MO_modeDialog (void); |
Executes "MODE" dialog.
MO_modeDialog opens the "MODE" dialog, and allows the user to set mode options. If the user pressed ENTER key, MO_digestOptions will be called to "digest" new settings to TIOS. If the user pressed ESC key, nothing will happen. In each case, the dialog will be removed from the screen after pressing ENTER or ESC.
void MO_notifyModeChange (short Flags); |
Sends mode change notify message to all applications.
MO_notifyModeChange sends a CM_MODE_CHANGE message to all
applications (note that the "Graph" application will receive this message first). This function
also has a parameter Flags, which contains a set of flags which describes what exactly
was changed. This parameter is attached to message in the extra field of the message, so it
gives more information to applications on what they need to check.
The flags can be one of the following as enumerated in MoNotifyFlags:
MO_NOTIFY_FOLDER | The current folder has changed. |
MO_NOTIFY_GRAPH_COUNT | 2 graph mode or 1 graph mode. |
MO_NOTIFY_GRAPH_TYPE_1 | Graph mode change. |
MO_NOTIFY_GRAPH_TYPE_2 | Graph mode change for graph 2 if in 2 graph mode. |
MO_NOTIFY_SPLIT | The screen size has changed. |
MO_NOTIFY_ANGLE | The angle mode has changed. |
MO_NOTIFY_PRECISION | The precision has changed between EXACT, APPROX and AUTO. |
MO_NOTIFY_FIX | Fix digits or float precision change. |
MO_NOTIFY_NUMBER_FORMAT | Exponential format: Normal, scientific or engineering. |
MO_NOTIFY_VECTOR_FORMAT | Rectangular, cylindrical or spherical. |
MO_NOTIFY_COMPLEX_FORMAT | Real, rectangular or polar. |
MO_NOTIFY_PRETTY_PRINT | Pretty Print has been switched on or off. |
MO_NOTIFY_UNIT_SYSTEM | SI, ENG/US or CUSTOM unit system. |
MO_NOTIFY_BASE | DEC, HEX or BIN base. |
MO_NOTIFY_LANGUAGE | AMS 2.00 or higher: The language mode has changed. |
MO_NOTIFY_DESKTOP | AMS 2.07 or higher: The Apps Desktop has been switched on or off. |
void MO_sendQuit (short TaskID, short Side); |
Quits an application on given side.
MO_sendQuit quits an application on side Side (0=left/top, 1 = right/bottom).
This is what pressing of the QUIT key does.
More precise, if Side is equal to the current side, the side will receive
CM_UNFOCUS and CM_DEACTIVATE messages.
After this, the application will receive CM_ENDTASK message.
Finally, the application on side Side will be set to CM_NULL.
If the application on side Side is already CM_NULL,
nothing will be performed.
Note: If you don't understand what "quitting" means, try MO_sendQuit(AP_CURRENT, 0) from
your program to "quit" the "Home screen" application.
You will notice that the menu will dissappear. Later, executing commands will not show results
in the home screen, because "repainting" of the "Home screen" window will be suspended
(the application is set to CM_NULL).
EVENT_HANDLER EV_hook; |
A global variable pointing to the "hook" event handler.
EV_hook is a global pointer variable which points to the "hook" event handler (or
NULL if there is no "hook" handler installed. Hook handler hooks
events like EV_captureEvents, however, the application
handler (either default application handler or user handler installed with
EV_captureEvents) is still called afterwards (see
EV_sendEvent for more info. This is probably meant for
debugging purposes as it is never used in TIOS.
Using EV_hook you can capture all messages and process them as you like, without
overriding current handlers. So, you can use it to change behaviour of some events,
or add new functionalities. DoorsOS for example uses EV_hook to add SHIFT+ON feature.
You also can hook the APPS key and display a different menu in which your application
set will be listed (then you can start your own event driven application via
EV_captureEvents). If you understand principles
described in this header file, this is not so hard. If you didn't understand what
is written here, don't try to play with this...
unsigned short *const MO_option; |
Contains a pointer to the global mode settings array.
MO_option is a constant pointer to an array of words (unsigned shorts) equivalent to the MO_OPTIONS structure pointed to by ModeSettings. In fact, the definition is almost exactly the same, only the pointer type differs for compatibility with TI's compiler.
See also: ModeSettings
MO_OPTIONS *const ModeSettings; |
Contains a pointer to the global MO_OPTIONS structure.
ModeSettings is the constant pointer to the MO_OPTIONS structure, which keeps all mode settings together. But note that this structure is "auxiliary": TIOS consults other variables to check various mode settings when necessary. So, values in this structure are correct only after calling MO_currentOptions, and after changing one or more values in this structure, you need to call MO_digestOptions to inform TIOS about any changes. So, if you want, for example, to change "Display Digits" settings to "FIX 4" and "Complex Format" to "POLAR", you should do:
MO_currentOptions (); ModeSettings->Fix = 5; ModeSettings->Complex = 3; MO_digestOptions (0);
See also: MO_option
typedef void (* EVENT_HANDLER) (EVENT *) CALLBACK; |
A pointer to an event handler.
EVENT_HANDLER is a pointer type, pointing to a void function which accepts one parameter which is a pointer to an EVENT. See EV_captureEvents and EV_hook for more info.
typedef struct EventStruct {
|
A structure describing an event message.
EVENT is a structure which describes an event message in an event-driven application.
enum EventIDs {...}; |
An enumeration describing IDs of system messages.
EventIDs is enumerated type for describing ID numbers of system messages (they are
stored in the Type field of the EVENT structure. All possible
ID numbers (everything is in hex) are described in the following table. "Extra field" describes which
subfield in extra union field of EVENT structure
is used for storing extra information (if any). "(depr.)" after a name specifies that
this name is deprecated.
Code | Message name | Description | Extra field |
0x0 | CM_NOTHING | ||
0x1 - 0x4FF | CM_LAST_STRING_NUMBER | Built-in strings: Strings for the AMS are stored in a table for lanugage customization. EV_defaultHandler will turn these events into CM_PASTE_STRING events for the application to process. For compatibility with TI's Flash Studio, CM_LAST_STRING_NUMBER (0x4FF) is defined here. |
|
0x500 | CM_FIRST_APP_ID | Commands in the range 0x500 - 0x6FF are reserved for applications. Generally, these commands refer to Menu choices made by the user while running the application. | |
0x700 | CM_FIRST_SYS_ID | Commands in the range 0x700 - 0x7BF are reserved for use by the AMS. | |
0x700 | CM_NULL CM_IDLE (depr.) |
Idle (idle is called after message sent). This message is sent to the active application when there are no other events to process. The application might use this event to take care of some background processing or update an animated display. This message is used for example in spinning of 3D graph. | |
0x701 | CM_INIT | Init application. This message is sent from EV_centralDispatcher after a reset or when batteries are inserted. | |
0x702 | CM_START CM_STARTTASK (depr.) |
Start Task (in rect r). This message is sent to a task when it is being started. r is a rectangle with the requested window location and size chosen by the user from the mode screen settings. The application passes it to WinOpen to create its initial window. StartType field of the message is checked here (see EV_startTask), because some applications display a "Current/Open/New" submenu on the APPS menu, so this field is needed to tell the application which submenu command was selected by the user. | r |
0x703 | CM_ACTIVATE | Activate. Applications usually respond to this message by highlighting their window border to make it apparent to the user which application is active, by setting menu command states, and by updating (or activating) registered menus (see EV_registerMenu. Calling EV_defaultHandler will register and start the default toolbar for the running application. | |
0x704 | CM_FOCUS | Focus. Applications usually respond to this message by getting Mode options, and by giving the focus to the application editor (see TE_focus in textedit.h header file). This usually means making the cursor flashing. | |
0x705 | CM_UNFOCUS | UnFocus. Usually used on switching sides. When used on the text editor, it means turning of the cursor flashing. | |
0x706 | CM_DEACTIVATE | DeActivate. This message is sent to the active application to inform it that it no longer holds the interactive center of attention. Applications usually respond to this message by hiding menus and releasing the memory occupied by them. | |
0x707 | CM_QUIT CM_ENDTASK (depr.) |
End Task. Applications usually respond to this message by hiding windows and doing various cleanups. | |
0x708 | CM_RESTART CM_START_CURRENT (depr.) |
Start current. This message only notifies the current application that the user has chosen to start the same application again. Usually ignored. | |
0x709 | CM_APD | ||
0x70A | CM_OFF | ||
0x70B | CM_ON | Sent to each application when the calculator is turned on after being turned off with ([2ND] [OFF]). This command is not sent if the calculator was turned off via APD (Auto Power Down). | |
0x70C | CM_INSTALL | Sent to a FLASH application after it has been successfully installed on the calculator. This event will be sent when batteries are replaced, and after the FLASH app has been downloaded into the FLASH memory. | |
0x70D | CM_UNINSTALL | Sent to a FLASH application before it is deleted from the FLASH memory. | |
0x70E | CM_PACK | Tells a FLASH app that FLASH memory garbage collection is about to take place. All important settings should to be backed up using the application's public storage. | |
0x70F | CM_UNPACK | Tells a FLASH app that FLASH memory garbage collection has finished. The application should restore any saved settings. | |
0x710 | CM_KEY_PRESS CM_KEYPRESS (depr.) |
Keypress. This is the most common event. Note that a lot of system and mode events (opening system menus, dialogs etc.) are also processed as keypresses. They all have correct keypresses attached to them (usually DIAMOND + ...). Tokens are usually send via EV_sendString and do not have to be processed as single keypresses. All special keypresses may be passed to EV_defaultHandler for further processing. | Key |
0x720 | CM_CUT CM_MENU_CUT (depr.) |
Menu command: Cut. Dedicated for cutting selected text to the clipboard. All similar (text editing) events should eventually be handled by TE_handleEvent (the default text editor handler). | |
0x721 | CM_COPY CM_MENU_COPY (depr.) |
Menu command: Copy. Dedicated for copying selected text to the clipboard. Should eventually be handled by the default text editor handler. | |
0x722 | CM_PASTE CM_MENU_PASTE (depr.) |
Menu command: Paste. Dedicated for pasting text from the clipboard to the edit buffer at the cursor position, replacing any eventually selected text. Should eventually be handled by the default text editor handler. | |
0x723 | CM_PASTE_STRING CM_STRING (depr.) |
Paste static (constant) text into the event paste buffer (in fact, it only sets a pointer to PasteText). See EV_eventLoop and EV_sendString. | PasteText |
0x724 | CM_PASTE_HANDLE CM_HSTRING (depr.) |
Paste dynamic text, associated with a handle. The handle is released back to the heap by the default text edit handler after the paste is complete. | hPasteText |
0x725 | CM_DELETE CM_DEL (depr.) |
DEL (backspace) keypress. Dedicated for deleting selected text, or one character to the left of the cursor if no text is selected. Should eventually be handled by the default text editor handler. | |
0x726 | CM_CLEAR CM_CLR (depr.) |
CLR keypress. Dedicated for clearing selected text (if no text is selected, clear from cursor to end of edit buffer, and if cursor is at end of edit buffer, clear all text from edit buffer). Should eventually be handled by the default text editor handler. | |
0x727 | CM_CLEAR_ALL CM_MENU_CLEAR (depr.) |
Menu command: Clear. The application should decide decides what it means. | |
0x728 | CM_FIND CM_MENU_FIND (depr.) |
Menu command: Find. The application should decide decides what it means. | |
0x730 | CM_TOGGLE_INSERT CM_INSERT (depr.) |
Insert key. Dedicated for switching between text insert mode and overstrike mode. Should eventually be handled by the default text editor handler. | |
0x740 | CM_CURSOR_FLASH CM_BLINK (depr.) |
Flash cursor (0.5 sec timer expired, see EV_eventLoop). | |
0x750 | CM_STO CM_STORE (depr.) |
"Store" keypress. The default handler convert this message to the right arrow character. | |
0x751 | CM_RCL CM_RECALL (depr.) |
"RCL" keypress. The default event handler displays a dialog box for the user to enter the name of a variable to recall. The chosen variable’s contents are pasted at the edit cursor. | |
0x760 | CM_WPAINT | Paint window. Pointer to a window which need to be painted is attached. Applications should check to see if it belongs to the application and to redraw it if it is. See EV_paintWindows. These are not sent to the capturing hook, unless an application ID number is set to CM_NULL (force redraw). WinOpen stores the current application ID number in TaskId field of WINDOW structure. | w |
0x770 | CM_OPEN CM_MENU_OPEN (depr.) |
Menu command: Open... (the application should decide how to handle this and similar event messages; there are no default actions for them). | |
0x771 | CM_SAVE_AS CM_MENU_SAVE (depr.) |
Menu command: Save Copy As... | |
0x772 | CM_NEW CM_MENU_NEW (depr.) |
Menu command: New... | |
0x773 | CM_FORMAT CM_MENU_FORMAT (depr.) |
Menu command: Format... | |
0x774 | CM_ABOUT CM_MENU_ABOUT (depr.) |
Menu command: About... | |
0x780 | CM_MODE_CHANGE | Notify Mode Change (see MO_notifyModeChange). | |
0x781 | CM_SWITCH_GRAPH | Notify Switch Graph (this message is sent to "Graph", "Window Editor", "Table" and "Y=Editor" applications only). This event is used when the user switches between graphs in two-graph mode. | |
0x782 | CM_DEFAULTS | This command is sent when Reset->RAM->Default is executed in the MEMORY screen. Applications should revert to default settings. | |
0x790 | CM_BACKGROUND | This command is sent to applications which have a special flag set in their ACB (Application Control Block). It is a very low priority message and is generally used for background processing. | |
0x7C0 | CM_OPEN_SYSDATA CM_GEOMETRY (depr.) |
Geometry Open Data. | |
0x7C0 - 0x7FF | Used especially by AMS 1.xx to communicate between applications. This command has been largely replaced by using application frames on AMS 2.xx | ||
0x800 | CM_FIRST_APP_STRING | ||
0x800 - 0xFFF | On AMS 2.xx, applications store pointers to their strings in a frame. Messages in the range from 0x800 - 0xFFF are reserved for the active application's strings. For more information, see XR_stringPtr. |
typedef struct {
|
A structure containing all system mode settings.
MO_OPTIONS is a structure which contains all system mode settings. All fields in this structure are in fact indices of appropriate menu options in the "MODE" dialog. The only exceptions are fields Split1App and Split2App: they contains task ID numbers of the appropriate applications.
See also: ModeSettings, MO_option, MO_currentOptions, MO_digestOptions
typedef enum MoNotifyFlags {
|
Enumerates notify messages for the MO_notifyModeChange function.
Enumerates notify messages for the MO_notifyModeChange function. The meaning of these flags is given in MO_notifyModeChange.
See also: MO_notifyModeChange
enum PaintFlags {PAINTING_ENABLED = 0, PAINTING_SUSPENDED = 2}; |
An enumeration describing whether painting is suspended or enabled.
PaintFlags is an enumeration which describes the constants used in the EV_suspendPainting and EV_restorePainting functions.
enum StandardTaskIDs {AP_NULL = -3, AP_RUNNING = -2, AP_CURRENT = -1}; |
An enumeration describing task ID constants.
StandardTaskIDs is an enumeration which describes standard task "magic" numbers
which works independently of actual task ID numbers, so they are AMS-independent
(see EV_sendEvent).
"Running" application is the application which has an attached and activated toolbar menu (this
does not need to be equal to "Current" application). "Null" application is special value used for
overriding CM_WPAINT block (see EV_sendEvent).
See also: MO_sendQuit
enum StartTypes {...}; |
A pseudo-enumeration describing start types for EV_startTask.
StartTypes is a pseudo-enumeration which describes standard "start types" used in the EV_startTask command, on such way to be compatible with all AMS versions. It is defined using macros, but it behaves as it is defined as
enum StartTypes {AP_START_CURRENT = 0x00, AP_START_NEW = 0x10, AP_START_OPEN = 0x20, AP_START_ERROR = 0x30};
on AMS 1.xx, and
enum StartTypes {AP_START_CURRENT = 0, AP_START_NEW = 1, AP_START_OPEN = 2, AP_START_ERROR = 3};
on AMS 2.xx.