Lugaru's Epsilon
Programmer's
Editor 14.04

Context:
Epsilon User's Manual and Reference
   Primitives and EEL Subroutines
      . . .
      Control Primitives
         Control Flow
         Character Types
         Examining 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 int key;
user int full_key;
int generic_key(int k)
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( ).

Some key combinations have both a generic and specific interpretation. For instance, the <Plus> key on a numeric keypad has a generic code identical to the <Plus> key on the main keyboard, but a unique specific code. Epsilon sets the full_key variable to the specific key code for that key, and key to the generic code for the key (in this case, "+"). For keys with only one interpretation, Epsilon sets key and full_key the same.

The generic_key( ) primitive returns the generic version of the specified key. For keys with only one interpretation, it returns the original key code.

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).

When a concurrent process is outputting text into an Epsilon buffer, it only appears there 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.

To add an idle-time task not associated with any specific buffer, or one that runs even if a given buffer isn't the current one, define a function with a name that starts with do_when_idle_. Epsilon will call it whenever it's idle. It must take a parameter times and return a result just like the when_idle( ) function.

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.

You can add your own logic for when a key repeats by defining a function with a name that starts with do_when_repeating_. The when_repeating( ) subroutine will call it whenever it runs. It must take no parameters and return no result.

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(?int ignore_suspended)

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. If its optional ignore_suspended parameter is nonzero, it counts a suspended macro (see Binding Primitives) as if no macro were running. 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 same goes for Unicode characters. 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-Alt-q key.

The remaining key codes represent those keys that don't correspond to any possible buffer character, 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. 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 remaining keys are GREYPLUS, GREYMINUS, GREYSTAR, GREYSLASH, GREYEQUAL, and GREYHELP for the +, -, *, /, =, and Help keys on the numeric keypad (not every keyboard has all these keys), and GREYENTER, GREYBACK, GREYTAB, GREYESC, and SPACEBAR for the <Enter>, <Backspace>, <Tab>, <Esc>, and <Spacebar> keys, respectively.

#define NUMSHIFT(c)     ((c) | KEY_SHIFT)
#define NUMCTRL(c)      ((c) | KEY_CTRL)
#define NUMALT(c)       ((c) | KEY_ALT)
#define KEY_PLAIN(c)    ((c) & ~(KEY_SHIFT | KEY_CTRL | KEY_ALT))

The NUMSHIFT(), NUMCTRL(), and NUMALT() macros make shifted, control, and alt versions of keys, respectively, by turning on the bit in a key code for each of these properties: KEY_SHIFT, KEY_CTRL, and KEY_ALT. For example, NUMCTRL(NUMDIGIT(3)) is Ctrl-n-<PgDn>, and NUMALT(KEYDELETE) is A-<Del>. The KEY_PLAIN() macro strips away these bits.

In this version, NUMALT( ) and ALT( ) are the same, and NUMCTRL( ) and CTRL( ) only differ on certain low-numbered characters: the former always turns on the KEY_CTRL bit, while the latter also generates ASCII control codes when given suitable ASCII characters.

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

The make_alt( ) subroutine defined in control.e will return an Alt version of any key. The make_ctrl( ) subroutine is similar, but makes a key into its Control version. These may be used instead of the ALT( ) and CTRL( ) macros.

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.

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 int 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 and full_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.)

This function always represents non-Latin1 Unicode characters (those in the range 256-65535) with their character names, like <GREEK SMALL LETTER GAMMA>. With a style of 3, Epsilon does this for Latin 1 characters (those in the range 32-255) too, thus representing all Unicode characters by name. With a style of 2, Epsilon uses Unicode character names for non-ASCII Latin 1 characters (those in the range 128-255) but represents printable ASCII characters like "J" as-is. With a style of 1, it represents all Latin 1 characters (in the range 32-255) as-is, using Unicode character names only for characters over 255.

See the %k sequence used by sprintf( ) and other functions, described in Printf-style Format Strings, for a more convenient way to translate keys or characters to text. Also see the unicode_character_name( ) primitive.

#define key_t             int
key_t *get_keycode()
int key_value(char *s, ?char **after)
stuff_macro(key_t *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 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 key_t macro represents the type of a key. It's the same as an int in this version, but not in very old Epsilon versions. Some code uses key_t instead of int, and #includes the compatibility header file oldkeys.h, to be compatible with very old Epsilon versions.

The key_value( ) primitive also converts key names into key codes, but it gets the key name from a string, not a buffer, and returns a single key code at a time. It tries to interpret s as a key name, and returns its value. If the optional pointer after is non-null, it must point to a character pointer. Epsilon sets *after to the position in the string after the key name. When s contains an invalid key name, key_value( ) returns -1 and sets *after (if after is non-null) to s.

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 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.

user char key_type;
user short key_code;

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-style encoding for the key that Epsilon received from the operating system, if available. Its ASCII code is in the low eight bits and its scan code is in the high eight bits.

The key_type variable has one of the following values, defined in codes.h. 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 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.

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. A macro key recorded with the EXTEND_SEL_KEY bit flag returns a key type of KT_EXTEND_SEL instead, but these extend codes are not used in current versions of Epsilon. In either case, the key_code variable is set to zero in this case.

In many environments, the key_code variable is always zero, and key_type is either KT_NORMAL, KT_MACRO, or KT_EXTEND_SEL.



Previous   Up    Next
Help Subroutines  Primitives and EEL Subroutines   The Mouse


Lugaru Epsilon Programmer's Editor 14.04 manual. Copyright (C) 1984, 2021 by Lugaru Software Ltd. All rights reserved.