2 * Copyright 2004-2012, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
7 * Axel Dörfler, axeld@pinc-software.de.
8 * John Scipione, jscipione@gmail.com
18 #include <ByteOrder.h>
21 #include <FindDirectory.h>
26 #define CHARS_TABLE_MAXSIZE 10000
29 extern status_t
_restore_key_map_();
32 // i couldn't put patterns and pattern bufs on the stack without segfaulting
34 const char versionPattern
[]
35 = "Version[[:space:]]+=[[:space:]]+\\([[:digit:]]+\\)";
36 const char capslockPattern
[]
37 = "CapsLock[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)";
38 const char scrolllockPattern
[]
39 = "ScrollLock[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)";
40 const char numlockPattern
[]
41 = "NumLock[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)";
42 const char lshiftPattern
[] = "LShift[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)";
43 const char rshiftPattern
[] = "RShift[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)";
44 const char lcommandPattern
[]
45 = "LCommand[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)";
46 const char rcommandPattern
[]
47 = "RCommand[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)";
48 const char lcontrolPattern
[]
49 = "LControl[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)";
50 const char rcontrolPattern
[]
51 = "RControl[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)";
52 const char loptionPattern
[]
53 = "LOption[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)";
54 const char roptionPattern
[]
55 = "ROption[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)";
56 const char menuPattern
[] = "Menu[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)";
57 const char locksettingsPattern
[]
58 = "LockSettings[[:space:]]+=[[:space:]]+\\([[:alnum:]]*\\)"
59 "[[:space:]]*\\([[:alnum:]]*\\)"
60 "[[:space:]]*\\([[:alnum:]]*\\)[[:space:]]*";
61 const char keyPattern
[] = "Key[[:space:]]+\\([[:alnum:]]+\\)[[:space:]]+="
62 "[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)"
63 "[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)"
64 "[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)"
65 "[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)"
66 "[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)"
67 "[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)"
68 "[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)"
69 "[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)"
70 "[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)"
73 const char acutePattern
[] = "Acute[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)"
74 "[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)[[:space:]]+";
75 const char gravePattern
[] = "Grave[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)"
76 "[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)[[:space:]]+";
77 const char circumflexPattern
[] = "Circumflex[[:space:]]+\\([[:alnum:]]"
78 "+\\|'.*'\\)[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)[[:space:]]+";
79 const char diaeresisPattern
[] = "Diaeresis[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)"
80 "[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)[[:space:]]+";
81 const char tildePattern
[] = "Tilde[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)"
82 "[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)[[:space:]]+";
83 const char acutetabPattern
[] = "AcuteTab[[:space:]]+="
84 "[[:space:]]+\\([[:alnum:]-]*\\)"
85 "[[:space:]]*\\([[:alnum:]-]*\\)"
86 "[[:space:]]*\\([[:alnum:]-]*\\)"
87 "[[:space:]]*\\([[:alnum:]-]*\\)"
88 "[[:space:]]*\\([[:alnum:]-]*\\)"
89 "[[:space:]]*\\([[:alnum:]-]*\\)"
90 "[[:space:]]*\\([[:alnum:]-]*\\)"
91 "[[:space:]]*\\([[:alnum:]-]*\\)"
92 "[[:space:]]*\\([[:alnum:]-]*\\)[[:space:]]*" ;
93 const char gravetabPattern
[] = "GraveTab[[:space:]]+="
94 "[[:space:]]+\\([[:alnum:]-]*\\)"
95 "[[:space:]]*\\([[:alnum:]-]*\\)"
96 "[[:space:]]*\\([[:alnum:]-]*\\)"
97 "[[:space:]]*\\([[:alnum:]-]*\\)"
98 "[[:space:]]*\\([[:alnum:]-]*\\)"
99 "[[:space:]]*\\([[:alnum:]-]*\\)"
100 "[[:space:]]*\\([[:alnum:]-]*\\)"
101 "[[:space:]]*\\([[:alnum:]-]*\\)"
102 "[[:space:]]*\\([[:alnum:]-]*\\)[[:space:]]*" ;
103 const char circumflextabPattern
[] = "CircumflexTab[[:space:]]+="
104 "[[:space:]]+\\([[:alnum:]-]*\\)"
105 "[[:space:]]*\\([[:alnum:]-]*\\)"
106 "[[:space:]]*\\([[:alnum:]-]*\\)"
107 "[[:space:]]*\\([[:alnum:]-]*\\)"
108 "[[:space:]]*\\([[:alnum:]-]*\\)"
109 "[[:space:]]*\\([[:alnum:]-]*\\)"
110 "[[:space:]]*\\([[:alnum:]-]*\\)"
111 "[[:space:]]*\\([[:alnum:]-]*\\)"
112 "[[:space:]]*\\([[:alnum:]-]*\\)[[:space:]]*" ;
113 const char diaeresistabPattern
[] = "DiaeresisTab[[:space:]]+="
114 "[[:space:]]+\\([[:alnum:]-]*\\)"
115 "[[:space:]]*\\([[:alnum:]-]*\\)"
116 "[[:space:]]*\\([[:alnum:]-]*\\)"
117 "[[:space:]]*\\([[:alnum:]-]*\\)"
118 "[[:space:]]*\\([[:alnum:]-]*\\)"
119 "[[:space:]]*\\([[:alnum:]-]*\\)"
120 "[[:space:]]*\\([[:alnum:]-]*\\)"
121 "[[:space:]]*\\([[:alnum:]-]*\\)"
122 "[[:space:]]*\\([[:alnum:]-]*\\)[[:space:]]*" ;
123 const char tildetabPattern
[] = "TildeTab[[:space:]]+="
124 "[[:space:]]+\\([[:alnum:]-]*\\)"
125 "[[:space:]]*\\([[:alnum:]-]*\\)"
126 "[[:space:]]*\\([[:alnum:]-]*\\)"
127 "[[:space:]]*\\([[:alnum:]-]*\\)"
128 "[[:space:]]*\\([[:alnum:]-]*\\)"
129 "[[:space:]]*\\([[:alnum:]-]*\\)"
130 "[[:space:]]*\\([[:alnum:]-]*\\)"
131 "[[:space:]]*\\([[:alnum:]-]*\\)"
132 "[[:space:]]*\\([[:alnum:]-]*\\)[[:space:]]*" ;
135 // re_pattern_buffer buffers
136 struct re_pattern_buffer versionBuf
;
137 struct re_pattern_buffer capslockBuf
;
138 struct re_pattern_buffer scrolllockBuf
;
139 struct re_pattern_buffer numlockBuf
;
140 struct re_pattern_buffer lshiftBuf
;
141 struct re_pattern_buffer rshiftBuf
;
142 struct re_pattern_buffer lcommandBuf
;
143 struct re_pattern_buffer rcommandBuf
;
144 struct re_pattern_buffer lcontrolBuf
;
145 struct re_pattern_buffer rcontrolBuf
;
146 struct re_pattern_buffer loptionBuf
;
147 struct re_pattern_buffer roptionBuf
;
148 struct re_pattern_buffer menuBuf
;
149 struct re_pattern_buffer locksettingsBuf
;
150 struct re_pattern_buffer keyBuf
;
151 struct re_pattern_buffer acuteBuf
;
152 struct re_pattern_buffer graveBuf
;
153 struct re_pattern_buffer circumflexBuf
;
154 struct re_pattern_buffer diaeresisBuf
;
155 struct re_pattern_buffer tildeBuf
;
156 struct re_pattern_buffer acutetabBuf
;
157 struct re_pattern_buffer gravetabBuf
;
158 struct re_pattern_buffer circumflextabBuf
;
159 struct re_pattern_buffer diaeresistabBuf
;
160 struct re_pattern_buffer tildetabBuf
;
164 dump_map(FILE* file
, const char* name
, int32
* map
)
166 fprintf(file
, "\t%s:\n\t{\n", name
);
168 for (uint32 i
= 0; i
< 16; i
++) {
170 for (uint32 j
= 0; j
< 8; j
++) {
171 fprintf(file
, "0x%04" B_PRIx32
",%s", map
[i
* 8 + j
],
176 fputs("\t},\n", file
);
181 dump_keys(FILE* file
, const char* name
, int32
* keys
)
183 fprintf(file
, "\t%s:\n\t{\n", name
);
185 for (uint32 i
= 0; i
< 4; i
++) {
186 fprintf(file
, "\t\t");
187 for (uint32 j
= 0; j
< 8; j
++) {
188 fprintf(file
, "0x%04" B_PRIx32
",%s", keys
[i
* 8 + j
],
193 fputs("\t},\n", file
);
211 Keymap::LoadSource(const char* name
)
213 FILE* file
= fopen(name
, "r");
217 status_t status
= LoadSource(file
);
225 Keymap::LoadSource(FILE* file
)
227 // Setup regexp parser
229 reg_syntax_t syntax
= RE_CHAR_CLASSES
;
230 re_set_syntax(syntax
);
232 const char* error
= NULL
;
234 error
= re_compile_pattern(versionPattern
, strlen(versionPattern
),
237 fputs(error
, stderr
);
238 error
= re_compile_pattern(capslockPattern
, strlen(capslockPattern
),
241 fputs(error
, stderr
);
242 error
= re_compile_pattern(scrolllockPattern
, strlen(scrolllockPattern
),
245 fputs(error
, stderr
);
246 error
= re_compile_pattern(numlockPattern
, strlen(numlockPattern
),
249 fputs(error
, stderr
);
250 error
= re_compile_pattern(lshiftPattern
, strlen(lshiftPattern
),
253 fputs(error
, stderr
);
254 error
= re_compile_pattern(rshiftPattern
, strlen(rshiftPattern
),
257 fputs(error
, stderr
);
258 error
= re_compile_pattern(lcommandPattern
, strlen(lcommandPattern
),
261 fputs(error
, stderr
);
262 error
= re_compile_pattern(rcommandPattern
, strlen(rcommandPattern
),
265 fputs(error
, stderr
);
266 error
= re_compile_pattern(lcontrolPattern
, strlen(lcontrolPattern
),
269 fputs(error
, stderr
);
270 error
= re_compile_pattern(rcontrolPattern
, strlen(rcontrolPattern
),
273 fputs(error
, stderr
);
274 error
= re_compile_pattern(loptionPattern
, strlen(loptionPattern
),
277 fputs(error
, stderr
);
278 error
= re_compile_pattern(roptionPattern
, strlen(roptionPattern
),
281 fputs(error
, stderr
);
282 error
= re_compile_pattern(menuPattern
, strlen(menuPattern
), &menuBuf
);
284 fputs(error
, stderr
);
285 error
= re_compile_pattern(locksettingsPattern
,
286 strlen(locksettingsPattern
), &locksettingsBuf
);
288 fputs(error
, stderr
);
289 error
= re_compile_pattern(keyPattern
, strlen(keyPattern
), &keyBuf
);
291 fputs(error
, stderr
);
292 error
= re_compile_pattern(acutePattern
, strlen(acutePattern
), ´Buf
);
294 fputs(error
, stderr
);
295 error
= re_compile_pattern(gravePattern
, strlen(gravePattern
), &graveBuf
);
297 fputs(error
, stderr
);
298 error
= re_compile_pattern(circumflexPattern
, strlen(circumflexPattern
),
301 fputs(error
, stderr
);
302 error
= re_compile_pattern(diaeresisPattern
, strlen(diaeresisPattern
),
305 fputs(error
, stderr
);
306 error
= re_compile_pattern(tildePattern
, strlen(tildePattern
), &tildeBuf
);
308 fputs(error
, stderr
);
309 error
= re_compile_pattern(acutetabPattern
, strlen(acutetabPattern
),
312 fputs(error
, stderr
);
313 error
= re_compile_pattern(gravetabPattern
, strlen(gravetabPattern
),
316 fputs(error
, stderr
);
317 error
= re_compile_pattern(circumflextabPattern
,
318 strlen(circumflextabPattern
), &circumflextabBuf
);
320 fputs(error
, stderr
);
321 error
= re_compile_pattern(diaeresistabPattern
,
322 strlen(diaeresistabPattern
), &diaeresistabBuf
);
324 fputs(error
, stderr
);
325 error
= re_compile_pattern(tildetabPattern
, strlen(tildetabPattern
),
328 fputs(error
, stderr
);
333 fChars
= new char[CHARS_TABLE_MAXSIZE
];
334 fCharsSize
= CHARS_TABLE_MAXSIZE
;
338 int circumflexOffset
= 0;
339 int diaeresisOffset
= 0;
347 fKeys
.option_shift_map
,
349 fKeys
.caps_shift_map
,
350 fKeys
.option_caps_map
,
351 fKeys
.option_caps_shift_map
356 while (fgets(buffer
, sizeof(buffer
) - 1, file
) != NULL
) {
357 if (buffer
[0] == '#' || buffer
[0] == '\n')
360 size_t length
= strlen(buffer
);
362 struct re_registers regs
;
364 if (re_search(&versionBuf
, buffer
, length
, 0, length
, ®s
) >= 0) {
365 sscanf(buffer
+ regs
.start
[1], "%" B_SCNu32
, &fKeys
.version
);
366 } else if (re_search(&capslockBuf
, buffer
, length
, 0, length
, ®s
)
368 sscanf(buffer
+ regs
.start
[1], "0x%" B_SCNx32
, &fKeys
.caps_key
);
369 } else if (re_search(&scrolllockBuf
, buffer
, length
, 0, length
, ®s
)
371 sscanf(buffer
+ regs
.start
[1], "0x%" B_SCNx32
, &fKeys
.scroll_key
);
372 } else if (re_search(&numlockBuf
, buffer
, length
, 0, length
, ®s
)
374 sscanf(buffer
+ regs
.start
[1], "0x%" B_SCNx32
, &fKeys
.num_key
);
375 } else if (re_search(&lshiftBuf
, buffer
, length
, 0, length
, ®s
)
377 sscanf(buffer
+ regs
.start
[1], "0x%" B_SCNx32
,
378 &fKeys
.left_shift_key
);
379 } else if (re_search(&rshiftBuf
, buffer
, length
, 0, length
, ®s
)
381 sscanf(buffer
+ regs
.start
[1], "0x%" B_SCNx32
,
382 &fKeys
.right_shift_key
);
383 } else if (re_search(&lcommandBuf
, buffer
, length
, 0, length
, ®s
)
385 sscanf(buffer
+ regs
.start
[1], "0x%" B_SCNx32
,
386 &fKeys
.left_command_key
);
387 } else if (re_search(&rcommandBuf
, buffer
, length
, 0, length
, ®s
)
389 sscanf(buffer
+ regs
.start
[1], "0x%" B_SCNx32
,
390 &fKeys
.right_command_key
);
391 } else if (re_search(&lcontrolBuf
, buffer
, length
, 0, length
, ®s
)
393 sscanf(buffer
+ regs
.start
[1], "0x%" B_SCNx32
,
394 &fKeys
.left_control_key
);
395 } else if (re_search(&rcontrolBuf
, buffer
, length
, 0, length
, ®s
)
397 sscanf(buffer
+ regs
.start
[1], "0x%" B_SCNx32
,
398 &fKeys
.right_control_key
);
399 } else if (re_search(&loptionBuf
, buffer
, length
, 0, length
, ®s
)
401 sscanf(buffer
+ regs
.start
[1], "0x%" B_SCNx32
,
402 &fKeys
.left_option_key
);
403 } else if (re_search(&roptionBuf
, buffer
, length
, 0, length
, ®s
)
405 sscanf(buffer
+ regs
.start
[1], "0x%" B_SCNx32
,
406 &fKeys
.right_option_key
);
407 } else if (re_search(&menuBuf
, buffer
, length
, 0, length
, ®s
)
409 sscanf(buffer
+ regs
.start
[1], "0x%" B_SCNx32
, &fKeys
.menu_key
);
410 } else if (re_search(&locksettingsBuf
, buffer
, length
, 0, length
, ®s
)
412 fKeys
.lock_settings
= 0;
413 for (int32 i
= 1; i
<= 3; i
++) {
414 const char* start
= buffer
+ regs
.start
[i
];
415 length
= regs
.end
[i
] - regs
.start
[i
];
419 if (!strncmp(start
, "CapsLock", length
))
420 fKeys
.lock_settings
|= B_CAPS_LOCK
;
421 else if (!strncmp(start
, "NumLock", length
))
422 fKeys
.lock_settings
|= B_NUM_LOCK
;
423 else if (!strncmp(start
, "ScrollLock", length
))
424 fKeys
.lock_settings
|= B_SCROLL_LOCK
;
426 } else if (re_search(&keyBuf
, buffer
, length
, 0, length
, ®s
)
429 if (sscanf(buffer
+ regs
.start
[1], "0x%" B_SCNx32
, &keyCode
) > 0) {
430 for (int i
= 2; i
<= 10; i
++) {
431 maps
[i
- 2][keyCode
] = offset
;
432 _ComputeChars(buffer
, regs
, i
, offset
);
435 } else if (re_search(´Buf
, buffer
, length
, 0, length
, ®s
)
437 for (int i
= 1; i
<= 2; i
++) {
438 fKeys
.acute_dead_key
[acuteOffset
++] = offset
;
439 _ComputeChars(buffer
, regs
, i
, offset
);
441 } else if (re_search(&graveBuf
, buffer
, length
, 0, length
, ®s
)
443 for (int i
= 1; i
<= 2; i
++) {
444 fKeys
.grave_dead_key
[graveOffset
++] = offset
;
445 _ComputeChars(buffer
, regs
, i
, offset
);
447 } else if (re_search(&circumflexBuf
, buffer
, length
, 0, length
, ®s
)
449 for (int i
= 1; i
<= 2; i
++) {
450 fKeys
.circumflex_dead_key
[circumflexOffset
++] = offset
;
451 _ComputeChars(buffer
, regs
, i
, offset
);
453 } else if (re_search(&diaeresisBuf
, buffer
, length
, 0, length
, ®s
)
455 for (int i
= 1; i
<= 2; i
++) {
456 fKeys
.dieresis_dead_key
[diaeresisOffset
++] = offset
;
457 _ComputeChars(buffer
, regs
, i
, offset
);
459 } else if (re_search(&tildeBuf
, buffer
, length
, 0, length
, ®s
) >= 0) {
460 for (int i
= 1; i
<= 2; i
++) {
461 fKeys
.tilde_dead_key
[tildeOffset
++] = offset
;
462 _ComputeChars(buffer
, regs
, i
, offset
);
464 } else if (re_search(´tabBuf
, buffer
, length
, 0, length
, ®s
)
466 _ComputeTables(buffer
, regs
, fKeys
.acute_tables
);
467 } else if (re_search(&gravetabBuf
, buffer
, length
, 0, length
, ®s
)
469 _ComputeTables(buffer
, regs
, fKeys
.grave_tables
);
470 } else if (re_search(&circumflextabBuf
, buffer
, length
, 0, length
, ®s
)
472 _ComputeTables(buffer
, regs
, fKeys
.circumflex_tables
);
473 } else if (re_search(&diaeresistabBuf
, buffer
, length
, 0, length
, ®s
)
475 _ComputeTables(buffer
, regs
, fKeys
.dieresis_tables
);
476 } else if (re_search(&tildetabBuf
, buffer
, length
, 0, length
, ®s
)
478 _ComputeTables(buffer
, regs
, fKeys
.tilde_tables
);
484 if (fKeys
.version
!= 3)
485 return KEYMAP_ERROR_UNKNOWN_VERSION
;
492 Keymap::SaveAsCurrent()
494 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
496 status_t status
= find_directory(B_USER_SETTINGS_DIRECTORY
, &path
, true);
500 path
.Append("Key_map");
502 status
= Save(path
.Path());
509 fprintf(stderr
, "Unsupported operation on this platform!\n");
515 //! Save a binary keymap to a file.
517 Keymap::Save(const char* name
)
520 status_t status
= file
.SetTo(name
,
521 B_WRITE_ONLY
| B_CREATE_FILE
| B_ERASE_FILE
);
525 // convert to big endian
526 for (uint32 i
= 0; i
< sizeof(fKeys
) / sizeof(uint32
); i
++) {
527 ((uint32
*)&fKeys
)[i
] = B_HOST_TO_BENDIAN_INT32(((uint32
*)&fKeys
)[i
]);
530 ssize_t bytesWritten
= file
.Write(&fKeys
, sizeof(fKeys
));
532 // convert endian back
533 for (uint32 i
= 0; i
< sizeof(fKeys
) / sizeof(uint32
); i
++) {
534 ((uint32
*)&fKeys
)[i
] = B_BENDIAN_TO_HOST_INT32(((uint32
*)&fKeys
)[i
]);
537 if (bytesWritten
< (ssize_t
)sizeof(fKeys
))
539 if (bytesWritten
< B_OK
)
542 uint32 charSize
= B_HOST_TO_BENDIAN_INT32(fCharsSize
);
544 bytesWritten
= file
.Write(&charSize
, sizeof(uint32
));
545 if (bytesWritten
< (ssize_t
)sizeof(uint32
))
547 if (bytesWritten
< B_OK
)
550 bytesWritten
= file
.Write(fChars
, fCharsSize
);
551 if (bytesWritten
< (ssize_t
)fCharsSize
)
553 if (bytesWritten
< B_OK
)
561 Keymap::SaveAsSource(const char* name
)
563 FILE* file
= fopen(name
, "w");
567 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
568 text_run_array
* textRuns
;
569 _SaveSourceText(file
, &textRuns
);
571 if (textRuns
!= NULL
) {
573 void* data
= BTextView::FlattenRunArray(textRuns
, &dataSize
);
576 node
.WriteAttr("styles", B_RAW_TYPE
, 0, data
, dataSize
);
581 BTextView::FreeRunArray(textRuns
);
584 _SaveSourceText(file
);
594 Keymap::SaveAsSource(FILE* file
)
596 _SaveSourceText(file
);
601 /*! Save a keymap as C source file - this is used to get the default keymap
602 into the input_server, for example.
603 \a mapName is usually the path of the input keymap, and is used as the
604 name of the keymap (the path will be removed, as well as its suffix).
607 Keymap::SaveAsCppHeader(const char* fileName
, const char* mapName
)
609 BString name
= mapName
;
612 int32 index
= name
.FindLast('/');
614 name
.Remove(0, index
+ 1);
617 index
= name
.FindLast('.');
619 name
.Truncate(index
);
621 FILE* file
= fopen(fileName
, "w");
626 " * Haiku Default System Keymap\n"
627 " * This file is automatically generated. Do not edit!\n"
629 fputs("#ifndef\t_SYSTEM_KEYMAP_H\n"
630 "#define\t_SYSTEM_KEYMAP_H\n\n\n", file
);
631 fputs("#include <InterfaceDefs.h>\n\n\n", file
);
632 fputs("#ifdef __cplusplus\n"
635 fprintf(file
, "const char *kSystemKeymapName = \"%s\";\n\n", name
.String());
636 fputs("const key_map kSystemKeymap = {\n", file
);
638 // version, default lock settings, modifier keys
639 fprintf(file
, "\tversion:%" B_PRIu32
",\n", fKeys
.version
);
640 fprintf(file
, "\tcaps_key:0x%" B_PRIx32
",\n", fKeys
.caps_key
);
641 fprintf(file
, "\tscroll_key:0x%" B_PRIx32
",\n", fKeys
.scroll_key
);
642 fprintf(file
, "\tnum_key:0x%" B_PRIx32
",\n", fKeys
.num_key
);
643 fprintf(file
, "\tleft_shift_key:0x%" B_PRIx32
",\n", fKeys
.left_shift_key
);
644 fprintf(file
, "\tright_shift_key:0x%" B_PRIx32
",\n",
645 fKeys
.right_shift_key
);
646 fprintf(file
, "\tleft_command_key:0x%" B_PRIx32
",\n",
647 fKeys
.left_command_key
);
648 fprintf(file
, "\tright_command_key:0x%" B_PRIx32
",\n",
649 fKeys
.right_command_key
);
650 fprintf(file
, "\tleft_control_key:0x%" B_PRIx32
",\n",
651 fKeys
.left_control_key
);
652 fprintf(file
, "\tright_control_key:0x%" B_PRIx32
",\n",
653 fKeys
.right_control_key
);
654 fprintf(file
, "\tleft_option_key:0x%" B_PRIx32
",\n",
655 fKeys
.left_option_key
);
656 fprintf(file
, "\tright_option_key:0x%" B_PRIx32
",\n",
657 fKeys
.right_option_key
);
658 fprintf(file
, "\tmenu_key:0x%" B_PRIx32
",\n", fKeys
.menu_key
);
659 fprintf(file
, "\tlock_settings:0x%" B_PRIx32
",\n", fKeys
.lock_settings
);
662 dump_map(file
, "control_map", fKeys
.control_map
);
663 dump_map(file
, "option_caps_shift_map", fKeys
.option_caps_shift_map
);
664 dump_map(file
, "option_caps_map", fKeys
.option_caps_map
);
665 dump_map(file
, "option_shift_map", fKeys
.option_shift_map
);
666 dump_map(file
, "option_map", fKeys
.option_map
);
667 dump_map(file
, "caps_shift_map", fKeys
.caps_shift_map
);
668 dump_map(file
, "caps_map", fKeys
.caps_map
);
669 dump_map(file
, "shift_map", fKeys
.shift_map
);
670 dump_map(file
, "normal_map", fKeys
.normal_map
);
673 dump_keys(file
, "acute_dead_key", fKeys
.acute_dead_key
);
674 dump_keys(file
, "grave_dead_key", fKeys
.grave_dead_key
);
675 dump_keys(file
, "circumflex_dead_key", fKeys
.circumflex_dead_key
);
676 dump_keys(file
, "dieresis_dead_key", fKeys
.dieresis_dead_key
);
677 dump_keys(file
, "tilde_dead_key", fKeys
.tilde_dead_key
);
680 fprintf(file
, "\tacute_tables:0x%" B_PRIx32
",\n", fKeys
.acute_tables
);
681 fprintf(file
, "\tgrave_tables:0x%" B_PRIx32
",\n", fKeys
.grave_tables
);
682 fprintf(file
, "\tcircumflex_tables:0x%" B_PRIx32
",\n",
683 fKeys
.circumflex_tables
);
684 fprintf(file
, "\tdieresis_tables:0x%" B_PRIx32
",\n",
685 fKeys
.dieresis_tables
);
686 fprintf(file
, "\ttilde_tables:0x%" B_PRIx32
",\n", fKeys
.tilde_tables
);
688 fputs("};\n\n", file
);
690 fputs("const uchar kSystemKeyChars[] = {\n", file
);
692 for (uint32 i
= 0; i
< fCharsSize
; i
++) {
700 fprintf(file
, "0x%02x,", (uint8
)fChars
[i
]);
702 fputs("\n};\n\n", file
);
704 fprintf(file
, "const uint32 kSystemKeyCharsSize = %" B_PRIu32
";\n\n",
706 fputs("#ifdef __cplusplus\n"
709 "#endif\t// _SYSTEM_KEYMAP_H\n", file
);
717 //! We make our input server use the map in /boot/home/config/settings/Keymap
721 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
722 return _restore_key_map_();
725 fprintf(stderr
, "Unsupported operation on this platform!\n");
732 Keymap::RestoreSystemDefault()
734 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
735 // work-around to get rid of this stupid find_directory_r() on Zeta
736 # ifdef find_directory
737 # undef find_directory
740 if (find_directory(B_USER_SETTINGS_DIRECTORY
, &path
) != B_OK
)
743 path
.Append("Key_map");
745 BEntry
entry(path
.Path());
750 fprintf(stderr
, "Unsupported operation on this platform!\n");
757 Keymap::GetKey(const char* chars
, int32 offset
, char* buffer
, size_t bufferSize
)
759 uint8 size
= (uint8
)chars
[offset
++];
765 strlcpy(buffer
, "''", bufferSize
);
769 // single-byte UTF-8/ASCII character
770 if ((uint8
)chars
[offset
] < 0x20 || (uint8
)chars
[offset
] > 0x7e)
771 sprintf(string
, "0x%02x", (uint8
)chars
[offset
]);
773 sprintf(string
, "'%s%c'",
774 (chars
[offset
] == '\\' || chars
[offset
] == '\'') ? "\\" : "",
780 // multi-byte UTF-8 character
781 sprintf(string
, "0x");
782 for (int i
= 0; i
< size
; i
++) {
783 sprintf(string
+ 2 * (i
+ 1), "%02x", (uint8
)chars
[offset
+ i
]);
788 strlcpy(buffer
, string
, bufferSize
);
793 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
795 Keymap::_SaveSourceText(FILE* file
, text_run_array
** _textRuns
)
797 text_run_array
* runs
= NULL
;
798 if (_textRuns
!= NULL
) {
799 runs
= BTextView::AllocRunArray(8);
804 Keymap::_SaveSourceText(FILE* file
)
808 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
809 static const rgb_color kCommentColor
= (rgb_color
){200, 92, 92, 255};
810 static const rgb_color kTextColor
= (rgb_color
){0, 0, 0, 255};
812 BFont font
= *be_fixed_font
;
815 runs
->runs
[0].offset
= 0;
816 runs
->runs
[0].font
= font
;
817 runs
->runs
[0].color
= kCommentColor
;
821 int bytes
= fprintf(file
, "#!/bin/keymap -s\n"
823 "#\tRaw key numbering for 102-key keyboard...\n");
825 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
827 runs
->runs
[1].offset
= bytes
;
828 runs
->runs
[1].font
= font
;
829 runs
->runs
[1].font
.SetSize(9);
830 runs
->runs
[1].color
= kCommentColor
;
834 bytes
+= fprintf(file
, "# [sys] [brk]\n"
836 "# [esc] [ f1] [ f2] [ f3] [ f4] [ f5] [ f6] [ f7] [ f8] [ f9] [f10] [f11] [f12] [prn] [scr] [pau]\n"
837 "# 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 K E Y P A D K E Y S\n"
839 "# [ ` ] [ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 7 ] [ 8 ] [ 9 ] [ 0 ] [ - ] [ = ] [ bck ] [ins] [hme] [pup] [num] [ / ] [ * ] [ - ]\n"
840 "# 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f 0x20 0x21 0x22 0x23 0x24 0x25\n"
842 "# [ tab ] [ q ] [ w ] [ e ] [ r ] [ t ] [ y ] [ u ] [ i ] [ o ] [ p ] [ [ ] [ ] ] [ \\ ] [del] [end] [pdn] [ 7 ] [ 8 ] [ 9 ] [ + ]\n"
843 "# 0x26 0x27 0x28 0x29 0x2a 0x2b 0x2c 0x2d 0x2e 0x2f 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x3a\n"
845 "# [ caps ] [ a ] [ s ] [ d ] [ f ] [ g ] [ h ] [ j ] [ k ] [ l ] [ ; ] [ ' ] [ enter ] [ 4 ] [ 5 ] [ 6 ]\n"
846 "# 0x3b 0x3c 0x3d 0x3e 0x3f 0x40 0x41 0x42 0x43 0x44 0x45 0x46 0x47 0x48 0x49 0x4a\n"
848 "# [shft] [ \\ ] [ z ] [ x ] [ c ] [ v ] [ b ] [ n ] [ m ] [ , ] [ . ] [ / ] [ shift ] [ up] [ 1 ] [ 2 ] [ 3 ] [ent]\n"
849 "# 0x4b 0x69 0x4c 0x4d 0x4e 0x4f 0x50 0x51 0x52 0x53 0x54 0x55 0x56 0x57 0x58 0x59 0x5a 0x5b\n"
851 "# [ ctrl ] [ cmd ] [ space ] [ cmd ] [ ctrl ] [lft] [dwn] [rgt] [ 0 ] [ . ]\n"
852 "# 0x5c 0x5d 0x5e 0x5f 0x60 0x61 0x62 0x63 0x64 0x65\n");
854 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
856 runs
->runs
[2].offset
= bytes
;
857 runs
->runs
[2].font
= font
;
858 runs
->runs
[2].color
= kCommentColor
;
862 bytes
+= fprintf(file
, "#\n"
863 "#\tNOTE: Key 0x69 does not exist on US keyboards\n"
864 "#\tNOTE: On a Microsoft Natural Keyboard:\n"
865 "#\t\t\tleft option = 0x66\n"
866 "#\t\t\tright option = 0x67\n"
867 "#\t\t\tmenu key = 0x68\n"
868 "#\tNOTE: On an Apple Extended Keyboard:\n"
869 "#\t\t\tleft option = 0x66\n"
870 "#\t\t\tright option = 0x67\n"
871 "#\t\t\tkeypad '=' = 0x6a\n"
872 "#\t\t\tpower key = 0x6b\n");
874 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
876 runs
->runs
[3].offset
= bytes
;
877 runs
->runs
[3].font
= *be_fixed_font
;
878 runs
->runs
[3].color
= kTextColor
;
882 bytes
+= fprintf(file
, "Version = %" B_PRIu32
"\n"
883 "CapsLock = 0x%02" B_PRIx32
"\n"
884 "ScrollLock = 0x%02" B_PRIx32
"\n"
885 "NumLock = 0x%02" B_PRIx32
"\n"
886 "LShift = 0x%02" B_PRIx32
"\n"
887 "RShift = 0x%02" B_PRIx32
"\n"
888 "LCommand = 0x%02" B_PRIx32
"\n"
889 "RCommand = 0x%02" B_PRIx32
"\n"
890 "LControl = 0x%02" B_PRIx32
"\n"
891 "RControl = 0x%02" B_PRIx32
"\n"
892 "LOption = 0x%02" B_PRIx32
"\n"
893 "ROption = 0x%02" B_PRIx32
"\n"
894 "Menu = 0x%02" B_PRIx32
"\n",
895 fKeys
.version
, fKeys
.caps_key
, fKeys
.scroll_key
, fKeys
.num_key
,
896 fKeys
.left_shift_key
, fKeys
.right_shift_key
,
897 fKeys
.left_command_key
, fKeys
.right_command_key
,
898 fKeys
.left_control_key
, fKeys
.right_control_key
,
899 fKeys
.left_option_key
, fKeys
.right_option_key
, fKeys
.menu_key
);
901 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
903 runs
->runs
[4].offset
= bytes
;
904 runs
->runs
[4].font
= *be_fixed_font
;
905 runs
->runs
[4].color
= kCommentColor
;
909 bytes
+= fprintf(file
, "#\n"
911 "# To set NumLock, do the following:\n"
912 "# LockSettings = NumLock\n"
914 "# To set everything, do the following:\n"
915 "# LockSettings = CapsLock NumLock ScrollLock\n"
918 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
920 runs
->runs
[5].offset
= bytes
;
921 runs
->runs
[5].font
= *be_fixed_font
;
922 runs
->runs
[5].color
= kTextColor
;
926 bytes
+= fprintf(file
, "LockSettings = ");
927 if ((fKeys
.lock_settings
& B_CAPS_LOCK
) != 0)
928 bytes
+= fprintf(file
, "CapsLock ");
929 if ((fKeys
.lock_settings
& B_NUM_LOCK
) != 0)
930 bytes
+= fprintf(file
, "NumLock ");
931 if ((fKeys
.lock_settings
& B_SCROLL_LOCK
) != 0)
932 bytes
+= fprintf(file
, "ScrollLock ");
933 bytes
+= fprintf(file
, "\n");
935 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
937 runs
->runs
[6].offset
= bytes
;
938 runs
->runs
[6].font
= *be_fixed_font
;
939 runs
->runs
[6].color
= kCommentColor
;
943 bytes
+= fputs("# Legend:\n"
950 "C Cs Co Cos \n", file
);
953 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
955 runs
->runs
[7].offset
= bytes
;
956 runs
->runs
[7].font
= *be_fixed_font
;
957 runs
->runs
[7].color
= kTextColor
;
961 for (int i
= 0; i
< 128; i
++) {
966 char optionShiftKey
[32];
968 char capsShiftKey
[32];
969 char optionCapsKey
[32];
970 char optionCapsShiftKey
[32];
972 GetKey(fChars
, fKeys
.normal_map
[i
], normalKey
, 32);
973 GetKey(fChars
, fKeys
.shift_map
[i
], shiftKey
, 32);
974 GetKey(fChars
, fKeys
.control_map
[i
], controlKey
, 32);
975 GetKey(fChars
, fKeys
.option_map
[i
], optionKey
, 32);
976 GetKey(fChars
, fKeys
.option_shift_map
[i
], optionShiftKey
, 32);
977 GetKey(fChars
, fKeys
.caps_map
[i
], capsKey
, 32);
978 GetKey(fChars
, fKeys
.caps_shift_map
[i
], capsShiftKey
, 32);
979 GetKey(fChars
, fKeys
.option_caps_map
[i
], optionCapsKey
, 32);
980 GetKey(fChars
, fKeys
.option_caps_shift_map
[i
], optionCapsShiftKey
, 32);
983 "Key 0x%02x = %-9s%-9s%-9s%-9s%-9s%-9s%-9s%-9s%-9s\n", i
,
984 normalKey
, shiftKey
, controlKey
, optionKey
, optionShiftKey
,
985 capsKey
, capsShiftKey
, optionCapsKey
, optionCapsShiftKey
);
988 int32
* deadOffsets
[] = {
989 fKeys
.acute_dead_key
,
990 fKeys
.grave_dead_key
,
991 fKeys
.circumflex_dead_key
,
992 fKeys
.dieresis_dead_key
,
996 char labels
[][12] = {
1004 uint32 deadTables
[] = {
1007 fKeys
.circumflex_tables
,
1008 fKeys
.dieresis_tables
,
1012 for (int i
= 0; i
< 5; i
++) {
1013 for (int deadIndex
= 0; deadIndex
< 32; deadIndex
++) {
1016 if (!GetKey(fChars
, deadOffsets
[i
][deadIndex
++], deadKey
, 32))
1019 GetKey(fChars
, deadOffsets
[i
][deadIndex
], secondKey
, 32);
1020 fprintf(file
, "%s %-9s = %-9s\n", labels
[i
], deadKey
, secondKey
);
1023 fprintf(file
, "%sTab = ", labels
[i
]);
1025 if ((deadTables
[i
] & B_NORMAL_TABLE
) != 0)
1026 fputs("Normal ", file
);
1027 if ((deadTables
[i
] & B_SHIFT_TABLE
) != 0)
1028 fputs("Shift ", file
);
1029 if ((deadTables
[i
] & B_CONTROL_TABLE
) != 0)
1030 fputs("Control ", file
);
1031 if ((deadTables
[i
] & B_OPTION_TABLE
) != 0)
1032 fputs("Option ", file
);
1033 if ((deadTables
[i
] & B_OPTION_SHIFT_TABLE
) != 0)
1034 fputs("Option-Shift ", file
);
1035 if ((deadTables
[i
] & B_CAPS_TABLE
) != 0)
1036 fputs("CapsLock ", file
);
1037 if ((deadTables
[i
] & B_CAPS_SHIFT_TABLE
) != 0)
1038 fputs("CapsLock-Shift ", file
);
1039 if ((deadTables
[i
] & B_OPTION_CAPS_TABLE
) != 0)
1040 fputs("CapsLock-Option ", file
);
1041 if ((deadTables
[i
] & B_OPTION_CAPS_SHIFT_TABLE
) != 0)
1042 fputs("CapsLock-Option-Shift ", file
);
1049 Keymap::_ComputeChars(const char* buffer
, struct re_registers
& regs
, int i
,
1052 char* current
= &fChars
[offset
+ 1];
1056 if (strncmp(buffer
+ regs
.start
[i
], "''", regs
.end
[i
] - regs
.start
[i
])
1059 } else if (sscanf(buffer
+ regs
.start
[i
], "'%s'", current
) > 0) {
1060 if (current
[0] == '\\')
1061 current
[0] = current
[1];
1062 else if (current
[0] == '\'')
1065 } else if (sscanf(buffer
+ regs
.start
[i
], "0x%s", hexChars
) > 0) {
1066 length
= strlen(hexChars
) / 2;
1067 for (uint32 j
= 0; j
< length
; j
++)
1068 sscanf(hexChars
+ 2*j
, "%02hhx", current
+ j
);
1071 fChars
[offset
] = length
;
1072 offset
+= length
+ 1;
1077 Keymap::_ComputeTables(const char* buffer
, struct re_registers
& regs
,
1080 for (int32 i
= 1; i
<= 9; i
++) {
1081 int32 length
= regs
.end
[i
] - regs
.start
[i
];
1085 const char* start
= buffer
+ regs
.start
[i
];
1087 if (strncmp(start
, "Normal", length
) == 0)
1088 table
|= B_NORMAL_TABLE
;
1089 else if (strncmp(start
, "Shift", length
) == 0)
1090 table
|= B_SHIFT_TABLE
;
1091 else if (strncmp(start
, "Control", length
) == 0)
1092 table
|= B_CONTROL_TABLE
;
1093 else if (strncmp(start
, "Option", length
) == 0)
1094 table
|= B_OPTION_TABLE
;
1095 else if (strncmp(start
, "Option-Shift", length
) == 0)
1096 table
|= B_OPTION_SHIFT_TABLE
;
1097 else if (strncmp(start
, "CapsLock", length
) == 0)
1098 table
|= B_CAPS_TABLE
;
1099 else if (strncmp(start
, "CapsLock-Shift", length
) == 0)
1100 table
|= B_CAPS_SHIFT_TABLE
;
1101 else if (strncmp(start
, "CapsLock-Option", length
) == 0)
1102 table
|= B_OPTION_CAPS_TABLE
;
1103 else if (strncmp(start
, "CapsLock-Option-Shift", length
) == 0)
1104 table
|= B_OPTION_CAPS_SHIFT_TABLE
;