Rawkey library v0.21
--------------------

This is an attempt to make the use of raw keyboard mode for games
easier. It hides the necessary ioctl()'s somewhat, and hopefully makes
the whole process a bit less painful. The library assumes you are
using svgalib.  (If you look in vga.c from [s]vgalib and check out the
bit where it changes the termio settings, for text mode you'd need to
do something along those lines before calling rawmode_init().)

VT switching can be arranged, but is disabled by default.


Installation
------------

To install, do a 'make install' as root. This will install 'rawkey.h'
in /usr/include, 'librawkey.a' in /usr/lib, and compile two simple
test programs (using svgalib), called 'testprog' and 'testvt'. If you
get an error, you're probably not root (you need to be root, even if
you're not installing the library yet, to run 'testprog' and
'testvt').

After that, check 'testprog' works by running it, using the cursors to move
the dot around, and Esc to quit. Check that holding, say, up and left cursor
keys at the same time gives a diagonal, and also check the response is
instant with no keyboard repeat delays.

Then check that 'testvt' allows you to switch VTs using Alt-Fn (or
Ctrl-Alt-Fn, both act the same). Other than that, it does the same as
'testprog'.


How to use the Rawkey library
-----------------------------

The important functions to know about are:


int rawmode_init()

call this to start using raw mode.
returns 1 if ok, 0 on error.
You should be in graphics mode before calling this, if using svgalib. A
typical startup sequence might go:

	main()
	{
	vga_init();
	vga_setmode(G320x200x256);
	rawmode_init();
	...


void rawmode_exit()

call this to resume normal operation.
You should be back in text mode before calling this, if using svgalib.

WARNING: Make *sure* you are out of RAW mode before exiting, or believe me
you'll regret it! Consider setting up signal handlers for things like
SIGSEGV or whatever just in case.


void scan_keyboard()

this handles scancode reading from the keyboard, which you shouldn't
*directly* worry about. You need to call this every so often - the easiest
way is to call it whenever you would ordinarily call, say, vga_getch(). Note
that this function has no return value - call it first then use
is_key_pressed() to check the status of any individual key.

Say if you would ordinarily use something like this for a 'press space'
type pause:

	while(vga_getch()!=32);

you would now do:

	[insert '#include <unistd.h>' at the top]

	do
          {
	  usleep(10000);	/* check at most every 1/100th of a second */
	  scan_keyboard();
	  }
	while(!is_key_pressed(SPACE_BAR));

i.e. scan_keyboard() goes where you would normally put a vga_getch(), but
when you need to test if a key was/is pressed, you use is_key_pressed() (see
below). The usleep() is to prevent burning unnecessary CPU time, as
scan_keyboard() is non-blocking, i.e. it doesn't wait for a keypress.


int is_key_pressed(int scancode)

this tells you if a specific key is pressed.
Returns 1 if true, 0 otherwise
The arg is the scancode of the key. You don't really need to know about
that, what you *do* need to know is that the following symbols are
pre-defined and can be used as args to is_key_pressed():

	ESCAPE_KEY, ENTER_KEY, BACKSPACE, TAB_KEY
	LEFT_SHIFT, RIGHT_SHIFT, LEFT_CTRL, LEFT_ALT	(see below)
	FUNC_KEY(x)	(x ranging from 1 to 12)
	CURSOR_LEFT, CURSOR_RIGHT, CURSOR_UP, CURSOR_DOWN, KEYPAD_CENTER
	INSERT_KEY, DELETE_KEY, HOME_KEY, END_KEY, PAGE_UP, PAGE_DOWN
	CAPS_LOCK, NUM_LOCK, SCROLL_LOCK
	GRAY_PLUS, GRAY_MINUS, GRAY_MULTIPLY, GRAY_DIVIDE	(see below)

Note the following:
1. 'LEFT_CTRL' and 'LEFT_ALT' actually cover both ctrl's and alt's.
   'LEFT_SHIFT' and 'RIGHT_SHIFT' do cover the respective shift's, however.
2. 'GRAY_MULTIPLY' is also generated by PrintScreen.
3. There is no reliable way to check for PrintScreen or Pause yet. Sorry.
4. KEYPAD_CENTER is the '5' in the centre of the numeric keypad.
5. If the key you want to check for is a letter or number key,
   use scancode_trans() as shown below in the 'Ctrl-X' example.
6. If the key you want to check for is shifted, think about how many keys
   you're pressing to get that key, then see 7 below.
7. If you want to check for, say, Ctrl-X, you should check them as two
   keys being simultaneously pressed, i.e. do:

     if(is_key_pressed(LEFT_CTRL) && is_key_pressed(scancode_trans('x')))
	...

8. If the key you want to check for isn't covered by any of the above,
   don't use it. :-)  It probably won't stay the same between different
   national keyboards anyhow, so it's a bad move to check for it.
9. In a similar vein, games writers please allow redefinable keys! It's a
   bit of a pain, but is a godsend for people who hate your wonderful
   perfect choice of keys :-) or have, say, an AZERTY keyboard which might
   screw those keys' arrangement up badly.

See testprog.c for a fuller example of how this function should be used.


int is_any_key_pressed()

this is a function that checks if any key is pressed (including shifts etc.)
to save you having to do it for those 'press any key' jobs.
Returns 1 if true, 0 otherwise.


int scancode_trans(int asciival)

effectively returns the scancode for the given ASCII
Also returns -1 if none found.
Use this with is_key_pressed to tell if a letter or number key is pressed -
e.g. to tell if the Q key is pressed (must be lowercase):

	if(is_key_pressed(scancode_trans('q'))) ...

This routine uses a copy of keymap 0 (no modifiers) as held by the kernel;
see loadkeys(1) and keytables(5) for more info.


void set_switch_functions(void (*off)(void),void (*on)(void))
void allow_switch(int on)

These allow you to setup console switching via alt-Fn. Call these
like:

	set_switch_functions(undrawfunc,redrawfunc);
	allow_switch(1);
	...

...where undrawfunc() puts the screen in text mode, and redrawfunc()
goes back to graphics and redraws the screen. If the user presses alt
and a function key this is detected in scan_keyboard(), which will
effectively block until the console is returned to.


This probably all looks rather confusing, so potential games writers
should look at testvt.c and rawkey.h for more clues as to how to go
about using raw keyboard mode via this library.


Epilogue
--------

I welcome bug reports, suggestions for improvements, anything really.
(Please bear in mind, however, that this library is only intended for the
simple keyboard use made by games. And IMHO, only games and emulators should
ever need to use RAW mode. X can go whistle. :-))

If you need any help using it, email me and I'll try to assist you.

Cheers,
- Russell Marks (mr216@gre.ac.uk)
