tmapldr.cpp
上传用户:tigerk9
上传日期:2020-03-10
资源大小:237k
文件大小:22k
源码类别:

Telnet客户端

开发平台:

Visual C++

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //Telnet Win32 : an ANSI telnet client.
  3. //Copyright (C) 1998-2000 Paul Brannan
  4. //Copyright (C) 1998 I.Ioannou
  5. //Copyright (C) 1997 Brad Johnson
  6. //
  7. //This program is free software; you can redistribute it and/or
  8. //modify it under the terms of the GNU General Public License
  9. //as published by the Free Software Foundation; either version 2
  10. //of the License, or (at your option) any later version.
  11. //
  12. //This program is distributed in the hope that it will be useful,
  13. //but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. //GNU General Public License for more details.
  16. //
  17. //You should have received a copy of the GNU General Public License
  18. //along with this program; if not, write to the Free Software
  19. //Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. //
  21. //I.Ioannou
  22. //roryt@hol.gr
  23. //
  24. ///////////////////////////////////////////////////////////////////////////
  25. /////////////////////////////////////////////////////////
  26. //     Class TMapLoader - Key/Character Mappings       //
  27. //                      - Loads from telnet.cfg        //
  28. //     originally part of KeyTrans.cpp                 //
  29. /////////////////////////////////////////////////////////
  30. #ifdef __BORLANDC__
  31. #include <fstream.h>
  32. #else
  33. #include <string>
  34. #include <fstream>
  35. #endif
  36. #include "tmapldr.h"
  37. #include "tnerror.h"
  38. #include "tnconfig.h"
  39. // It's probably a good idea to turn off the "identifier was truncated" warning
  40. // in MSVC (Paul Brannan 5/25/98)
  41. #ifdef _MSC_VER
  42. #pragma warning(disable: 4786)
  43. #endif
  44. // AVS
  45. // skip inline comments, empty lines
  46. static char * getline(istream& i, char* buf, int size){
  47. int len = 0;
  48. while (1) {
  49. memset(buf,0,size);
  50. if (i.eof()) break;
  51. i.getline(buf,size,'n');
  52. while (buf[len]) {
  53. if ( /*(buf[len]>=0) &&*/ buf[len]< ' ' ) buf[len] = ' ';
  54. len++;
  55. };
  56. len = 0;
  57. // not so fast, but work ;)
  58. while ( buf[len] ) {
  59.             if ( (buf[len] == ' ') && (buf[len+1] == ' ')) {
  60. memmove(buf+len, buf+len+1, strlen(buf+len));
  61.             } else len++;
  62. };
  63. if (buf[0] == ' ') memmove(buf, buf+1, size-1);
  64. // empty or comment
  65. if ((buf[0]==0)||(buf[0]==';')) continue;
  66. len = 0; // look for comment like this one
  67. while (buf[len])
  68. if ((buf[len] == '/') && (buf[len+1] == '/')) buf[len] = 0;
  69. else len++;
  70. if (len && (buf[len-1] == ' ')) {
  71.                 len--;
  72.                 buf[len]=0;
  73. };
  74. // in case for comment like this one (in line just a comment)
  75. if (buf[0]==0) continue;
  76. break;
  77. };
  78. return (buf);
  79. };
  80. //AVS
  81. // use string as FIFO queue for lines
  82. static int getline(string&str, char* buf, size_t sz) {
  83. if ( !str.length() ) return 0;
  84. const char * p = strchr(str.c_str(),'n');
  85. unsigned int len; // Changed to unsigned (Paul Brannan 6/23/98)
  86. if ( p==NULL )
  87. len = str.length();
  88. else
  89. len = p - str.c_str();
  90. len = len<sz?len:sz-1;
  91. strncpy(buf,str.c_str(), len);
  92. buf[len]=0;
  93. // DJGPP also uses erase rather than remove (Paul Brannan 6/23/98)
  94. #ifndef __BORLANDC__
  95. str.erase(0, len + 1);
  96. #else
  97. str.remove(0,len+1);
  98. #endif
  99. return 1;
  100. };
  101. //AVS
  102. // parse nnn and Xhh
  103. static int getbyte(const char*str) {
  104. unsigned char retval = 0;
  105. int base = 10;
  106. int readed = 0;
  107. if ( (*str == 'x') || (*str == 'X') ) {
  108. base = 16;
  109. readed++;
  110. };
  111. while (readed != 3 && str[readed]) {
  112. unsigned char ch = toupper(str[readed]);
  113. if ( isdigit(ch) ) {
  114. retval = retval*base + (ch -'0');
  115. } else if (base == 16 && ch >= 'A' && ch <= 'F') {
  116. retval = retval*base + (ch-'A'+10);
  117. } else {
  118. return -1;
  119. };
  120. readed++;
  121. };
  122. // Ioannou: If we discard the 0x00 we can't undefine a key !!!
  123. //  if ( retval == 0 ) {
  124. //     return -1;
  125. //  };
  126. return retval;
  127. };
  128. //AVS
  129. // a little optimization
  130. DWORD Fix_ControlKeyState(char * Next_Token) {
  131. if (stricmp(Next_Token, "RIGHT_ALT" ) == 0) return RIGHT_ALT_PRESSED;
  132. if (stricmp(Next_Token, "LEFT_ALT"  ) == 0) return LEFT_ALT_PRESSED;
  133. if (stricmp(Next_Token, "RIGHT_CTRL") == 0) return RIGHT_CTRL_PRESSED;
  134. if (stricmp(Next_Token, "LEFT_CTRL" ) == 0) return LEFT_CTRL_PRESSED;
  135. if (stricmp(Next_Token, "SHIFT"     ) == 0) return SHIFT_PRESSED;
  136. if (stricmp(Next_Token, "NUMLOCK"   ) == 0) return NUMLOCK_ON;
  137. if (stricmp(Next_Token, "SCROLLLOCK") == 0) return SCROLLLOCK_ON;
  138. if (stricmp(Next_Token, "CAPSLOCK"  ) == 0) return CAPSLOCK_ON;
  139. if (stricmp(Next_Token, "ENHANCED"  ) == 0) return ENHANCED_KEY;
  140. // Paul Brannan 5/27/98
  141. if (stricmp(Next_Token, "APP_KEY"   ) == 0) return APP_KEY;
  142. // Paul Brannan 6/28/98
  143. if (stricmp(Next_Token, "APP2_KEY"  ) == 0) return APP2_KEY;
  144. // Paul Brannan 8/28/98
  145. if (stricmp(Next_Token, "APP3_KEY"  ) == 0) return APP3_KEY;
  146. // Paul Brannan 12/9/98
  147. if (stricmp(Next_Token, "APP4_KEY"  ) == 0) return APP4_KEY;
  148. return 0;
  149. }
  150. // AVS
  151. // rewrited to suppert xhh notation, a little optimized
  152. char* Fix_Tok(char * tok) {
  153. static char s[256];
  154. int i,j,n;
  155. // setmem is nonstandard; memset is standard (Paul Brannan 5/25/98)
  156. memset(s, 0, 256);
  157. //  setmem(s, 256, 0);
  158. i = j = n = 0;
  159. if ( tok != NULL ) {
  160. for ( ; tok[i] != 0; ) {
  161. switch ( tok[i] ) {
  162. case '\' :
  163. switch ( tok[i+1] ) {
  164. case '\':
  165. s[j++] = '\';
  166. i += 2;
  167. break;
  168. default:
  169. n = getbyte(tok+i+1);
  170. if ( n < 0 )
  171. s[j++] = tok[i++];
  172. else {
  173. s[j++]=n;
  174. i += 4;
  175. } ;
  176. break;
  177. };
  178. break;
  179. case '^' :
  180.                     if ( tok[i+1] >= '@' ) {
  181. s[j++] = tok[i+1] - '@';
  182. i += 2;
  183. break;
  184.                     }
  185. default  :
  186.                     s[j++] = tok[i++];
  187. }
  188. }
  189. }
  190. return s;
  191. };
  192. // AVS
  193. // perform 'normalization' for lines like [some text], and some checks
  194. // maybe it will be done faster - but no time for it
  195. int normalizeSplitter(string& buf) {
  196.     if ( buf.length() <= 2 ) return 0;
  197.     if ( buf[0] == '[' && buf[buf.length()-1] == ']' ) {
  198. while ( buf[1] == ' ' )
  199. // DJGPP also uses erase rather than remove (Paul Brannan 6/23/98)
  200. #ifndef __BORLANDC__
  201. buf.erase(1, 1);
  202. #else
  203. buf.remove(1,1);
  204. #endif
  205. while ( buf[buf.length()-2] == ' ' )
  206. // Paul Brannan 6/23/98
  207. #ifndef __BORLANDC__
  208. buf.erase(buf.length()-2,1);
  209. #else
  210. buf.remove(buf.length()-2,1);
  211. #endif
  212. return 1;
  213.     }
  214.     return 0;
  215. };
  216. // AVS
  217. // looking for part in string array, see Load(..) for more info
  218. int TMapLoader::LookForPart(stringArray& sa, const char* partType, const char* partName) {
  219.     if ( !sa.IsEmpty() ) {
  220. string cmpbuf("[");
  221. cmpbuf += partType;
  222. cmpbuf += " ";
  223. cmpbuf += partName;
  224. cmpbuf += "]";
  225. normalizeSplitter(cmpbuf); // if no parttype, [global] for example
  226. int max = sa.GetItemsInContainer();
  227. for ( int i = 0; i<max; i++ )
  228. // I found some strange behavior if strnicmp was used here
  229.             if (strnicmp(cmpbuf.c_str(),sa[i].c_str(),cmpbuf.length()) == 0)
  230. return i;
  231.     };
  232.     return INT_MAX;
  233. };
  234. // AVS
  235. // load globals to 'globals'
  236. // in buf must be a [global] part of input file
  237. int TMapLoader::LoadGlobal(string& buf) {
  238. char wbuf[128];
  239. while ( buf.length() ) {
  240. wbuf[0]=0;
  241. if (!getline(buf,wbuf,sizeof(wbuf))) break;
  242. if ( wbuf[0]==0 ) break;
  243. char* Name = strtok(wbuf, TOKEN_DELIMITERS);
  244. if ( stricmp(Name, "[global]")==0 ) continue;
  245. char* Value = strtok(NULL, TOKEN_DELIMITERS);
  246. if ( Value == NULL ) {
  247. //              cerr << "[global] -> no value for " << Name << endl;
  248. printm(0, FALSE, MSG_KEYNOVAL, Name);
  249. continue;
  250. };
  251. int val = atoi(Value);
  252. if ( val > 0 && val <= 0xff ) {
  253. if ( !KeyTrans.AddGlobalDef(val, Name)) return 0;
  254. }
  255. else {
  256. //             cerr << "[global] -> bad value for " << Name << endl;
  257. printm(0, FALSE, MSG_KEYBADVAL, Name);
  258. continue;
  259. };
  260. };
  261. return 1;
  262. };
  263. // AVS
  264. // perform parsing of strings like 'VK_CODE shifts text'
  265. // returns text on success
  266. char* TMapLoader::ParseKeyDef(const char* buf, WORD& vk_code, DWORD& control) {
  267. char wbuf[256];
  268. strcpy(wbuf,buf);
  269. char* ptr = strtok(wbuf, TOKEN_DELIMITERS);
  270. if ( ptr == NULL ) return NULL;
  271. int i = KeyTrans.LookOnGlobal(ptr);
  272. if ( i == INT_MAX ) return NULL;
  273. vk_code = KeyTrans.GetGlobalCode(i);
  274. control = 0;
  275. DWORD st;
  276. while (1) {
  277. ptr = strtok(NULL, TOKEN_DELIMITERS);
  278. if ((ptr == NULL) || ((st = Fix_ControlKeyState(ptr)) == 0)) break;
  279. control |= st;
  280. };
  281. if ( ptr == NULL ) return NULL;
  282. return Fix_Tok(ptr);
  283. };
  284. // AVS
  285. // load keymap to current map
  286. // be aware - buf must passed by value, its destroyed
  287. int TMapLoader::LoadKeyMap(string buf) {
  288. char wbuf[128];
  289. WORD vk_code;
  290. DWORD control;
  291. int i;
  292. // Paul Brannan Feb. 22, 1999
  293. strcpy(wbuf, "VK_");
  294. wbuf[4] = 0;
  295. wbuf[3] = ini.get_escape_key();
  296. i = KeyTrans.LookOnGlobal(wbuf);
  297. if (i != INT_MAX) {
  298. KeyTrans.AddKeyDef(KeyTrans.GetGlobalCode(i), RIGHT_ALT_PRESSED, TN_ESCAPE);
  299. KeyTrans.AddKeyDef(KeyTrans.GetGlobalCode(i), LEFT_ALT_PRESSED, TN_ESCAPE);
  300. }
  301. wbuf[3] = ini.get_scrollback_key();
  302. i = KeyTrans.LookOnGlobal(wbuf);
  303. if (i != INT_MAX) {
  304. KeyTrans.AddKeyDef(KeyTrans.GetGlobalCode(i), RIGHT_ALT_PRESSED, TN_SCROLLBACK);
  305. KeyTrans.AddKeyDef(KeyTrans.GetGlobalCode(i), LEFT_ALT_PRESSED, TN_SCROLLBACK);
  306. }
  307. wbuf[3] = ini.get_dial_key();
  308. i = KeyTrans.LookOnGlobal(wbuf);
  309. if (i != INT_MAX) {
  310. KeyTrans.AddKeyDef(KeyTrans.GetGlobalCode(i), RIGHT_ALT_PRESSED, TN_DIAL);
  311. KeyTrans.AddKeyDef(KeyTrans.GetGlobalCode(i), LEFT_ALT_PRESSED, TN_DIAL);
  312. }
  313. KeyTrans.AddKeyDef(VK_INSERT, SHIFT_PRESSED, TN_PASTE);
  314. while ( buf.length() ) {
  315. wbuf[0] = 0;
  316. if (!getline(buf,wbuf,sizeof(wbuf))) break;
  317. if ( wbuf[0]==0 ) break;
  318. if ( strnicmp(wbuf,"[keymap",7)==0 ) continue;
  319. char * keydef = ParseKeyDef(wbuf,vk_code,control);
  320. if ( keydef != NULL ) {
  321. // Check to see if keydef is a "special" code (Paul Brannan 3/29/00)
  322. if(!strnicmp(keydef, "\tn_escape", strlen("\tn_escape"))) {
  323. if(!KeyTrans.AddKeyDef(vk_code, control, TN_ESCAPE)) return 0;
  324. } else if(!strnicmp(keydef, "\tn_scrollback", strlen("\tn_scrollback"))) {
  325. if(!KeyTrans.AddKeyDef(vk_code, control, TN_SCROLLBACK)) return 0;
  326. } else if(!strnicmp(keydef, "\tn_dial", strlen("\tn_dial"))) {
  327. if(!KeyTrans.AddKeyDef(vk_code, control, TN_DIAL)) return 0;
  328. } else if(!strnicmp(keydef, "\tn_paste", strlen("\tn_paste"))) {
  329. if(!KeyTrans.AddKeyDef(vk_code, control, TN_PASTE)) return 0;
  330. } else if(!strnicmp(keydef, "\tn_null", strlen("\tn_null"))) {
  331. if(!KeyTrans.AddKeyDef(vk_code, control, TN_NULL)) return 0;
  332. } else if(!strnicmp(keydef, "\tn_cr", strlen("\tn_cr"))) {
  333. if(!KeyTrans.AddKeyDef(vk_code, control, TN_CR)) return 0;
  334. } else if(!strnicmp(keydef, "\tn_crlf", strlen("\tn_crlf"))) {
  335. if(!KeyTrans.AddKeyDef(vk_code, control, TN_CRLF)) return 0;
  336. } else 
  337. if(!KeyTrans.AddKeyDef(vk_code,control,keydef)) return 0;
  338. // else DeleteKeyDef() ???? - I'm not sure...
  339. }
  340. };
  341. return 1;
  342. };
  343. // AVS
  344. // load [charmap ...] part to xlat
  345. int TMapLoader::LoadCharMap(string buf) {
  346. char wbuf[128];
  347. char charmapname[128];
  348. charmapname[0] = 0;
  349. //        xlat.init(); now it done by KeyTranslator::Load()
  350. while ( buf.length() ) {
  351. wbuf[0]=0;
  352. if (!getline(buf,wbuf,sizeof(wbuf))) break;
  353. if ( wbuf[0]==0 ) break;
  354. if ( strnicmp(wbuf,"[charmap",8)==0 ) {
  355. strcpy(charmapname,wbuf);
  356. continue;
  357. };
  358. char * host = strtok(wbuf, " ");
  359. char * console = strtok(NULL, " ");
  360. int bHost;
  361. int bConsole;
  362. if ( host == NULL || console == NULL ) {
  363. //              cerr << charmapname << " -> Bad structure" << endl;
  364. printm(0, FALSE, MSG_KEYBADSTRUCT, charmapname);
  365. return 0;
  366. };
  367. if ( strlen(host) > 1 && host[0] == '\' )
  368. bHost = getbyte(host+1);
  369. else
  370. bHost = (unsigned char)host[0];
  371. if ( strlen(console) > 1 && console[0] == '\' )
  372. bConsole = getbyte(console+1);
  373. else
  374. bConsole = (unsigned char)console[0];
  375. if ( bHost <= 0 || bConsole <= 0 ) {
  376. //              cerr << charmapname << " -> Bad chars? "
  377. //                   << host << " -> " << console << endl;
  378. printm(0, FALSE, MSG_KEYBADCHARS, charmapname, host, console);
  379. return 0;
  380. };
  381. // xlat.table[bHost] = bConsole;
  382. Charmap.modmap(bHost, 'B', bConsole);
  383. };
  384. return (Charmap.enabled = 1);
  385. return 1;
  386. };
  387. // AVS
  388. // ignore long comment [comment] ... [end comment]
  389. // recursive!
  390. int getLongComment(istream& is, char* wbuf, size_t sz) {
  391. int bufLen;
  392.     while ( is ) {
  393. wbuf[0] = 0;
  394. getline(is, wbuf, sz);
  395. if ( wbuf[0]==0 ) return 1;
  396. bufLen = strlen(wbuf);
  397. if ( wbuf[0] == '[' && wbuf[bufLen-1] == ']' ) {
  398. string temps(wbuf);
  399. if (!normalizeSplitter(temps)) {
  400. //           cerr << "Unexpected line '" << temps << "'n";
  401. printm(0, FALSE, MSG_KEYUNEXPLINE, temps.c_str());
  402. return 0;
  403. };
  404. if ( stricmp(temps.c_str(),"[comment]") == 0 ) {
  405. // do recursive call
  406. if ( !getLongComment(is, wbuf, sz) ) return 0;
  407. continue;
  408. };
  409. if ( stricmp(temps.c_str(),"[end comment]") == 0 ) return 1;
  410. };
  411.     };
  412. // we get a warning if we don't put a return here (Paul Brannan 5/25/98)
  413. return 0;
  414. };
  415. // AVS
  416. // completelly rewrited to support new conceptions
  417. int TMapLoader::Load(const char * filename, const char * szActiveEmul) {
  418. char buf[256];
  419. int bufLen;
  420. ifstream inpfile(filename);
  421. KeyTrans.DeleteAllDefs();
  422. Charmap.init();
  423. // it is an array for store [...] ... [end ...] parts from file
  424. stringArray SA(0,0,sizeof(string));
  425. int AllOk = 0;
  426. while ( inpfile ) {
  427. getline(inpfile, buf, 255);
  428. bufLen = strlen(buf);
  429. if ( !bufLen ) continue;
  430. if ( buf[0] == '[' && buf[bufLen-1] == ']' ) {
  431. // is a part splitter [...]
  432. string temps(buf);
  433. if (!normalizeSplitter(temps)) {
  434. printm(0, FALSE, MSG_KEYUNEXPLINE, temps.c_str());
  435. AllOk = 0;
  436. break;
  437. };
  438. // if a comment
  439. if ( stricmp(temps.c_str(),"[comment]") == 0 ) {
  440. #ifdef KEYDEBUG
  441. printit(temps.c_str());
  442. #endif
  443. if ( !getLongComment(inpfile, buf, sizeof(buf)) ) {
  444. printm(0, FALSE, MSG_KEYUNEXPEOF);
  445. break;
  446. };
  447. #ifdef KEYDEBUG
  448. printit("r          r");
  449. #endif
  450. continue;
  451. };
  452. string back = temps;
  453. // prepare line for make it as [end ...]
  454. // and check it
  455. if ( strnicmp(back.c_str(), "[global]", 8) == 0 ) {} // do nothing
  456. else if ( strnicmp(back.c_str(), "[keymap", 7) == 0 ) {
  457. // DJGPP also uses erase rather than remove (Paul Brannan 6/23/98)
  458. #ifndef __BORLANDC__
  459. back.erase(7);
  460. #else
  461. back.remove(7);
  462. #endif
  463. back += "]";
  464. }
  465. else if ( strnicmp(back.c_str(), "[charmap", 8) == 0 ) {
  466. // Paul Brannan 6/23/98
  467. #ifndef __BORLANDC__
  468. back.erase(8);
  469. #else
  470. back.remove(8);
  471. #endif
  472. back += "]";
  473. }
  474. else if ( strnicmp(back.c_str(), "[config", 7) == 0 ) {
  475. // Paul Brannan 6/23/98
  476. #ifndef __BORLANDC__
  477. back.erase(7);
  478. #else
  479. back.remove(7);
  480. #endif
  481. back += "]";
  482. }
  483. else {
  484. //        cerr << "Unexpected token " << back << endl;
  485. printm(0, FALSE, MSG_KEYUNEXPTOK, back.c_str());
  486. break;
  487. };
  488. back.insert(1,"END "); // now it looks like [END ...]
  489. #ifdef KEYDEBUG
  490. printit(temps.c_str());
  491. #endif
  492. int ok = 0;
  493. // fetch it to temps
  494. while ( 1 ) {
  495. getline(inpfile, buf, sizeof(buf));
  496. bufLen = strlen(buf);
  497. if ( !bufLen ) break;
  498. if ( buf[0] == '[' && buf[bufLen-1] == ']' ) {
  499. string t(buf);
  500. if ( !normalizeSplitter(t) ) break;
  501. if ( stricmp(t.c_str(),back.c_str()) == 0 ) {
  502. ok = 1;
  503. break;
  504. };
  505. // AVS 31.12.97 fix [comment] block inside another block
  506. if ( stricmp(t.c_str(),"[comment]") == 0 &&
  507. getLongComment(inpfile, buf, sizeof(buf)) ) continue;
  508. break;
  509. };
  510. temps += "n";
  511. temps += buf;
  512. };
  513. if ( !ok ) {
  514. //         cerr << "Unexpected end of file or token" << endl;
  515. printm(0, FALSE, MSG_KEYUNEXP);
  516. AllOk = 0;
  517. break;
  518. };
  519. #ifdef KEYDEBUG
  520. printit("r                                                                      r");
  521. #endif
  522. AllOk = SA.Add(temps);;
  523. if ( !AllOk ) break;
  524. } else {
  525. //       cerr << "Unexpected line '" << buf << "'n";
  526. printm(0, FALSE, MSG_KEYUNEXPLINE, buf);
  527. AllOk = 0;
  528. break;
  529. };
  530. };
  531. inpfile.close();
  532. if ( !AllOk ) return 0;
  533. // now all file are in SA, comments are stripped
  534. int i = LookForPart(SA, "global", "");
  535. if ( i == INT_MAX ) {
  536. //     cerr << "No [GLOBAL] definition!" << endl;
  537. printm(0, FALSE, MSG_KEYNOGLOBAL);
  538. return 0;
  539. };
  540. if ( !LoadGlobal(SA[i]) ) {
  541. return 0;
  542. };
  543. // look for need configuration
  544. i = LookForPart(SA, "config", szActiveEmul);
  545. if ( i == INT_MAX ) {
  546. //     cerr << "No [CONFIG " << szActiveEmul << "]n";
  547. printm(0, FALSE, MSG_KEYNOCONFIG, szActiveEmul);
  548. return 0;
  549. };
  550. //  cerr << "use configuration: " << szActiveEmul << endl;
  551. printm(0, FALSE, MSG_KEYUSECONFIG, szActiveEmul);
  552. BOOL hadKeys = FALSE;
  553. string config = SA[i];
  554. // parse it
  555. while ( config.length() ) {
  556. buf[0] = 0;
  557. getline(config,buf,sizeof(buf));
  558. bufLen = strlen(buf);
  559. if ( !bufLen || (buf[0] == '[' && buf[bufLen-1] == ']') ) continue;
  560. if ( strnicmp(buf,"keymap",6) == 0 ) {
  561. string orig(buf);
  562. printit("t"); printit(buf); printit("n");
  563. char * mapdef = strtok(buf,":");
  564. char * switchKey = strtok(NULL,"n");
  565. if ( !KeyTrans.mapArray.IsEmpty() && switchKey == NULL ) {
  566. //            cerr << "no switch Key for '" << mapdef
  567. //                 << "'" << endl;
  568. printm(0, FALSE, MSG_KEYNOSWKEY, mapdef);
  569. break;
  570. };
  571. if ( KeyTrans.mapArray.IsEmpty() ) {
  572. if ( switchKey != NULL ) { // create default keymap
  573. //               cerr << "You cannot define switch key for default keymap -> ignored"
  574. //                    << endl;
  575. printm(0, FALSE, MSG_KEYCANNOTDEF);
  576. };
  577. TKeyDef empty;
  578. KeyTrans.mapArray.Add(KeyMap(string(mapdef)));
  579. KeyTrans.switchMap(empty); // set it as current keymap
  580. KeyTrans.mainKeyMap = KeyTrans.currentKeyMap;
  581. }
  582. else {
  583. string keydef(switchKey);
  584. keydef += " !*!*!*"; // just for check
  585. WORD vk_code;
  586. DWORD control;
  587. switchKey = ParseKeyDef(keydef.c_str(),vk_code,control);
  588. if ( switchKey != NULL ) {
  589. TKeyDef swi(NULL,control,vk_code);
  590. if ( KeyTrans.switchMap(swi) > 0 ) {
  591. //                  cerr << "Duplicate switching keyn";
  592. printm(0, FALSE, MSG_KEYDUPSWKEY);
  593. break;
  594. };
  595. KeyTrans.mapArray.Add(KeyMap(swi, orig));
  596. KeyTrans.switchMap(swi); // set it as current keymap
  597. }
  598. };
  599. mapdef+=7; // 'keymap '
  600. // now load defined keymaps to current
  601. while ((mapdef != NULL)&&
  602. (mapdef = strtok(mapdef,TOKEN_DELIMITERS)) != NULL ) {
  603. i = LookForPart(SA,"keymap",mapdef);
  604. if ( i == INT_MAX ) {
  605. //               cerr << "Unknown KEYMAP " << mapdef << endl;
  606. printm(0, FALSE, MSG_KEYUNKNOWNMAP, mapdef);
  607. } else {
  608. mapdef = strtok(NULL,"n"); // strtok is used in LoadKeyMap
  609. // so - save pointer!
  610. hadKeys = LoadKeyMap(SA[i]); // load it
  611. };
  612. };
  613. }
  614. else if ( strnicmp(buf,"charmap",7) == 0 ) {
  615. printit("t"); printit(buf); printit("n");
  616. char * mapdef = buf + 8;// 'charmap '
  617. int SuccesLoaded = 0;
  618. // now load defined charmaps to current
  619. while ((mapdef != NULL)&&
  620. (mapdef = strtok(mapdef,TOKEN_DELIMITERS)) != NULL ) {
  621. i = LookForPart(SA,"charmap",mapdef);
  622. if ( i == INT_MAX ) {
  623. //               cerr << "Unknown KEYMAP " << mapdef << endl;
  624. printm(0, FALSE, MSG_KEYUNKNOWNMAP, mapdef);
  625. } else {
  626. mapdef = strtok(NULL,"n"); // strtok is used in LoadKeyMap
  627. // so - save pointer!
  628. if (LoadCharMap(SA[i])) // load it
  629. SuccesLoaded++;
  630. };
  631. };
  632. if (!SuccesLoaded) {
  633. //            cerr << "No charmaps loadedn";
  634. printm(0, FALSE, MSG_KEYNOCHARMAPS);
  635. Charmap.init();
  636. };
  637. /*         strtok(buf," ");
  638.   char* name = strtok(NULL," ");
  639.   if ( name == NULL ) {
  640.   cerr << "No name for CHARMAP" << endl;
  641.   } else {
  642.   i = LookForPart(SA,"charmap", name);
  643.   if ( i == INT_MAX ) {
  644.   cerr << "Unknown CHARMAP " << name << endl;
  645.   } else {
  646.   LoadCharMap(SA[i]);
  647.   };
  648.   };
  649. */
  650. }
  651. else {
  652. //        cerr << "unexpected token in " << szActiveEmul << endl;
  653. printm(0, FALSE, MSG_KEYUNEXPTOKIN, szActiveEmul);
  654. }
  655. }
  656. if ( hadKeys) {
  657. TKeyDef empty;
  658. KeyTrans.switchMap(empty); // switch to default
  659. KeyTrans.mainKeyMap = KeyTrans.currentKeyMap; // save it's number
  660. //     cerr << "There are " << (KeyTrans.mapArray.GetItemsInContainer()) << " mapsn";
  661. char s[12]; // good enough for a long int (32-bit)
  662. itoa(KeyTrans.mapArray.GetItemsInContainer(), s, 10);
  663. printm(0, FALSE, MSG_KEYNUMMAPS, s);
  664. return 1;
  665. };
  666. return 0;
  667. }
  668. void TMapLoader::Display() {
  669.     int max = KeyTrans.mapArray.GetItemsInContainer();
  670.     if (max == 0) {
  671.        printm(0, FALSE, MSG_KEYNOKEYMAPS);
  672.        return;
  673.     };
  674.     for ( int i = 0; i < max; i++ ) {
  675.        char buf[20];
  676.        itoa(i,buf,10);
  677.        printit("t");
  678.        // Ioannou : we can show the current
  679.        if (KeyTrans.currentKeyMap == i)
  680.          printit("*");
  681.        else
  682.          printit(" ");
  683.        strcat(buf," ");
  684.        printit(buf);
  685.        char * msg = new char [KeyTrans.mapArray[i].orig.length()+1];
  686.        strcpy(msg,KeyTrans.mapArray[i].orig.c_str());
  687.        printit(msg);
  688.        delete[] msg;
  689.        printit("n");
  690.     };
  691. };