/**[txh]******************************************************************** Keyboard module, Copyright 2001-2003 by Salvador E. Tropea Description: This is the base class for keyboard input. Most members are pointers to functions defined by each platform dependent driver. Default members are provided. This is a complete new file created from concepts that José Angel Sanchez Caso provide me and coded from scratch. Original Turbo Vision didn't even have such a class. ***************************************************************************/ #define Uses_TEvent #define Uses_TGKey #define Uses_TVCodePage #define Uses_FullSingleKeySymbols #define Uses_ctype #define Uses_string #define Uses_stdlib #include /***************************************************************************** Data members initialization *****************************************************************************/ char TGKey::suspended=1; ushort TGKey::AltSet=0; // Default: Left and right key are different ones int TGKey::Mode=0; int TGKey::inputMode=TGKey::codepage; char *TGKey::KeyNames[]= { "Unknown", "A","B","C","D","E","F","G","H","I","J","K", "L","M","N","O","P","Q","R","S","T","U","V", "W","X","Y","Z", "OpenBrace","BackSlash","CloseBrace","Pause","Esc", "0","1","2","3","4","5","6","7","8","9", "BackSpace","Tab","Enter","Colon","Quote","Grave", "Comma","Stop","Slash","Asterisk","Space","Minus", "Plus","PrnScr","Equal","F1","F2","F3","F4","F5", "F6","F7","F8","F9","F10","F11","F12","Home", "Up","PgUp","Left","Right","End","Down","PgDn", "Insert","Delete","Caret","Admid","DobleQuote", "Numeral","Dolar","Percent","Amper","OpenPar", "ClosePar","DoubleDot","LessThan","GreaterThan", "Question","A_Roba","Or","UnderLine","OpenCurly", "CloseCurly","Tilde","Macro","WinLeft","WinRight","WinSel", "Mouse" }; #define NumKeyNames (sizeof(TGKey::KeyNames)/sizeof(char *)) /***************************************************************************** Function pointer members initialization *****************************************************************************/ int (*TGKey::kbhit)(void) =defaultKbhit; void (*TGKey::clear)(void) =defaultClear; ushort (*TGKey::gkey)() =defaultGkey; unsigned (*TGKey::getShiftState)() =defaultGetShiftState; void (*TGKey::fillTEvent)(TEvent &e) =defaultFillTEvent; uchar (*TGKey::NonASCII2ASCII)(uchar val) =defaultNonASCII2ASCII; int (*TGKey::CompareASCII)(uchar val, uchar code)=defaultCompareASCII; void (*TGKey::SetKbdMapping)(int version) =defaultSetKbdMapping; int (*TGKey::GetKbdMapping)(int version) =defaultGetKbdMapping; void (*TGKey::Suspend)() =defaultSuspend; void (*TGKey::Resume)() =defaultResume; int (*TGKey::SetCodePage)(int id) =defaultSetCodePage; int (*TGKey::AltInternat2ASCII)(TEvent &event) =defaultAltInternat2ASCII; void (*TGKey::fillCharCode)(TEvent &e) =defaultFillCharCode; /***************************************************************************** Default behaviors for the members *****************************************************************************/ int TGKey::defaultKbhit() { return 0; } unsigned TGKey::defaultGetShiftState() { return 0; } ushort TGKey::defaultGkey() { return 0; } void TGKey::defaultClear() {} void TGKey::defaultSuspend() {} void TGKey::defaultResume() {} uchar TGKey::defaultNonASCII2ASCII(uchar val) { return val; } int TGKey::defaultCompareASCII(uchar val, uchar code) { return val==code; } void TGKey::defaultSetKbdMapping(int version) { Mode=version; } int TGKey::defaultGetKbdMapping(int /*version*/) { return Mode; } void TGKey::defaultFillTEvent(TEvent &/*e*/) {}; /***************************************************************************** Real members *****************************************************************************/ void TGKey::suspend() { if (suspended) return; suspended=1; Suspend(); } void TGKey::resume() { if (!suspended) return; suspended=0; Resume(); } const char *TGKey::NumberToKeyName(unsigned val) { if (val' },{ 0x042f,'Z' },{ 0x0430,'f' },{ 0x0431,',' },{ 0x0432,'d' }, { 0x0433,'u' },{ 0x0434,'L' },{ 0x0435,'t' },{ 0x0436,';' },{ 0x0437,'p' }, { 0x0438,'b' },{ 0x0439,'q' },{ 0x043a,'r' },{ 0x043b,'K' },{ 0x043c,'v' }, { 0x043d,'y' },{ 0x043e,'j' },{ 0x043f,'g' },{ 0x0440,'h' },{ 0x0441,'c' }, { 0x0442,'n' },{ 0x0443,'e' },{ 0x0444,'a' },{ 0x0445,'[' },{ 0x0446,'w' }, { 0x0447,'x' },{ 0x0448,'i' },{ 0x0449,'o' },{ 0x044a,'}' },{ 0x044b,'s' }, { 0x044c,'m' },{ 0x044d,'\'' },{ 0x044e,'.' },{ 0x044f,'z' } }; int TGKey::defaultSetCodePage(int id) { switch (id) { case TVCodePage::PC855: case TVCodePage::PC866: case TVCodePage::ISORussian: case TVCodePage::KOI8r: case TVCodePage::KOI8_CRL_NMSU: case TVCodePage::CP1251: case TVCodePage::MacCyr: case TVCodePage::MacOSUkrainian: // Not sure about the rest of russian code pages. FillKeyMapForCP(id,RussianKeyboard,sizeof(RussianKeyboard)/sizeof(stIntCodePairs)); NonASCII2ASCII=Generic_NonASCII2ASCII; CompareASCII=Generic_CompareASCII; AltInternat2ASCII=Generic_AltInternat2ASCII; break; case TVCodePage::PC737: case TVCodePage::PC869: case TVCodePage::CP1253: case TVCodePage::ISOGreek: FillKeyMapForCP(id,GreekKeyboard,sizeof(GreekKeyboard)/sizeof(stIntCodePairs)); NonASCII2ASCII=Generic_NonASCII2ASCII; CompareASCII=Generic_CompareASCII; AltInternat2ASCII=Generic_AltInternat2ASCII; break; default: NonASCII2ASCII=defaultNonASCII2ASCII; CompareASCII=defaultCompareASCII; AltInternat2ASCII=defaultAltInternat2ASCII; return 0; } return 1; } uchar TGKey::KeyMap[128]; static int compare(const void *v1, const void *v2) { stIntCodePairs *p1=(stIntCodePairs *)v1; stIntCodePairs *p2=(stIntCodePairs *)v2; return (p1->unicode>p2->unicode)-(p1->unicodeunicode); } /**[txh]******************************************************************** Description: Fills the KeyMap table using the provided keyboard layout. ***************************************************************************/ void TGKey::FillKeyMapForCP(int id, stIntCodePairs *keyboard, size_t szKb) { stIntCodePairs cp[256]; TVCodePage::GetUnicodesForCP(id,cp); ushort *tr=TVCodePage::GetTranslate(id); int i; stIntCodePairs s; for (i=128; i<256; i++) { s.unicode=TVCodePage::UnicodeForInternalCode(tr[i]); void *res=bsearch(&s,keyboard,szKb,sizeof(stIntCodePairs),compare); KeyMap[i-128]=res ? ((stIntCodePairs *)res)->code : i; } } uchar TGKey::Generic_NonASCII2ASCII(uchar ascii) { return ascii>=0x80 ? KeyMap[ascii-0x80] : ascii; } int TGKey::Generic_CompareASCII(uchar val, uchar code) { if (val >=0x80) val =KeyMap[val- 0x80]; if (code>=0x80) code=KeyMap[code-0x80]; return val==code; } int TGKey::defaultAltInternat2ASCII(TEvent &) { return 0; } #if 0 #define SP1 kbBackSpace #define SP2 kbTab #define SP3 kbEnter #define SP4 kbEnter #define SP5 kbEsc #else #define SP1 0x80 | kbH #define SP2 0x80 | kbI #define SP3 0x80 | kbJ #define SP4 0x80 | kbM #define SP5 0x80 | kbOpenBrace #endif const uchar TGKey::kbByASCII[128]= { 0,kbA,kbB,kbC,kbD,kbE,kbF,kbG, SP1,SP2,SP3,kbK,kbL,SP4,kbN,kbO, kbP,kbQ,kbR,kbS,kbT,kbU,kbV,kbW, kbX,kbY,kbZ,SP5,kbBackSlash,kbCloseBrace,kb6,kbMinus, kbSpace,kbAdmid,kbDobleQuote,kbNumeral,kbDolar,kbPercent,kbAmper,kbQuote, kbOpenPar,kbClosePar,kbAsterisk,kbPlus,kbComma,kbMinus,kbStop,kbSlash, kb0,kb1,kb2,kb3,kb4,kb5,kb6,kb7, kb8,kb9,kbDoubleDot,kbColon,kbLessThan,kbEqual,kbGreaterThan,kbQuestion, kbA_Roba,kbA,kbB,kbC,kbD,kbE,kbF,kbG, kbH,kbI,kbJ,kbK,kbL,kbM,kbN,kbO, kbP,kbQ,kbR,kbS,kbT,kbU,kbV,kbW, kbX,kbY,kbZ,kbOpenBrace,kbBackSlash,kbCloseBrace,kbCaret,kbUnderLine, kbGrave,kbA,kbB,kbC,kbD,kbE,kbF,kbG, kbH,kbI,kbJ,kbK,kbL,kbM,kbN,kbO, kbP,kbQ,kbR,kbS,kbT,kbU,kbV,kbW, kbX,kbY,kbZ,kbOpenCurly,kbOr,kbCloseCurly,kbTilde,kbBackSpace }; /**[txh]******************************************************************** Description: When using a "non-ASCII" keyboard the application gets Alt+Non-ASCII. This routine tries to figure out which key was used and changes the event to be Alt+ASCII. Example: A greek keyboard can generate Alt+Alfa, in this case the routine will convert it into Alt+A (because Alfa is in the key that A is located). Return: !=0 if the event was altered. ***************************************************************************/ int TGKey::Generic_AltInternat2ASCII(TEvent &e) { if (e.what==evKeyDown && e.keyDown.charScan.charCode>=0x80 && (e.keyDown.keyCode & (kbAltRCode | kbAltLCode)) && (e.keyDown.keyCode & kbKeyMask)==kbUnkNown) { uchar key=KeyMap[e.keyDown.charScan.charCode-0x80]; if (key<0x80) { e.keyDown.keyCode|=kbByASCII[key]; return 1; } } return 0; } /**[txh]******************************************************************** Description: Used by objects that needs the TEvent.keyDown.charCode filled. ***************************************************************************/ void TGKey::defaultFillCharCode(TEvent &e) { if (e.keyDown.charCode!=0xFFFFFFFF && e.keyDown.charScan.charCode) e.keyDown.charCode=TVCodePage::convertInpCP_2_U16(e.keyDown.charScan.charCode); }