/* * akbd.c * * Really good keyboard handling * * © 1994-1998 Straylight */ /*----- Licensing note ----------------------------------------------------* * * This file is part of Straylight's Steel library. * * Steel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * Steel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Steel. If not, write to the Free Software Foundation, * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "os.h" #include "akbd.h" #include "bbc.h" /* * BOOL akbd_checkInternalKey(int ikey) * * Use * Checks whether a given key is being pressed at the moment. * * Parameters * int ikey == the internal key number of the key to check, as shown on page * 1-849 of the RISC OS 3 Programmer's Reference Manual. */ BOOL akbd_checkInternalKey(int ikey) { return (bbc_inkey(0xFF00 | (ikey ^ 0xFF))); } /* * int akbd_translate(int chcode) * * Use * Translates the given WIMP-type key number, as returned in a Key_Pressed * (wimp_EKEY) event into a STEEL extended key number, which should * distinguish almost every keypress available. * * Parameters * int chcode == a WIMP-type keypress number * * Returns * An extended keycode */ #define akbd__WEIRDCTRL 0x000003BB #define akbd__modify(a,b,c,d) \ switch (modifiers) \ { \ case 0: \ return (a); \ case 1: \ return (b); \ case 2: \ return (c); \ case 3: \ return (d); \ } int akbd_translate(int chcode) { int modifiers; int icode=0; int base=0; /* --- If it's a function key, the WIMP has translated it for us --- */ if ((chcode>=0x1CA) || (chcode>=0x180 && chcode<=0x1BF) || (chcode>='a' && chcode<='z') || (chcode>='A' && chcode<='Z') || (chcode>='[' && chcode<=']')) return (chcode); /* --- Work out the modifier status --- */ modifiers=0; if (akbd_checkInternalKey(0)) modifiers|=1; if (akbd_checkInternalKey(1)) modifiers|=2; /* --- How many ways can you press Delete? --- */ if (chcode==0x7F) { switch (modifiers) { case 0: return (0x7F); case 1: return (0x17F); case 2: return (0x01F); case 3: return (0x11F); } } /* --- Check for variants of space --- */ if (chcode==' ') akbd__modify(0x020,0x120,0x000,0x100); /* --- The many faces of the Return key --- */ if (chcode==0x0D) { /* --- He pressed return (or maybe ^M, or even Enter...) --- */ if (akbd_checkInternalKey(60)) { /* --- It was Enter, so return a variant of that --- */ akbd__modify(0x166,0x176,0x126,0x146); } else if (!akbd_checkInternalKey(101)) { /* --- It *wasn't* ^M, so it must have been Return --- */ akbd__modify(0x01D,0x11D,0x13D,0x15D); } /* --- If it was ^M, the control key mashing will catch it --- */ } /* --- Check for control keys --- */ if (chcode<0x1B) { if (akbd__WEIRDCTRL & (1<='0' && chcode<='9') { static char keypadTable[]={106,107,124,108,122,123,26,27,42,43}; if (akbd_checkInternalKey(keypadTable[chcode-'0'])) { /* --- It was the keypad version, so we have to modify it --- */ return (chcode+(0x1C0-'0')+(modifiers<<4)); } else return (chcode); } /* --- Test for the rest of the keypad --- */ switch (chcode) { case '/': icode=74; base=0x161; break; case '*': icode=91; base=0x162; break; case '#': icode=90; base=0x163; break; case '-': icode=59; base=0x164; break; case '+': icode=58; base=0x165; break; case '.': icode=76; base=0x167; break; } if (icode) { /* --- It could be a keypad key here, so check --- */ if (akbd_checkInternalKey(icode)) { /* --- It is one of the other keypad keys, so return it modified --- */ akbd__modify(base,base+16,base-64,base-32); } } /* --- The revolting gross (US-ism -- yuk) keys that are left --- */ switch (chcode) { case 0x01E: /* --- Home, or maybe ^6 :-/ --- */ if (akbd_checkInternalKey(24)) { if (modifiers & 1) return (0x156); else return (0x136); } else akbd__modify(0x01E,0x11E,0x13E,0x15E); break; case 0x01B: /* --- Escape, or maybe ^[ :-/ --- */ if (akbd_checkInternalKey(56)) { if (modifiers & 1) return (0x14B); else return (0x12B); } else akbd__modify(0x01B,0x11B,0x13B,0x15B); break; case 0x01C: case 0x01D: case 0x01F: if (modifiers & 1) return (chcode+0x130); else return (chcode+0x110); break; } /* --- Hmm -- it seems sensible after all --- */ return (chcode); } /* * BOOL akbd_pollsh(void) * * Use * Returns whether the Shift key is pressed */ BOOL akbd_pollsh(void) { return (akbd_checkInternalKey(0)); } /* * BOOL akbd_pollctl(void) * * Use * Returns whether the Control key is pressed */ BOOL akbd_pollctl(void) { return (akbd_checkInternalKey(1)); } /* * BOOL akbd_pollkey(int *code) * * Use * Reports whether the user has typed ahead, and if so what the keypress * was. Note that the keypresses returned are WIMP-type, not STEEL extended * ones so you will have to use akbd_translate if you need the extended * type. * * This call could be used to allow buffering of keypresses: on a * Key_Pressed event you would call this routine until it returns FALSE * and store the codes it returns in a buffer along with the code from the * event. */ BOOL akbd_pollkey(int *code) { int key; /* --- Find out if there is a key waiting --- */ key=bbc_inkey(0); if (key==-1) return (FALSE); /* --- Check for extended codes --- */ if (!key) { key=bbc_inkey(0); if (key) *code=key+0x100; else *code=0; } else *code=key; /* --- We found one --- */ return (TRUE); }