Lugaru's Epsilon
Programmer's
Editor

Context:
Epsilon User's Manual and Reference
   Primitives and EEL Subroutines
      . . .
      Control Primitives
         Control Flow
         Character Types
         Strings
         . . .
         Help Subroutines
      Input Primitives
         Keys
         The Mouse
         Window Events
         . . .
      Defining Language Modes
         Language-specific Subroutines

Previous   Up    Next
Help Subroutines  Primitives and EEL Subroutines   The Mouse


Epsilon User's Manual and Reference > Primitives and EEL Subroutines > Input Primitives >

Keys

wait_for_key()
user short key;
when_idle(int times)     /* EEL subroutine */
add_buffer_when_idle(int buf, int (*func)())
delete_buffer_when_idle(int buf, int (*func)())
when_repeating()         /* EEL subroutine */
int is_key_repeating()

The wait_for_key( ) primitive advances to the next key, waiting for one if necessary. The variable key stores the last key obtained from wait_for_key( ). Its value may be from 0 to NUMKEYS - 1. The macro NUMKEYS is defined in eel.h.

When you call wait_for_key( ), it first checks to see if the ungot_key variable has a key (see below) and uses that if it does. If not, and a keyboard macro is active, wait_for_key( ) returns the next character from the macro. (The primitive also keeps track of repeat counts for macros.) If there is no key in ungot_key and no macro is active, the primitive checks to see if you have already typed another key and returns it if you have. If not, the primitive waits until you type a key (or a mouse action or other event occurs--Epsilon treats all of these as keys).

In the DOS version, if there is a concurrent process running, the primitive dispatches to the process to let it run until you press a key, instead of waiting. Even in other environments where a concurrent process can run independently of Epsilon, the process's output is only inserted in an Epsilon buffer during a call to wait_for_key( ). Epsilon handles the processing of other concurrent events like FTP transfers during this time as well.

While Epsilon is waiting for a key, it calls the when_idle( ) subroutine. The default version of this function does idle-time code coloring and displays any defined idle-time message in the echo area (see the show-when-idle variable), among other things. The when_idle( ) subroutine receives a parameter that indicates the number of times the subroutine has been called since Epsilon began waiting for a key. Every time Epsilon gets a key (or other event), it resets this count to zero.

The when_idle( ) subroutine should return a timeout code in hundredths of a second. Epsilon will not call the subroutine again until the specified time has elapsed, or another key arrives. If it doesn't need Epsilon to call it for one second, for example, it can return 100. If it wants Epsilon to call it again as soon as possible (assuming Epsilon remains idle), it can return 0. If the subroutine has completed all its work and doesn't need to be called again until after the next keystroke or mouse event, it can return -1. Epsilon will then go idle waiting for the next event. (The return value is only advisory; Epsilon may call when_idle( ) more frequently or less frequently than it requests.)

A mode may wish to provide additional functions that run during idle time, beyond those the when_idle( ) subroutine performs itself. The add_buffer_when_idle( ) subroutine registers a function func so that it will be called during idle-time processing whenever buf is the current buffer. The delete_buffer_when_idle( ) subroutine removes the specified function from that buffer's list of buffer-specific idle-time functions. (It does nothing if the function was not on the list.) A buffer-specific when-idle function takes a parameter times and must return a result in the same fashion as the when_idle( ) function itself.

When you hold down a key to make it repeat, Epsilon does not call the when_idle( ) subroutine. Instead, it calls the when_repeating( ) subroutine. Again, this varies by environment: under some operating systems, Epsilon cannot distinguish between repeated key presses and holding down a key to make it repeat. If this is the case, Epsilon won't call the function.

The is_key_repeating( ) primitive returns nonzero if the user is currently holding down a key causing it to repeat. Epsilon can't detect this in all environments, so the primitive always returns 0 in that case.

int getkey()            /* control.e */

Instead of calling wait_for_key( ) directly, EEL commands should call the EEL subroutine getkey( ) (defined in control.e), to allow certain actions that are written in EEL code to take effect on each character. For example, the standard version of getkey( ) saves each new character in a macro, if you're defining one. It checks the EEL variable _len_def_mac, which contains the length of the macro being defined plus one, or zero if you're not defining a macro. For convenience, getkey( ) also returns the new key. The getkey( ) subroutine calls wait_for_key( ). (If you want to add functions to getkey( ), see The Name Table to make sure your extension doesn't interfere with other extensions that may also add to getkey( ).)

int char_avail()
int in_macro()

The char_avail( ) primitive returns 0 if wait_for_key( ) would have to wait if it were called, and 1 otherwise. That is, it returns nonzero if and only if a key is available from ungot_key, a keyboard macro, or the keyboard.

The in_macro( ) primitive returns 1 if a keyboard macro is running or has been suspended, 0 otherwise. While processing the last key of a keyboard macro, in_macro( ) will return 0, because Epsilon has already discarded the keyboard macro by that time. Check the key-from-macro variable instead to see if the key currently being handled came from a macro.

There are some textual macros defined in eel.h which help in forming the codes for keys in an EEL function. The codes for normal ASCII keys are their ASCII codes, so the code for the key "a" is 'a'. The ALT() macro makes these normal keys into their Alt forms, so the code for Alt-a is ALT('a'). The CTRL() macro changes a character into the corresponding control character, so CTRL('h') or CTRL('H') both represent the Ctrl-h key. Both CTRL(ALT('q')) and ALT(CTRL('q')) stand for the Ctrl-A-q key.

The remaining key codes represent the non-ASCII keys, plus various key codes that represent other kinds of input events, such as mouse activity.

The FKEY() macro represents the function keys. FKEY(1) and FKEY(12) are F1 and F12, respectively. Note that this macro takes a number, not a character.

Refer to the cursor pad keys using the macros KEYINSERT, KEYEND, KEYDOWN, KEYPGDN, KEYLEFT, KEYRIGHT, KEYHOME, KEYUP, KEYPGUP, and KEYDELETE. If you use the -ke switch to separate the numeric keypad from the cursor pad, you can refer to the numeric keypad keys with the NUMDIGIT() macro: NUMDIGIT(0) is N-0, and NUMDIGIT(9) is N-9. NUMDOT is the numeric keypad period, and NUMENTER is the <Enter> or <Return> key on the numeric keypad (normally mapped to Ctrl-M).

The codes for the grey keys are GREYPLUS, GREYMINUS, GREYSTAR and GREYSLASH for the +, -, *, and / keys on the numeric keypad, and GREYENTER, GREYBACK, GREYTAB, and GREYESC for the <Enter>, <Backspace>, <Tab>, and <Esc> keys, respectively. (By default, several of these keys are mapped to others. See below.)

For all cursor, numeric, function, and grey keys, the NUMSHIFT(), NUMCTRL(), and NUMALT() macros make shifted, control, and alt versions, respectively. For example, NUMCTRL(NUMDIGIT(3)) is Ctrl-N-<PgDn>, and NUMALT(KEYDELETE) is A-<Del>.

int make_alt(int k)          /* control.e */
int make_ctrl(int k)         /* control.e */

The macros such as ALT( ) and NUMALT( ) described above create the codes for Alt versions of various types of keys. The make_alt( ) subroutine defined in control.e will return an Alt version of any key. Use one of the macros when the key involved is constant, and use the subroutine when it's variable. The make_ctrl( ) subroutine is similar, but makes a key into its Control version.

Use the IS_CTRL_KEY() macro to determine if a given key is a control key of some kind. Its value is nonzero if the key is an ASCII Control character, a function key with Control held down, or any other Control key. It understands all types of keys. The macro IS_ALT_KEY() is similar; its value is nonzero if the given key was generated when holding down the Alt key.

Keys returned from a macro can use some special bit flags. Epsilon uses the EXTEND_SEL_KEY bit flag to indicate that the shift key was held down when the current key in the macro was recorded, indicating that text should be selected. See Highlighted Regions for details.

A macro command recorded using the notation <!find-file> uses the bit flag CMD_INDEX_KEY. In this case the value of key is not a true key, but rather the name table index of the specified command. See Keys and their Representation for more information.

user short ungot_key;

If the ungot_key variable is set to some value other than its usual value of -1, that number is placed in key as the new key when wait_for_key( ) is called next, and ungot_key is set to -1 again. You can use this to make a command that reads keys itself, then exits and runs the key again when you press an unrecognized key. The statement ungot_key = key; accomplishes this.

show_char(char *str, int key, ?int style)

The show_char( ) primitive converts a key code to its printed representation, described in Keys and their Representation. For example, the code produced by function key 3 generates the string F-3. The string is appended to the character array str.

If show_char( )'s optional third parameter is present, and nonzero, this primitive will use a longer, more readable printed representation. For example, rather than C-A-S or , or S-F-10, show_char( ) will return Ctrl-Alt-S or <Comma> or Shift-F10. (Epsilon can only parse the former style, in Epsilon command files and in all other commands that use the get_keycode( ) primitive below.)

short *get_keycode()
stuff_macro(short *mac, int oneline)

The get_keycode( ) primitive is used to translate a sequence of key names such as "C-xC-A-f" into the equivalent key codes. It moves past a quoted sequence of key names in the buffer and returns an array of short ints with the key codes. The same array is used each time the function is called. The first entry of the array contains the number of array entries. The primitive returns null if the string had an invalid key name.

The stuff_macro( ) subroutine inserts a sequence of key names into the current buffer in a format that get_keycode( ) can read, surrounding the key names with " characters. The list of keys is specified by an array of short ints in the same format get_keycode( ) uses: the first value contains the total number of array entries. If oneline is nonzero, the subroutine represents line breaks with \n so that the text stays on one line.

short *keytran;
#define KEYTRANPASS     1000

The keytran primitive is a pointer to a short. It must point to an array of NUMKEYS shorts. This array changes the mapping of the keyboard, by changing the code the keyboard gives for a particular key. This change happens only when wait_for_key( ) returns a key from the keyboard, not when it returns a key from a keyboard macro. The value inserted in key is actually keytran[original-key-code].

If the value in keytran is -1, the original key code is used anyway. (Most keys use this setting.) If the value is -2, the key is silently ignored. If the value in keytran is KEYTRANPASS or more, Epsilon subtracts KEYTRANPASS before using the new value (but see below).

In the DOS version, some keytran values have a special meaning. Epsilon needs to use some keys that the BIOS normally considers invalid and discards. To prevent this, Epsilon intercepts all keys before the BIOS gets them, and decides whether to let the BIOS see them or not. (Epsilon could keep all the keys and never let the BIOS see them, but then any resident software or TSR's you had wouldn't be able to see them either.)

Epsilon decides whether to let the BIOS see each key based on its keytran entry. If it's a valid key code, Epsilon keeps it from the BIOS. If it's -2, Epsilon ignores it. Otherwise, (if it's -1, or KEYTRANPASS or more), Epsilon sends it to the BIOS. When it comes back, if its entry was KEYTRANPASS or more, Epsilon subtracts KEYTRANPASS from the entry and uses that number as the key.

This scheme means that any given key can be either ignored, sent to the BIOS, kept by Epsilon, kept but translated to another key, or sent to the BIOS and then (if the BIOS sends it back) translated to another key. These correspond to keytran entries of -2, -1, k, n, and KEYTRANPASS + n, respectively, where k is the original key, and n is the other key it could be replaced by.

By default, Epsilon keeps all keys that the BIOS considers invalid and would discard, and passes the rest through to the BIOS. The keys that Epsilon keeps are invisible to any resident programs that intercept keys, and cannot be used as "hot keys". Epsilon's program-keys command, described in Altering Keys, is useful for altering the keytran array.

user char key_type;
user short key_code;
user char kbd_extended;

When wait_for_key( ) returns a key that comes directly from the keyboard, it also sets the primitive variables key_type and key_code. These let EEL programs distinguish between keys that translate to the same Epsilon key code, for certain special applications. The wait_for_key( ) primitive doesn't change either variable when the key comes from ungot_key.

The key_code variable contains the sixteen-bit BIOS encoding for the key that Epsilon received from the operating system. Its ASCII code is in the low eight bits and its scan code is in the high eight bits. Under DOS, the key_code is zero when the keytran table entry for a key instructs Epsilon not to pass the key to the BIOS.

The key_type variable has one of the following values, defined in codes.h. If KT_KEYTRAN, the key had an explicit translation in the keytran table and Epsilon used it without passing it to the BIOS. If KT_NONASCII or KT_NONASCII_EXT, the key was a special key without an ASCII translation, such as a function key. Such keys are of type KT_NONASCII_EXT if they're one of the "E0" keys on an extended keyboard that are synonyms to multikey sequences on the old keyboard, such as the keys on the extended keyboard's cursor pad. Under DOS, these keys are of type KT_NONASCII_EXT only if you use the -ke switch, otherwise they're of type KT_NONASCII.

A key type of KT_ACCENT_SEQ indicates a multikey sequence that the operating system or a resident program has translated as a single key, such as an ê. Key type KT_ACCENT generally means the operating system translated a single key to a graphics character or foreign language character. Key type KT_NORMAL represents any other key. Most keys have a key type of KT_NORMAL.

A key type of KT_MACRO means the key came from a macro. But a macro key recorded with the EXTEND_SEL_KEY bit flag returns a key type of KT_EXTEND_SEL instead. In either case, the key_code variable is set to zero in this case.

In Epsilon for Windows or Unix, the key_code variable is always zero, and key_type is either KT_NORMAL, KT_MACRO, or KT_EXTEND_SEL.

The kbd_extended variable tells whether the -ke flag was used to make the numeric pad and cursor pad keys distinct. Normally, both are treated the same, and this variable is zero. If you give the -ke flag, Epsilon treats these as separate sets of keys, and makes the variable nonzero.



Previous   Up    Next
Help Subroutines  Primitives and EEL Subroutines   The Mouse


Lugaru Copyright (C) 1984, 2020 by Lugaru Software Ltd. All rights reserved.