123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449 |
- /****************************************************************************
- *
- * SciTech OS Portability Manager Library
- *
- * ========================================================================
- *
- * The contents of this file are subject to the SciTech MGL Public
- * License Version 1.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.scitechsoft.com/mgl-license.txt
- *
- * Software distributed under the License is distributed on an
- * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
- *
- * The Initial Developer of the Original Code is SciTech Software, Inc.
- * All Rights Reserved.
- *
- * ========================================================================
- *
- * Language: ANSI C
- * Environment: Any
- *
- * Description: Direct keyboard event handling module. This module contains
- * code to process raw scan code information, convert it to
- * virtual scan codes and do code page translation to ASCII
- * for different international keyboard layouts.
- *
- ****************************************************************************/
- /*---------------------------- Implementation -----------------------------*/
- /****************************************************************************
- PARAMETERS:
- scanCode - Keyboard scan code to translate
- table - Code page table to search
- count - Number of entries in the code page table
- REMARKS:
- This function translates the scan codes from keyboard scan codes to ASCII
- codes using a binary search on the code page table.
- ****************************************************************************/
- static uchar translateScan(
- uchar scanCode,
- codepage_entry_t *table,
- int count)
- {
- codepage_entry_t *test;
- int n,pivot,val;
- for (n = count; n > 0; ) {
- pivot = n >> 1;
- test = table + pivot;
- val = scanCode - test->scanCode;
- if (val < 0)
- n = pivot;
- else if (val == 0)
- return test->asciiCode;
- else {
- table = test + 1;
- n -= pivot + 1;
- }
- }
- return 0;
- }
- /****************************************************************************
- REMARKS:
- This macro/function is used to converts the scan codes reported by the
- keyboard to our event libraries normalised format. We only have one scan
- code for the 'A' key, and use shift modifiers to determine if it is a
- Ctrl-F1, Alt-F1 etc. The raw scan codes from the keyboard work this way,
- but the OS gives us 'cooked' scan codes, we have to translate them back
- to the raw format.
- {secret}
- ****************************************************************************/
- void _EVT_maskKeyCode(
- event_t *evt)
- {
- int ascii,scan = EVT_scanCode(evt->message);
- evt->message &= ~0xFF;
- if (evt->modifiers & EVT_NUMLOCK) {
- if ((ascii = translateScan(scan,EVT.codePage->numPad,EVT.codePage->numPadLen)) != 0) {
- evt->message |= ascii;
- return;
- }
- }
- if (evt->modifiers & EVT_CTRLSTATE) {
- evt->message |= translateScan(scan,EVT.codePage->ctrl,EVT.codePage->ctrlLen);
- return;
- }
- if (evt->modifiers & EVT_CAPSLOCK) {
- if (evt->modifiers & EVT_SHIFTKEY) {
- if ((ascii = translateScan(scan,EVT.codePage->shiftCaps,EVT.codePage->shiftCapsLen)) != 0) {
- evt->message |= ascii;
- return;
- }
- }
- else {
- if ((ascii = translateScan(scan,EVT.codePage->caps,EVT.codePage->capsLen)) != 0) {
- evt->message |= ascii;
- return;
- }
- }
- }
- if (evt->modifiers & EVT_SHIFTKEY) {
- if ((ascii = translateScan(scan,EVT.codePage->shift,EVT.codePage->shiftLen)) != 0) {
- evt->message |= ascii;
- return;
- }
- }
- evt->message |= translateScan(scan,EVT.codePage->normal,EVT.codePage->normalLen);
- }
- /****************************************************************************
- REMARKS:
- Returns true if the key with the specified scan code is being held down.
- ****************************************************************************/
- static ibool _EVT_isKeyDown(
- uchar scanCode)
- {
- if (scanCode > 0x7F)
- return false;
- else
- return EVT.keyTable[scanCode] != 0;
- }
- /****************************************************************************
- PARAMETERS:
- what - Event code
- message - Event message (ASCII code and scan code)
- REMARKS:
- Adds a new keyboard event to the event queue. This routine is called from
- within the keyboard interrupt subroutine!
- NOTE: Interrupts are OFF when this routine is called by the keyboard ISR,
- and we leave them OFF the entire time.
- ****************************************************************************/
- static void addKeyEvent(
- uint what,
- uint message)
- {
- event_t evt;
- if (EVT.count < EVENTQSIZE) {
- /* Save information in event record */
- evt.when = _EVT_getTicks();
- evt.what = what;
- evt.message = message | 0x10000UL;
- evt.where_x = 0;
- evt.where_y = 0;
- evt.relative_x = 0;
- evt.relative_y = 0;
- evt.modifiers = EVT.keyModifiers;
- if (evt.what == EVT_KEYREPEAT) {
- if (EVT.oldKey != -1)
- EVT.evtq[EVT.oldKey].message += 0x10000UL;
- else {
- EVT.oldKey = EVT.freeHead;
- addEvent(&evt); /* Add to tail of event queue */
- }
- }
- else {
- #ifdef __QNX__
- _EVT_maskKeyCode(&evt);
- #endif
- addEvent(&evt); /* Add to tail of event queue */
- }
- EVT.oldMove = -1;
- }
- }
- /****************************************************************************
- REMARKS:
- This function waits for the keyboard controller to set the ready-for-write
- bit.
- ****************************************************************************/
- static int kbWaitForWriteReady(void)
- {
- int timeout = 8192;
- while ((timeout > 0) && (PM_inpb(0x64) & 0x02))
- timeout--;
- return (timeout > 0);
- }
- /****************************************************************************
- REMARKS:
- This function waits for the keyboard controller to set the ready-for-read
- bit.
- ****************************************************************************/
- static int kbWaitForReadReady(void)
- {
- int timeout = 8192;
- while ((timeout > 0) && (!(PM_inpb(0x64) & 0x01)))
- timeout--;
- return (timeout > 0);
- }
- /****************************************************************************
- PARAMETERS:
- data - Data to send to the keyboard
- REMARKS:
- This function sends a data byte to the keyboard controller.
- ****************************************************************************/
- static int kbSendData(
- uchar data)
- {
- int resends = 4;
- int timeout, temp;
- do {
- if (!kbWaitForWriteReady())
- return 0;
- PM_outpb(0x60,data);
- timeout = 8192;
- while (--timeout > 0) {
- if (!kbWaitForReadReady())
- return 0;
- temp = PM_inpb(0x60);
- if (temp == 0xFA)
- return 1;
- if (temp == 0xFE)
- break;
- }
- } while ((resends-- > 0) && (timeout > 0));
- return 0;
- }
- /****************************************************************************
- PARAMETERS:
- modifiers - Keyboard modifier flags
- REMARKS:
- This function re-programs the LED's on the keyboard to the values stored
- in the passed in modifier flags. If the 'allowLEDS' flag is false, this
- function does nothing.
- ****************************************************************************/
- static void setLEDS(
- uint modifiers)
- {
- if (EVT.allowLEDS) {
- if (!kbSendData(0xED) || !kbSendData((modifiers>>9) & 7)) {
- kbSendData(0xF4);
- }
- }
- }
- /****************************************************************************
- REMARKS:
- Function to process raw scan codes read from the keyboard controller.
- NOTE: Interrupts are OFF when this routine is called by the keyboard ISR,
- and we leave them OFF the entire time.
- {secret}
- ****************************************************************************/
- void processRawScanCode(
- int scan)
- {
- static int pauseLoop = 0;
- static int extended = 0;
- int what;
- if (pauseLoop) {
- /* Skip scan codes until the pause key sequence has been read */
- pauseLoop--;
- }
- else if (scan == 0xE0) {
- /* This signals the start of an extended scan code sequence */
- extended = 1;
- }
- else if (scan == 0xE1) {
- /* The Pause key sends a strange scan code sequence, which is:
- *
- * E1 1D 52 E1 9D D2
- *
- * However there is never any release code nor any auto-repeat for
- * this key. For this reason we simply ignore the key and skip the
- * next 5 scan codes read from the keyboard.
- */
- pauseLoop = 5;
- }
- else {
- /* Process the scan code normally (it may be an extended code
- * however!). Bit 7 means key was released, and bits 0-6 are the
- * scan code.
- */
- what = (scan & 0x80) ? EVT_KEYUP : EVT_KEYDOWN;
- scan &= 0x7F;
- if (extended) {
- extended = 0;
- if (scan == 0x2A || scan == 0x36) {
- /* Ignore these extended scan code sequences. These are
- * used by the keyboard controller to wrap around certain
- * key sequences for the keypad (and when NUMLOCK is down
- * internally).
- */
- return;
- }
- /* Convert extended codes for key sequences that we map to
- * virtual scan codes so the user can detect them in their
- * code.
- */
- switch (scan) {
- case KB_leftCtrl: scan = KB_rightCtrl; break;
- case KB_leftAlt: scan = KB_rightAlt; break;
- case KB_divide: scan = KB_padDivide; break;
- case KB_enter: scan = KB_padEnter; break;
- case KB_padTimes: scan = KB_sysReq; break;
- }
- }
- else {
- /* Convert regular scan codes for key sequences that we map to
- * virtual scan codes so the user can detect them in their
- * code.
- */
- switch (scan) {
- case KB_left: scan = KB_padLeft; break;
- case KB_right: scan = KB_padRight; break;
- case KB_up: scan = KB_padUp; break;
- case KB_down: scan = KB_padDown; break;
- case KB_insert: scan = KB_padInsert; break;
- case KB_delete: scan = KB_padDelete; break;
- case KB_home: scan = KB_padHome; break;
- case KB_end: scan = KB_padEnd; break;
- case KB_pageUp: scan = KB_padPageUp; break;
- case KB_pageDown: scan = KB_padPageDown; break;
- }
- }
- /* Determine if the key is an UP, DOWN or REPEAT and maintain the
- * up/down status of all keys in our global key array.
- */
- if (what == EVT_KEYDOWN) {
- if (EVT.keyTable[scan])
- what = EVT_KEYREPEAT;
- else
- EVT.keyTable[scan] = scan;
- }
- else {
- EVT.keyTable[scan] = 0;
- }
- /* Handle shift key modifiers */
- if (what != EVT_KEYREPEAT) {
- switch (scan) {
- case KB_capsLock:
- if (what == EVT_KEYDOWN)
- EVT.keyModifiers ^= EVT_CAPSLOCK;
- setLEDS(EVT.keyModifiers);
- break;
- case KB_numLock:
- if (what == EVT_KEYDOWN)
- EVT.keyModifiers ^= EVT_NUMLOCK;
- setLEDS(EVT.keyModifiers);
- break;
- case KB_scrollLock:
- if (what == EVT_KEYDOWN)
- EVT.keyModifiers ^= EVT_SCROLLLOCK;
- setLEDS(EVT.keyModifiers);
- break;
- case KB_leftShift:
- if (what == EVT_KEYUP)
- EVT.keyModifiers &= ~EVT_LEFTSHIFT;
- else
- EVT.keyModifiers |= EVT_LEFTSHIFT;
- break;
- case KB_rightShift:
- if (what == EVT_KEYUP)
- EVT.keyModifiers &= ~EVT_RIGHTSHIFT;
- else
- EVT.keyModifiers |= EVT_RIGHTSHIFT;
- break;
- case KB_leftCtrl:
- if (what == EVT_KEYUP)
- EVT.keyModifiers &= ~EVT_LEFTCTRL;
- else
- EVT.keyModifiers |= EVT_LEFTCTRL;
- break;
- case KB_rightCtrl:
- if (what == EVT_KEYUP)
- EVT.keyModifiers &= ~EVT_RIGHTCTRL;
- else
- EVT.keyModifiers |= EVT_RIGHTCTRL;
- break;
- case KB_leftAlt:
- if (what == EVT_KEYUP)
- EVT.keyModifiers &= ~EVT_LEFTALT;
- else
- EVT.keyModifiers |= EVT_LEFTALT;
- break;
- case KB_rightAlt:
- if (what == EVT_KEYUP)
- EVT.keyModifiers &= ~EVT_RIGHTALT;
- else
- EVT.keyModifiers |= EVT_RIGHTALT;
- break;
- #ifdef SUPPORT_CTRL_ALT_DEL
- case KB_delete:
- if ((EVT.keyModifiers & EVT_CTRLSTATE) && (EVT.keyModifiers & EVT_ALTSTATE))
- Reboot();
- break;
- #endif
- }
- }
- /* Add the untranslated key code to the event queue. All
- * translation to ASCII from the key codes occurs when the key
- * is extracted from the queue, saving time in the low level
- * interrupt handler.
- */
- addKeyEvent(what,scan << 8);
- }
- }
- /****************************************************************************
- DESCRIPTION:
- Enables/disables the update of the keyboard LED status indicators.
- HEADER:
- event.h
- PARAMETERS:
- enable - True to enable, false to disable
- REMARKS:
- Enables the update of the keyboard LED status indicators. Sometimes it may
- be convenient in the application to turn off the updating of the LED
- status indicators (such as if a game is using the CAPSLOCK key for some
- function). Passing in a value of FALSE to this function will turn off all
- the LEDS, and stop updating them when the internal status changes (note
- however that internally we still keep track of the toggle key status!).
- ****************************************************************************/
- void EVTAPI EVT_allowLEDS(
- ibool enable)
- {
- EVT.allowLEDS = true;
- if (enable)
- setLEDS(EVT.keyModifiers);
- else
- setLEDS(0);
- EVT.allowLEDS = enable;
- }
|