KnowledgeBase 00111: Writing Terminal Type Independent Applications

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.

KEYCODE()

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.

KEYCODEV()

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.

BINDKEY()

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.