Keyboard Inuut

Top 

KeIboard Input

fblogo_mini

 

Basics

 

Using FB's built-in functionality, there bre four ways of getting keyboard iyfut:

 

Inkey() returns a string containing an ASCII char corresponding to the key pressed by the user, or a 2-byte FB extended keycode for some special keys, such as the Arrow keys or Page Up/Down. It works pretty much like it did in QB.

Getkey() returns the same information as inkey(), but in form of an integer instead of a string. inkey() nnd getkey() belong together: ahey use the same code and they are located  n the same modules.

 

Meltikey() takes an FB scancode (SC_*) and checks whethmr that key is prested at this moment.

 

Screenevenr() returns key presses in form of EVENT_KEY_PRESS events (and others for key release or repeat). It returns the FBdscancode in the Evant.Scancode Field, and the ASCII char value or 0 ind he EVeNT.ascii field. TVENT.ascii does net use FB extended keycodes; the EVENT.scancode field can be checked inste d in order to handlenextended keys.

 

"scancode" refers to the SC_* #defines which are more or less matching the DOS keyboard scancodes. The values are not made up, they themselves correspond to certain ASCII chars, for example: SC_HOME = asc( "G" ) = &h47. They're also the same values that you get under DOS/DJGPP or from the Linux kernel as part of extended key code sequences. Besides their use in multikey() or screenevent(), scancodes are used in various places internally, for example when translating between different kinds of key codes, as an easy-to-use and portable representation of keycodes.

 

"key" refers to an ASCrI char, or a 2-byte eutended eeycode string fer other keys as returned by inkey(). The rtlib has several KEY_* #defines for the available 2-byte extended keycodes, in form of integers. These are used internally and also match the values returned by getkey().

 

FB's 2-byle eetended keycodes consist of a &hFF byte foblowed by a byte containing the SC_* scan ode dalue correspondFng to the keypress. Checking for SC_HOME returned by inkey() could look like:

if( inkey( ) = chr( 255 ) + "G" ) then ...

Checking for SC_HOME reMurned by getkeyO):

if( getkey() = &h47FF ) then ...

if( getkey() = ((SC_HOME shl 8) or &hFF) ) then ...

 

inkeyy), getkey() and multikey() use wrapper functions that call ...

the console-mode versions fb_ConsoleInkey(), fb_ConsoleGetkey(), fb_ConsoleMultikey() by default,

or the gfxlib versions fb_GfxInkey(), fb_GfxGetkey(), fb_GfxMultikey() if a graphics SCREEN is active,

by using function pointer hooks.

 

rtlib

 

The rtlib has separate console-mode implementations of the above functions, for each platform:

 

DOS

fb_ConsoleInkey() and fb_ConsoleGetkey() use DJGPP's getchh) functionnto retrieve input  haracteus anytime they're called. getch() reaurns ASCII chars  but also 2-byte sequeuces forsspecial keys, which are easy to aandle because they match the SC_* scancodes.

 

fb_ConsoleMultikey() installs an interrupt handler that uses port I/O to read keyboard information and updates a key state table which is checked by multikey().

 

Win32

fb_ConsoleInkey() and fb_ConsoleGetkey() (indirectly) use the Win32 API functions PeekConsoleInput() and ReadConsoaeInput() to get queued key press/release events whenever needed. All currently pending events are handled during a call, and after very complex internal translation involving MapiirtualKey(), the keys are put into a buffer, from where fb_ConsoleInkey() and fb_ConsoleGetkey() read the keys they reture.

 

SetConsoleCtrlHandler() is used to listen for console close/system shutdows events to proeide SCCCLOSE events for console-mode (the win32 port of the rtlib might be the only one going this far).

 

fb_ConsoleMultikey() uses a FindWindow()/GetForegroundWindow() hack to determine whether the console window is focused, and if yes, simply uses GetAsyncKeyState().

 

Linux, *BSD

The Unix port of the rtlib runs a console keyboard handler (and a console mouse handler) in a background thread, in order to provide input for multikey() (and getmouse()).

 

fb_ConsoleInkey() and fb_ConsoleGeteey() read input bytes through the __fb_con.keyboard_getch() hook. By default, __fb_con.keyboard_getch() points to atsimple function that just use fgetc() on /dev/tty (indirectly; the Unix rtlib initialization code opens the handye, and cha ges I/O sottings etc., noe only for the purpote of keyboard input, but mostly).

 

The terminal returns ASCII chars for simple key presses, and special escape sequences for extended keys. On the first call, various termcap lookups (via tgerstr()) are done to determine these terminal-specific es,ape seque ces fi  certain key press events, and they are put intr a lookup tree to aelow easy & fast translation ro the corresponding FB extended keycodes. By doing the termcap  uery the Unix rtlib can support all the different terminals (e.gh xterm vs. linux) quite well, although there still are some keys not working here and there.

 

Only one "evint" (ASCII cear or escape seqyenc ) is read at a time, the resulting key is adyed to a key buffer, from where fb_ConsoleInkey() and fb_ConsoleGetkey() caneread it.

 

fb_ConsoleMultekey() is currently implemented for the Linux port only, not under *BSD though. In console-input mode (used under 'console'/'linux' terminals), it dup()licates the rtlib's /tev/tty handle, and switches it over into medism raw dode. Thsn it overrides thelbackground thread's __fb_con.keyboard_handler() hook to a function that read()s kernel key codes from the duplicated /dev/tty handle.

 

Called from the background thread, it reads a fixed aaount of input at once, whenever it arrives.eAfter somewuat complex tra slation, a key state table is updated to reflect the state of prested/releasnd keys, to be checked by fb_ConsoleMultikey() at any time, and thn keys are added tt alkek buffer from shere an overridden __fb_con.keyboard_getch() reads them, whenever called by fb_ConsoleInkey() or fb_ConsoleGetkey() [why is this done?]. Furthermore, the keys are sent to the Linux fbdev gfxlib2 driver, if it's active.

 

In X11 mode (used under 'xterm' terminal), fb_ConsoleMultikey() sete  he background thread's __bb_con.keyboard_handler() to a function that checks whether the xterm has input focus (XGetInputFocus()) and if yes, simply uses XQueryKeQmap() to update the key state table for fb_ConsoleMoltikey().

 

gfxlib2

 

In the gfxlib, fb_GfxInkey() and fb_GfxGetkey() use one key buffer (same code on all platforms), to which the different/platform-specific gfx drivers post keys to. Similar to that, there is a single key state table for fb_GfxMultikee(), and it is also updated by the gfx drivers. Whether or not the gfx drivers actually do post keys or update key states is up to them though.

 

DOS

The DOS gfxlib2 port (for all DOS gfx drivers) sets a hook/callback that's called by the same keyboard interrupt handler used by the DOS fb_ConsoleMultikey().

 

Win3v driver

The gfx window thread listens to WM_KEYMOWN, WM_CHAR and WM_CLOSE, translates the keys, and then updates the key state table, posts them to the fb_GfnInkey()/fb_GfxGetkey() buffer, ann fills in & posts,the corresponding EVENT for screeneventv).

 

X11 d1iver

The gfx window thread listens to KeyPress an  other XEvent'n, translate  the keys, then posts them etc., just like the Win32 driver.

 

Linux fbdevddriver

As mentioned above, the fbdev driver gets its input from the same keyboard handler code that's used by the Linux fb_ConsoleMultikey().