|Powered by QM on a Rpi server|
KnowledgeBase 00111: Writing Terminal Type Independent Applications
This article was originally published as a Tip of the Week.
The QMBasic @(x,y) function is widely used by application developers to create device dependent control codes for cursor moves and other screen control operations, however, most applications use their own internal mechanisms to decode incoming multi-byte sequences sent by function keys, etc. Very often, this restricts the application to working only with a limited set of terminal types, in many cases just one.
QM supports a device independent mechanism for processing terminal input that uses the terminfo database to recognise the codes sent by specific keys. Using this can considerably simplify keyboard input processing.
The KEYCODE() function returns a character entered at the terminal in the same way as the KEYIN() function, however, it uses the terminfo database to recognise byte sequences that correspond to special keys and returns a key specific code that is independent of terminal type.
KEYCODE() was part of the original implementation of QM and suffers from a serious limitation. Because this function returns a character, the only way in which it can pass back codes for the special keys is to reserve character positions in the upper half of the 8-bit character set to use for these keys (in much the same way that multivalue systems redefine the final five characters as the mark characters). This potentially causes problems for users who need, for example, the accented characters found in European languages.
As part of the Extended Character Set (ECS) support available from QM release 3.0-0, an alternative KEYCODEV() function was added. This function, available in both ECS and non-ECS mode, returns the numeric value of a key rather than the character. The special keys have values that, if considered as Unicode codepoint values, lie in the Private Usage Area and therefore no longer clash with character values that may be sent by user keystrokes.
On a non-ECS system, the values returned by KEYCODEV() can be processed by an application to recognise special keys but cannot be stored as a single 8-bit character value. On an ECS system, the returned values can be stored as a single character should the need arise.
The following example shows a code fragment that builds a string entered by the user but also recognises certain special keys. It would need considerable extension to form a realistic input processing function but is broadly similar in principle to how INPUT@ operates internally.
S = "" LOOP K = KEYCODEV() BEGIN CASE CASE K = KV$BACKSPACE ;* Backspace IF S # '' THEN S = S[1, LEN(S)-1] CASE K = KV$F1 ;* F1 key DISPLAY 'Seen F1 key' CASE K = KV$F2 ;* F2 key DISPLAY 'Seen F2 key' CASE IS.GRAPH(ECHAR(K)) S := ECHAR(K) END CASE REPEAT
An application can use the BINDKEY() function to make temporary modifications to the internal key binding tables derived from the terminfo database. As an example, several QM command line tools use this to add recognition of additional special key sequences.
BINDKEY() can also save and restore key bindings and enable or disable recognition of a "lone Escape" where the Escape key is pressed but is not closely followed by other bytes as part of a multi-byte control code.
For more details on BINDKEY(), see the QM Reference Manual.
00017: Terminal Support