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