00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "keytrans.h"
00027
00028 #include <qpe/qpeapplication.h>
00029
00030 #include <qnamespace.h>
00031 #include <qbuffer.h>
00032 #include <qobject.h>
00033 #include <qdict.h>
00034 #include <qintdict.h>
00035 #include <qfile.h>
00036 #include <qglobal.h>
00037 #include <qdir.h>
00038
00039
00040
00041
00042 #include <stdio.h>
00043
00044
00045 #undef USE_APPDATA_DIR
00046
00047
00048 #define HERE printf("%s(%d): here\n",__FILE__,__LINE__)
00049
00050
00051
00052
00053
00054
00055 KeyTrans::KeyEntry::KeyEntry(int _ref, int _key, int _bits, int _mask, int _cmd, QString _txt)
00056 : ref(_ref), key(_key), bits(_bits), mask(_mask), cmd(_cmd), txt(_txt)
00057 {
00058 }
00059
00060 KeyTrans::KeyEntry::~KeyEntry()
00061 {
00062 }
00063
00064 bool KeyTrans::KeyEntry::matches(int _key, int _bits, int _mask)
00065 { int m = mask & _mask;
00066 return _key == key && (bits & m) == (_bits & m);
00067 }
00068
00069 QString KeyTrans::KeyEntry::text()
00070 {
00071 return txt;
00072 }
00073
00074
00075
00076
00077
00078
00079
00080 KeyTrans::KeyTrans()
00081 {
00082 path = "";
00083 numb = 0;
00084 }
00085
00086 KeyTrans::~KeyTrans()
00087 {
00088 }
00089
00090 KeyTrans::KeyEntry* KeyTrans::addEntry(int ref, int key, int bits, int mask, int cmd, QString txt)
00091
00092 {
00093 for (QListIterator<KeyEntry> it(table); it.current(); ++it)
00094 {
00095 if (it.current()->matches(key,bits,mask))
00096 {
00097 return it.current();
00098 }
00099 }
00100 table.append(new KeyEntry(ref,key,bits,mask,cmd,txt));
00101 return (KeyEntry*)NULL;
00102 }
00103
00104 bool KeyTrans::findEntry(int key, int bits, int* cmd, const char** txt, int* len)
00105 {
00106 for (QListIterator<KeyEntry> it(table); it.current(); ++it)
00107 if (it.current()->matches(key,bits,0xffff))
00108 {
00109 *cmd = it.current()->cmd;
00110 *txt = it.current()->txt.ascii();
00111 *len = it.current()->txt.length();
00112 return TRUE;
00113 }
00114 return FALSE;
00115 }
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131 #define SYMName 0
00132 #define SYMString 1
00133 #define SYMEol 2
00134 #define SYMEof 3
00135 #define SYMOpr 4
00136 #define SYMError 5
00137
00138 #define inRange(L,X,H) ((L <= X) && (X <= H))
00139 #define isNibble(X) (inRange('A',X,'F')||inRange('a',X,'f')||inRange('0',X,'9'))
00140 #define convNibble(X) (inRange('0',X,'9')?X-'0':X+10-(inRange('A',X,'F')?'A':'a'))
00141
00142 class KeytabReader
00143 {
00144 public:
00145 KeytabReader(QString p, QIODevice &d);
00146 public:
00147 void getCc();
00148 void getSymbol();
00149 void parseTo(KeyTrans* kt);
00150 void ReportError(const char* msg);
00151 void ReportToken();
00152 private:
00153 int sym;
00154 QString res;
00155 int len;
00156 int slinno;
00157 int scolno;
00158 private:
00159 int cc;
00160 int linno;
00161 int colno;
00162 QIODevice* buf;
00163 QString path;
00164 };
00165
00166
00167 KeytabReader::KeytabReader(QString p, QIODevice &d)
00168 {
00169 path = p;
00170 buf = &d;
00171 cc = 0;
00172 }
00173
00174 void KeytabReader::getCc()
00175 {
00176 if (cc == '\n') { linno += 1; colno = 0; }
00177 if (cc < 0) return;
00178 cc = buf->getch();
00179 colno += 1;
00180 }
00181
00182 void KeytabReader::getSymbol()
00183 {
00184 res = ""; len = 0; sym = SYMError;
00185 while (cc == ' ') getCc();
00186 if (cc == '#')
00187 {
00188 while (cc != '\n' && cc > 0) getCc();
00189 }
00190 slinno = linno;
00191 scolno = colno;
00192 if (cc <= 0)
00193 {
00194 sym = SYMEof; return;
00195 }
00196 if (cc == '\n')
00197 {
00198 getCc();
00199 sym = SYMEol; return;
00200 }
00201 if (inRange('A',cc,'Z')||inRange('a',cc,'z')||inRange('0',cc,'9'))
00202 {
00203 while (inRange('A',cc,'Z') || inRange('a',cc,'z') || inRange('0',cc,'9'))
00204 {
00205 res = res + (char)cc;
00206 getCc();
00207 }
00208 sym = SYMName;
00209 return;
00210 }
00211 if (strchr("+-:",cc))
00212 {
00213 res = "";
00214 res = res + (char)cc;
00215 getCc();
00216 sym = SYMOpr; return;
00217 }
00218 if (cc == '"')
00219 {
00220 getCc();
00221 while (cc >= ' ' && cc != '"')
00222 { int sc;
00223 if (cc == '\\')
00224 {
00225 getCc();
00226 switch (cc)
00227 {
00228 case 'E' : sc = 27; getCc(); break;
00229 case 'b' : sc = 8; getCc(); break;
00230 case 'f' : sc = 12; getCc(); break;
00231 case 't' : sc = 9; getCc(); break;
00232 case 'r' : sc = 13; getCc(); break;
00233 case 'n' : sc = 10; getCc(); break;
00234 case '\\' :
00235 case '"' : sc = cc; getCc(); break;
00236 case 'x' : getCc();
00237 sc = 0;
00238 if (!isNibble(cc)) return; sc = 16*sc + convNibble(cc); getCc();
00239 if (!isNibble(cc)) return; sc = 16*sc + convNibble(cc); getCc();
00240 break;
00241 default : return;
00242 }
00243 }
00244 else
00245 {
00246
00247 sc = cc; getCc();
00248 }
00249 res = res + (char)sc;
00250 len = len + 1;
00251 }
00252 if (cc != '"') return;
00253 getCc();
00254 sym = SYMString; return;
00255 }
00256 }
00257
00258 void KeytabReader::ReportToken()
00259 {
00260 printf("sym(%d): ",slinno);
00261 switch(sym)
00262 {
00263 case SYMEol : printf("End of line"); break;
00264 case SYMEof : printf("End of file"); break;
00265 case SYMName : printf("Name: %s",res.latin1()); break;
00266 case SYMOpr : printf("Opr : %s",res.latin1()); break;
00267 case SYMString : printf("String len %d,%d ",res.length(),len);
00268 for (unsigned i = 0; i < res.length(); i++)
00269 printf(" %02x(%c)",res.latin1()[i],res.latin1()[i]>=' '?res.latin1()[i]:'?');
00270 break;
00271 }
00272 printf("\n");
00273 }
00274
00275 void KeytabReader::ReportError(const char* msg)
00276 {
00277 fprintf(stderr,"%s(%d,%d):error: %s.\n",path.ascii(),slinno,scolno,msg);
00278 }
00279
00280
00281
00282 class KeyTransSymbols
00283 {
00284 public:
00285 KeyTransSymbols();
00286 protected:
00287 void defOprSyms();
00288 void defModSyms();
00289 void defKeySyms();
00290 void defKeySym(const char* key, int val);
00291 void defOprSym(const char* key, int val);
00292 void defModSym(const char* key, int val);
00293 public:
00294 QDict<QObject> keysyms;
00295 QDict<QObject> modsyms;
00296 QDict<QObject> oprsyms;
00297 };
00298
00299 static KeyTransSymbols * syms = 0L;
00300
00301
00302
00303
00304
00305
00306
00307 KeyTrans* KeyTrans::fromDevice(QString path, QIODevice &buf)
00308 {
00309 KeyTrans* kt = new KeyTrans;
00310 kt->path = path;
00311 KeytabReader ktr(path,buf); ktr.parseTo(kt);
00312 return kt;
00313 }
00314
00315
00316 #define assertSyntax(Cond,Message) if (!(Cond)) { ReportError(Message); goto ERROR; }
00317
00318 void KeytabReader::parseTo(KeyTrans* kt)
00319 {
00320
00321
00322 buf->open(IO_ReadOnly);
00323 getCc();
00324 linno = 1;
00325 colno = 1;
00326 getSymbol();
00327
00328 Loop:
00329
00330 if (sym == SYMName && !strcmp(res.latin1(),"keyboard"))
00331 {
00332 getSymbol(); assertSyntax(sym == SYMString, "Header expected")
00333 kt->hdr = res.latin1();
00334 getSymbol(); assertSyntax(sym == SYMEol, "Text unexpected")
00335 getSymbol();
00336 goto Loop;
00337 }
00338 if (sym == SYMName && !strcmp(res.latin1(),"key"))
00339 {
00340
00341 getSymbol(); assertSyntax(sym == SYMName, "Name expected")
00342 assertSyntax(syms->keysyms[res], "Unknown key name")
00343 int key = (int)syms->keysyms[res]-1;
00344
00345 getSymbol();
00346 int mode = 0;
00347 int mask = 0;
00348 while (sym == SYMOpr && (!strcmp(res.latin1(),"+") || !strcmp(res.latin1(),"-")))
00349 {
00350 bool on = !strcmp(res.latin1(),"+");
00351 getSymbol();
00352
00353 assertSyntax(sym == SYMName, "Name expected")
00354 assertSyntax(syms->modsyms[res], "Unknown mode name")
00355 int bits = (int)syms->modsyms[res]-1;
00356 if (mask & (1 << bits))
00357 {
00358 fprintf(stderr,"%s(%d,%d): mode name used multible times.\n",path.ascii(),slinno,scolno);
00359 }
00360 else
00361 {
00362 mode |= (on << bits);
00363 mask |= (1 << bits);
00364 }
00365
00366 getSymbol();
00367 }
00368 assertSyntax(sym == SYMOpr && !strcmp(res.latin1(),":"), "':' expected")
00369 getSymbol();
00370
00371 assertSyntax(sym == SYMName || sym == SYMString,"Command or string expected")
00372 int cmd = 0;
00373 if (sym == SYMName)
00374 {
00375 assertSyntax(syms->oprsyms[res], "Unknown operator name")
00376 cmd = (int)syms->oprsyms[res]-1;
00377
00378 }
00379 if (sym == SYMString)
00380 {
00381 cmd = CMD_send;
00382
00383
00384
00385 }
00386
00387 KeyTrans::KeyEntry* ke = kt->addEntry(slinno,key,mode,mask,cmd,res);
00388 if (ke)
00389 {
00390 fprintf(stderr,"%s(%d): keystroke already assigned in line %d.\n",path.ascii(),slinno,ke->ref);
00391 }
00392 getSymbol();
00393 assertSyntax(sym == SYMEol, "Unexpected text")
00394 goto Loop;
00395 }
00396 if (sym == SYMEol)
00397 {
00398 getSymbol();
00399 goto Loop;
00400 }
00401
00402 assertSyntax(sym == SYMEof, "Undecodable Line")
00403
00404 buf->close();
00405 return;
00406
00407 ERROR:
00408 while (sym != SYMEol && sym != SYMEof) getSymbol();
00409 goto Loop;
00410 }
00411
00412
00413 KeyTrans* KeyTrans::defaultKeyTrans()
00414 {
00415 QCString txt =
00416 #include "default.keytab.h"
00417 ;
00418 QBuffer buf(txt);
00419 return fromDevice("[buildin]",buf);
00420 }
00421
00422 KeyTrans* KeyTrans::fromFile(const char* path)
00423 {
00424 QFile file(path);
00425 return fromDevice(path,file);
00426 }
00427
00428
00429
00430
00431
00432 void KeyTransSymbols::defKeySym(const char* key, int val)
00433 {
00434 keysyms.insert(key,(QObject*)(val+1));
00435 }
00436
00437 void KeyTransSymbols::defOprSym(const char* key, int val)
00438 {
00439 oprsyms.insert(key,(QObject*)(val+1));
00440 }
00441
00442 void KeyTransSymbols::defModSym(const char* key, int val)
00443 {
00444 modsyms.insert(key,(QObject*)(val+1));
00445 }
00446
00447 void KeyTransSymbols::defOprSyms()
00448 {
00449
00450 defOprSym("scrollLineUp", CMD_scrollLineUp );
00451 defOprSym("scrollLineDown",CMD_scrollLineDown);
00452 defOprSym("scrollPageUp", CMD_scrollPageUp );
00453 defOprSym("scrollPageDown",CMD_scrollPageDown);
00454 defOprSym("emitSelection", CMD_emitSelection );
00455 defOprSym("prevSession", CMD_prevSession );
00456 defOprSym("nextSession", CMD_nextSession );
00457 }
00458
00459 void KeyTransSymbols::defModSyms()
00460 {
00461
00462 defModSym("Shift", BITS_Shift );
00463 defModSym("Control", BITS_Control );
00464 defModSym("Alt", BITS_Alt );
00465
00466 defModSym("BsHack", BITS_BsHack );
00467 defModSym("Ansi", BITS_Ansi );
00468 defModSym("NewLine", BITS_NewLine );
00469 defModSym("AppCuKeys", BITS_AppCuKeys );
00470 }
00471
00472 void KeyTransSymbols::defKeySyms()
00473 {
00474
00475 defKeySym("Escape", Qt::Key_Escape );
00476 defKeySym("Tab", Qt::Key_Tab );
00477 defKeySym("Backtab", Qt::Key_Backtab );
00478 defKeySym("Backspace", Qt::Key_Backspace );
00479 defKeySym("Return", Qt::Key_Return );
00480 defKeySym("Enter", Qt::Key_Enter );
00481 defKeySym("Insert", Qt::Key_Insert );
00482 defKeySym("Delete", Qt::Key_Delete );
00483 defKeySym("Pause", Qt::Key_Pause );
00484 defKeySym("Print", Qt::Key_Print );
00485 defKeySym("SysReq", Qt::Key_SysReq );
00486 defKeySym("Home", Qt::Key_Home );
00487 defKeySym("End", Qt::Key_End );
00488 defKeySym("Left", Qt::Key_Left );
00489 defKeySym("Up", Qt::Key_Up );
00490 defKeySym("Right", Qt::Key_Right );
00491 defKeySym("Down", Qt::Key_Down );
00492 defKeySym("Prior", Qt::Key_Prior );
00493 defKeySym("Next", Qt::Key_Next );
00494 defKeySym("Shift", Qt::Key_Shift );
00495 defKeySym("Control", Qt::Key_Control );
00496 defKeySym("Meta", Qt::Key_Meta );
00497 defKeySym("Alt", Qt::Key_Alt );
00498 defKeySym("CapsLock", Qt::Key_CapsLock );
00499 defKeySym("NumLock", Qt::Key_NumLock );
00500 defKeySym("ScrollLock", Qt::Key_ScrollLock );
00501 defKeySym("F1", Qt::Key_F1 );
00502 defKeySym("F2", Qt::Key_F2 );
00503 defKeySym("F3", Qt::Key_F3 );
00504 defKeySym("F4", Qt::Key_F4 );
00505 defKeySym("F5", Qt::Key_F5 );
00506 defKeySym("F6", Qt::Key_F6 );
00507 defKeySym("F7", Qt::Key_F7 );
00508 defKeySym("F8", Qt::Key_F8 );
00509 defKeySym("F9", Qt::Key_F9 );
00510 defKeySym("F10", Qt::Key_F10 );
00511 defKeySym("F11", Qt::Key_F11 );
00512 defKeySym("F12", Qt::Key_F12 );
00513 defKeySym("F13", Qt::Key_F13 );
00514 defKeySym("F14", Qt::Key_F14 );
00515 defKeySym("F15", Qt::Key_F15 );
00516 defKeySym("F16", Qt::Key_F16 );
00517 defKeySym("F17", Qt::Key_F17 );
00518 defKeySym("F18", Qt::Key_F18 );
00519 defKeySym("F19", Qt::Key_F19 );
00520 defKeySym("F20", Qt::Key_F20 );
00521 defKeySym("F21", Qt::Key_F21 );
00522 defKeySym("F22", Qt::Key_F22 );
00523 defKeySym("F23", Qt::Key_F23 );
00524 defKeySym("F24", Qt::Key_F24 );
00525 defKeySym("F25", Qt::Key_F25 );
00526 defKeySym("F26", Qt::Key_F26 );
00527 defKeySym("F27", Qt::Key_F27 );
00528 defKeySym("F28", Qt::Key_F28 );
00529 defKeySym("F29", Qt::Key_F29 );
00530 defKeySym("F30", Qt::Key_F30 );
00531 defKeySym("F31", Qt::Key_F31 );
00532 defKeySym("F32", Qt::Key_F32 );
00533 defKeySym("F33", Qt::Key_F33 );
00534 defKeySym("F34", Qt::Key_F34 );
00535 defKeySym("F35", Qt::Key_F35 );
00536 defKeySym("Super_L", Qt::Key_Super_L );
00537 defKeySym("Super_R", Qt::Key_Super_R );
00538 defKeySym("Menu", Qt::Key_Menu );
00539 defKeySym("Hyper_L", Qt::Key_Hyper_L );
00540 defKeySym("Hyper_R", Qt::Key_Hyper_R );
00541
00542
00543 defKeySym("Space", Qt::Key_Space );
00544 defKeySym("Exclam", Qt::Key_Exclam );
00545 defKeySym("QuoteDbl", Qt::Key_QuoteDbl );
00546 defKeySym("NumberSign", Qt::Key_NumberSign );
00547 defKeySym("Dollar", Qt::Key_Dollar );
00548 defKeySym("Percent", Qt::Key_Percent );
00549 defKeySym("Ampersand", Qt::Key_Ampersand );
00550 defKeySym("Apostrophe", Qt::Key_Apostrophe );
00551 defKeySym("ParenLeft", Qt::Key_ParenLeft );
00552 defKeySym("ParenRight", Qt::Key_ParenRight );
00553 defKeySym("Asterisk", Qt::Key_Asterisk );
00554 defKeySym("Plus", Qt::Key_Plus );
00555 defKeySym("Comma", Qt::Key_Comma );
00556 defKeySym("Minus", Qt::Key_Minus );
00557 defKeySym("Period", Qt::Key_Period );
00558 defKeySym("Slash", Qt::Key_Slash );
00559 defKeySym("0", Qt::Key_0 );
00560 defKeySym("1", Qt::Key_1 );
00561 defKeySym("2", Qt::Key_2 );
00562 defKeySym("3", Qt::Key_3 );
00563 defKeySym("4", Qt::Key_4 );
00564 defKeySym("5", Qt::Key_5 );
00565 defKeySym("6", Qt::Key_6 );
00566 defKeySym("7", Qt::Key_7 );
00567 defKeySym("8", Qt::Key_8 );
00568 defKeySym("9", Qt::Key_9 );
00569 defKeySym("Colon", Qt::Key_Colon );
00570 defKeySym("Semicolon", Qt::Key_Semicolon );
00571 defKeySym("Less", Qt::Key_Less );
00572 defKeySym("Equal", Qt::Key_Equal );
00573 defKeySym("Greater", Qt::Key_Greater );
00574 defKeySym("Question", Qt::Key_Question );
00575 defKeySym("At", Qt::Key_At );
00576 defKeySym("A", Qt::Key_A );
00577 defKeySym("B", Qt::Key_B );
00578 defKeySym("C", Qt::Key_C );
00579 defKeySym("D", Qt::Key_D );
00580 defKeySym("E", Qt::Key_E );
00581 defKeySym("F", Qt::Key_F );
00582 defKeySym("G", Qt::Key_G );
00583 defKeySym("H", Qt::Key_H );
00584 defKeySym("I", Qt::Key_I );
00585 defKeySym("J", Qt::Key_J );
00586 defKeySym("K", Qt::Key_K );
00587 defKeySym("L", Qt::Key_L );
00588 defKeySym("M", Qt::Key_M );
00589 defKeySym("N", Qt::Key_N );
00590 defKeySym("O", Qt::Key_O );
00591 defKeySym("P", Qt::Key_P );
00592 defKeySym("Q", Qt::Key_Q );
00593 defKeySym("R", Qt::Key_R );
00594 defKeySym("S", Qt::Key_S );
00595 defKeySym("T", Qt::Key_T );
00596 defKeySym("U", Qt::Key_U );
00597 defKeySym("V", Qt::Key_V );
00598 defKeySym("W", Qt::Key_W );
00599 defKeySym("X", Qt::Key_X );
00600 defKeySym("Y", Qt::Key_Y );
00601 defKeySym("Z", Qt::Key_Z );
00602 defKeySym("BracketLeft", Qt::Key_BracketLeft );
00603 defKeySym("Backslash", Qt::Key_Backslash );
00604 defKeySym("BracketRight", Qt::Key_BracketRight);
00605 defKeySym("AsciiCircum", Qt::Key_AsciiCircum );
00606 defKeySym("Underscore", Qt::Key_Underscore );
00607 defKeySym("QuoteLeft", Qt::Key_QuoteLeft );
00608 defKeySym("BraceLeft", Qt::Key_BraceLeft );
00609 defKeySym("Bar", Qt::Key_Bar );
00610 defKeySym("BraceRight", Qt::Key_BraceRight );
00611 defKeySym("AsciiTilde", Qt::Key_AsciiTilde );
00612 }
00613
00614 KeyTransSymbols::KeyTransSymbols()
00615 {
00616 defModSyms();
00617 defOprSyms();
00618 defKeySyms();
00619 }
00620
00621
00622
00623 static int keytab_serial = 0;
00624
00625 static QIntDict<KeyTrans> * numb2keymap = 0L;
00626 static QDict<KeyTrans> * path2keymap = 0L;
00627
00628 KeyTrans* KeyTrans::find(int numb)
00629 {
00630 KeyTrans* res = numb2keymap->find(numb);
00631 return res ? res : numb2keymap->find(0);
00632 }
00633
00634 KeyTrans* KeyTrans::find(const char* path)
00635 {
00636 KeyTrans* res = path2keymap->find(path);
00637 return res ? res : numb2keymap->find(0);
00638 }
00639
00640 int KeyTrans::count()
00641 {
00642 return numb2keymap->count();
00643 }
00644
00645 void KeyTrans::addKeyTrans()
00646 {
00647 this->numb = keytab_serial ++;
00648 numb2keymap->insert(numb,this);
00649 path2keymap->insert(path,this);
00650 }
00651
00652 void KeyTrans::loadAll()
00653 {
00654 if (!numb2keymap)
00655 numb2keymap = new QIntDict<KeyTrans>;
00656 if (!path2keymap)
00657 path2keymap = new QDict<KeyTrans>;
00658 if (!syms)
00659 syms = new KeyTransSymbols;
00660
00661 defaultKeyTrans()->addKeyTrans();
00662
00663
00664 QString path = QPEApplication::qpeDir() + "etc/keytabs";
00665 QDir dir(path);
00666 QStringList lst = dir.entryList("*.keytab");
00667
00668 for(QStringList::Iterator it = lst.begin(); it != lst.end(); ++it ) {
00669 QFile file(path + "/" + *it);
00670 KeyTrans* sc = KeyTrans::fromDevice(*it, file);
00671 if (sc) {
00672 sc->addKeyTrans();
00673 }
00674 }
00675
00676 }
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705