// This may look like C code, but it is really -*- C++ -*- // ------------------------------------------------------------------ // The Goldware Library // Copyright (C) 1990-1999 Odinn Sorensen // ------------------------------------------------------------------ // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library 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 // Library General Public License for more details. // // You should have received a copy of the GNU Library General Public // License along with this program; if not, write to the Free // Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, // MA 02111-1307, USA // ------------------------------------------------------------------ // $Id$ // ------------------------------------------------------------------ // Keyboard functions. // ------------------------------------------------------------------ #include #include #include #include #include #ifdef GOLD_MOUSE #include #endif // ------------------------------------------------------------------ // Event sources const int GEVT_KEYBOARD = 0; const int GEVT_BUFFER = 1; const int GEVT_MOUSE = 2; const int GEVT_TICK = 3; // ------------------------------------------------------------------ void gkbdtickpressreset() { gkbd.tickpress = gclock(); } // ------------------------------------------------------------------ void gkbdtickvaluereset() { gkbd.tickvalue = gclock(); } // ------------------------------------------------------------------ gkey kbmhit() { gkey k; // Check for keypress in internal buffer or keyboard if(gkbd.kbuf) { gkbd.source = GEVT_BUFFER; k = gkbd.kbuf->xch; } else { gkbd.source = GEVT_KEYBOARD; k = kbxhit(); } return k; } // ------------------------------------------------------------------ static void kbd_call_func(VfvCP func) { int row, col; bool hidden = vcurhidden(); vposget(&row,&col); _menu_t* menu = gwin.cmenu; (*func)(); gwin.cmenu = menu; vposset(row,col); if(hidden) vcurhide(); else vcurshow(); } // ------------------------------------------------------------------ static _item_t* find_hotkey(_menu_t* wmenu, gkey xch) { _item_t* witem; _item_t* item; // do while more items in this menu for(witem=wmenu->item; witem!=NULL; witem=witem->prev) { // if hot key matches keypress, return its item address if(witem->hotkey==xch and (!(witem->fmask&M_NOSEL)) and witem->select!=NULL) return witem; // if current item has a child menu, process it if(witem->child!=NULL) { item = find_hotkey((_menu_t*)witem->child, xch); if(item!=NULL) return item; } } // return address of item found return witem; } // ------------------------------------------------------------------ static void makeextkey(gkey xshift, gkey& xkey) { switch(xkey) { case Key_Home: case Key_C_Home: if(xshift & ALT) xkey = Key_A_HomeG; if(xshift & (LSHIFT | RSHIFT)) KCodScn(xkey) |= 0x80; break; case Key_End: case Key_C_End: if(xshift & ALT) xkey = Key_A_EndG; if(xshift & (LSHIFT | RSHIFT)) KCodScn(xkey) |= 0x80; break; case Key_Up: if(xshift & ALT) xkey = Key_A_UpG; else if(xshift & GCTRL) xkey = Key_C_Up; if(xshift & (LSHIFT | RSHIFT)) KCodScn(xkey) |= 0x80; break; case Key_Dwn: if(xshift & ALT) xkey = Key_A_DwnG; else if(xshift & GCTRL) xkey = Key_C_Dwn; if(xshift & (LSHIFT | RSHIFT)) KCodScn(xkey) |= 0x80; break; case Key_Lft: if(xshift & ALT) xkey = Key_A_LftG; if(xshift & (LSHIFT | RSHIFT)) KCodScn(xkey) |= 0x80; break; case Key_Rgt: if(xshift & ALT) xkey = Key_A_RgtG; if(xshift & (LSHIFT | RSHIFT)) KCodScn(xkey) |= 0x80; break; case Key_PgUp: if(xshift & ALT) xkey = Key_A_PgUpG; if(xshift & (LSHIFT | RSHIFT)) KCodScn(xkey) |= 0x80; break; case Key_PgDn: if(xshift & ALT) xkey = Key_A_PgDnG; if(xshift & (LSHIFT | RSHIFT)) KCodScn(xkey) |= 0x80; break; case Key_Ins: if(xshift & ALT) xkey = Key_A_InsG; else if(xshift & GCTRL) xkey = Key_C_Ins; if(xshift & (LSHIFT | RSHIFT)) KCodScn(xkey) |= 0x80; break; case Key_Del: if(xshift & ALT) xkey = Key_A_DelG; else if(xshift & GCTRL) xkey = Key_C_Del; if(xshift & (LSHIFT | RSHIFT)) KCodScn(xkey) |= 0x80; break; } } // ------------------------------------------------------------------ extern int blanked; gkey getxch(int __tick) { gkey k; while(1) { // Keyboard polling loop if(gkbd.polling) { while(not kbmhit()) { Clock thistick = gclock(); long tickdiff = thistick - gkbd.tickvalue; if(tickdiff < 0) { gkbd.tickvalue = thistick; tickdiff = gkbd.tickinterval + 1; } if(tickdiff > gkbd.tickinterval) { gkbd.tickvalue = thistick; if(gkbd.tickfunc) { gkbd.inidle = true; (*gkbd.tickfunc)(); gkbd.inidle = false; } if(__tick) kbput(Key_Tick); } if(gmtsk.detected) gmtsk.timeslice(); } } // Get key from internal buffer or keyboard if(gkbd.kbuf) { gkbd.source = GEVT_BUFFER; k = gkbd.kbuf->xch; KBuf* _kbuf = gkbd.kbuf->next; throw_free(gkbd.kbuf); gkbd.kbuf = _kbuf; if(gkbd.kbuf) gkbd.kbuf->prev = NULL; } else { gkbd.source = GEVT_KEYBOARD; k = kbxget(); gkey s = kbxget(2); // Read shift status if(not gkbd.extkbd) { if(s & (LSHIFT|RSHIFT|GCTRL|ALT)) makeextkey(s,k); } } // Note time of keypress unless it's a tick if(k != Key_Tick) gkbdtickpressreset(); // Search through onkey linked list for a // matching defined onkey. If one is found, // then save the current environment, call the // onkey's function, and restore the environment. if(not blanked) { KBnd* _onkey = gkbd.onkey; while(_onkey) { if(_onkey->keycode == k) { gkbd.curronkey = _onkey; kbd_call_func(_onkey->func); #ifdef GOLD_MOUSE if(gkbd.inmenu and gmou.FreeCursor()) return 0; #endif break; } _onkey = _onkey->prev; } if(_onkey) { if(not _onkey->pass or (_onkey->pass >= 0xFE00)) k = 0; else k = _onkey->pass; } else { // Search for a menu hot key. If one is found, // then save the current environment, call the // hotkey's function, and restore the environment. if(gwin.menu) { _item_t* item = find_hotkey(gwin.menu,k); if(item) { gwin.menu->hotkey = true; kbd_call_func(item->select); #ifdef GOLD_MOUSE if(gkbd.inmenu and gmou.FreeCursor()) return 0; #endif k = 0; } } } } // If we still have a keycode, exit the loop if(k) break; } // Return keycode return k; } // ------------------------------------------------------------------