From 30dcc55d0a860cde18da7c32ba5f7f66f50a8764 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Tue, 23 Jun 2009 09:44:31 +0000 Subject: [PATCH] * More or less rewrote main.cpp to use getopt_long() instead of the self-made argument evaluation. Also separated the evaluation from performing the options, solving a TODO, and added long versions for the options. * Changed Keymap methods to work on a path instead of entry_refs - this simplifies the code a bit over the place. * Added new option to load a source keymap directly (-s, --load-source). * Renamed some methods to make clearer what they do. * Added a way to directly write a source keymap to a file (by specifying the -o option together with -d). * Coding style cleanup, ordered Keymap methods in the order they are declared. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31195 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/bin/keymap/Keymap.cpp | 1361 +++++++++++++++++++++---------------- src/bin/keymap/Keymap.h | 70 +- src/bin/keymap/main.cpp | 269 +++++--- 3 files changed, 983 insertions(+), 717 deletions(-) diff --git a/src/bin/keymap/Keymap.cpp b/src/bin/keymap/Keymap.cpp index 872247b1a2..dcdce1a2eb 100644 --- a/src/bin/keymap/Keymap.cpp +++ b/src/bin/keymap/Keymap.cpp @@ -1,28 +1,164 @@ /* - * Copyright (c) 2004-2006, Haiku, Inc. + * Copyright 2004-2009, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. * - * This software is part of the Haiku distribution and is covered - * by the Haiku license. - * - * Author: Jérôme Duval + * Authors: + * Jérôme Duval + * Axel Dörfler, axeld@pinc-software.de. */ #include "Keymap.h" +#include +#include +#include + #include #include #include #include #include -#include -#include - #define CHARS_TABLE_MAXSIZE 10000 +extern status_t _restore_key_map_(); + + +// i couldn't put patterns and pattern bufs on the stack without segfaulting +// regexp patterns +const char versionPattern[] + = "Version[[:space:]]+=[[:space:]]+\\([[:digit:]]+\\)"; +const char capslockPattern[] + = "CapsLock[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)"; +const char scrolllockPattern[] + = "ScrollLock[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)"; +const char numlockPattern[] + = "NumLock[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)"; +const char lshiftPattern[] = "LShift[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)"; +const char rshiftPattern[] = "RShift[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)"; +const char lcommandPattern[] + = "LCommand[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)"; +const char rcommandPattern[] + = "RCommand[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)"; +const char lcontrolPattern[] + = "LControl[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)"; +const char rcontrolPattern[] + = "RControl[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)"; +const char loptionPattern[] + = "LOption[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)"; +const char roptionPattern[] + = "ROption[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)"; +const char menuPattern[] = "Menu[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)"; +const char locksettingsPattern[] + = "LockSettings[[:space:]]+=[[:space:]]+\\([[:alnum:]]*\\)" + "[[:space:]]*\\([[:alnum:]]*\\)" + "[[:space:]]*\\([[:alnum:]]*\\)[[:space:]]*"; +const char keyPattern[] = "Key[[:space:]]+\\([[:alnum:]]+\\)[[:space:]]+=" + "[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)" + "[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)" + "[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)" + "[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)" + "[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)" + "[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)" + "[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)" + "[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)" + "[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)" + "[[:space:]]+"; + + +const char acutePattern[] = "Acute[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)" + "[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)[[:space:]]+"; +const char gravePattern[] = "Grave[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)" + "[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)[[:space:]]+"; +const char circumflexPattern[] = "Circumflex[[:space:]]+\\([[:alnum:]]" + "+\\|'.*'\\)[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)[[:space:]]+"; +const char diaeresisPattern[] = "Diaeresis[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)" + "[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)[[:space:]]+"; +const char tildePattern[] = "Tilde[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)" + "[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)[[:space:]]+"; +const char acutetabPattern[] = "AcuteTab[[:space:]]+=" + "[[:space:]]+\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)[[:space:]]*" ; +const char gravetabPattern[] = "GraveTab[[:space:]]+=" + "[[:space:]]+\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)[[:space:]]*" ; +const char circumflextabPattern[] = "CircumflexTab[[:space:]]+=" + "[[:space:]]+\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)[[:space:]]*" ; +const char diaeresistabPattern[] = "DiaeresisTab[[:space:]]+=" + "[[:space:]]+\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)[[:space:]]*" ; +const char tildetabPattern[] = "TildeTab[[:space:]]+=" + "[[:space:]]+\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)" + "[[:space:]]*\\([[:alnum:]-]*\\)[[:space:]]*" ; + + +// re_pattern_buffer buffers +struct re_pattern_buffer versionBuf; +struct re_pattern_buffer capslockBuf; +struct re_pattern_buffer scrolllockBuf; +struct re_pattern_buffer numlockBuf; +struct re_pattern_buffer lshiftBuf; +struct re_pattern_buffer rshiftBuf; +struct re_pattern_buffer lcommandBuf; +struct re_pattern_buffer rcommandBuf; +struct re_pattern_buffer lcontrolBuf; +struct re_pattern_buffer rcontrolBuf; +struct re_pattern_buffer loptionBuf; +struct re_pattern_buffer roptionBuf; +struct re_pattern_buffer menuBuf; +struct re_pattern_buffer locksettingsBuf; +struct re_pattern_buffer keyBuf; +struct re_pattern_buffer acuteBuf; +struct re_pattern_buffer graveBuf; +struct re_pattern_buffer circumflexBuf; +struct re_pattern_buffer diaeresisBuf; +struct re_pattern_buffer tildeBuf; +struct re_pattern_buffer acutetabBuf; +struct re_pattern_buffer gravetabBuf; +struct re_pattern_buffer circumflextabBuf; +struct re_pattern_buffer diaeresistabBuf; +struct re_pattern_buffer tildetabBuf; + + void dump_map(FILE* file, const char* name, int32* map) { @@ -73,205 +209,11 @@ Keymap::~Keymap() } -void -Keymap::GetKey(char *chars, int32 offset, char* string) -{ - int size = chars[offset++]; - char str[32]; - memset(str, 0, 32); - memset(string, 0, 32); - - switch (size) { - case 0: - // Not mapped - sprintf(str, "''"); - break; - - case 1: - // 1-byte UTF-8/ASCII character - if ((uint8)chars[offset] < 0x20 - || (uint8)chars[offset] > 0x7e) - sprintf(str, "0x%02x", (uint8)chars[offset]); - else - sprintf(str, "'%s%c'", - (chars[offset] == '\\' || chars[offset] == '\'') ? "\\" : "", chars[offset]); - break; - - default: - // n-byte UTF-8/ASCII character - sprintf(str, "0x"); - for (int i = 0; i < size; i++) { - sprintf(str + 2*(i+1), "%02x", (uint8)chars[offset+i]); - } - break; - } - - strncpy(string, str, strlen(str) < 12 ? strlen(str) : 12); - // TODO: Huh? -} - - -void -Keymap::Dump() -{ - printf("#!/bin/keymap -l\n" - "#\n" - "#\tRaw key numbering for 101 keyboard...\n" - "# [sys] [brk]\n" - "# 0x7e 0x7f\n" - "# [esc] [ f1] [ f2] [ f3] [ f4] [ f5] [ f6] [ f7] [ f8] [ f9] [f10] [f11] [f12] [prn] [scr] [pau]\n" - "# 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" - "#\n" - "# [ ` ] [ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 7 ] [ 8 ] [ 9 ] [ 0 ] [ - ] [ = ] [bck] [ins] [hme] [pup] [num] [ / ] [ * ] [ - ]\n" - "# 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f 0x20 0x21 0x22 0x23 0x24 0x25\n" - "#\n" - "# [tab] [ q ] [ w ] [ e ] [ r ] [ t ] [ y ] [ u ] [ i ] [ o ] [ p ] [ [ ] [ ] ] [ \\ ] [del] [end] [pdn] [ 7 ] [ 8 ] [ 9 ] [ + ]\n" - "# 0x26 0x27 0x28 0x29 0x2a 0x2b 0x2c 0x2d 0x2e 0x2f 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x3a\n" - "#\n" - "# [cap] [ a ] [ s ] [ d ] [ f ] [ g ] [ h ] [ j ] [ k ] [ l ] [ ; ] [ ' ] [ enter ] [ 4 ] [ 5 ] [ 6 ]\n" - "# 0x3b 0x3c 0x3d 0x3e 0x3f 0x40 0x41 0x42 0x43 0x44 0x45 0x46 0x47 0x48 0x49 0x4a\n" - "#\n" - "# [shift] [ z ] [ x ] [ c ] [ v ] [ b ] [ n ] [ m ] [ , ] [ . ] [ / ] [shift] [ up] [ 1 ] [ 2 ] [ 3 ] [ent]\n" - "# 0x4b 0x4c 0x4d 0x4e 0x4f 0x50 0x51 0x52 0x53 0x54 0x55 0x56 0x57 0x58 0x59 0x5a 0x5b\n" - "#\n" - "# [ctr] [cmd] [ space ] [cmd] [ctr] [lft] [dwn] [rgt] [ 0 ] [ . ]\n" - "# 0x5c 0x5d 0x5e 0x5f 0x60 0x61 0x62 0x63 0x64 0x65\n" - "#\n" - "#\tNOTE: On a Microsoft Natural Keyboard:\n" - "#\t\t\tleft option = 0x66\n" - "#\t\t\tright option = 0x67\n" - "#\t\t\tmenu key = 0x68\n" - "#\tNOTE: On an Apple Extended Keyboard:\n" - "#\t\t\tleft option = 0x66\n" - "#\t\t\tright option = 0x67\n" - "#\t\t\tkeypad '=' = 0x6a\n" - "#\t\t\tpower key = 0x6b\n"); - - printf("Version = %ld\n", fKeys.version); - printf("CapsLock = 0x%02lx\n", fKeys.caps_key); - printf("ScrollLock = 0x%02lx\n", fKeys.scroll_key); - printf("NumLock = 0x%02lx\n", fKeys.num_key); - printf("LShift = 0x%02lx\n", fKeys.left_shift_key); - printf("RShift = 0x%02lx\n", fKeys.right_shift_key); - printf("LCommand = 0x%02lx\n", fKeys.left_command_key); - printf("RCommand = 0x%02lx\n", fKeys.right_command_key); - printf("LControl = 0x%02lx\n", fKeys.left_control_key); - printf("RControl = 0x%02lx\n", fKeys.right_control_key); - printf("LOption = 0x%02lx\n", fKeys.left_option_key); - printf("ROption = 0x%02lx\n", fKeys.right_option_key); - printf("Menu = 0x%02lx\n", fKeys.menu_key); - printf("#\n" - "# Lock settings\n" - "# To set NumLock, do the following:\n" - "# LockSettings = NumLock\n" - "#\n" - "# To set everything, do the following:\n" - "# LockSettings = CapsLock NumLock ScrollLock\n" - "#\n"); - printf("LockSettings = "); - if (fKeys.lock_settings & B_CAPS_LOCK) - printf("CapsLock "); - if (fKeys.lock_settings & B_NUM_LOCK) - printf("NumLock "); - if (fKeys.lock_settings & B_SCROLL_LOCK) - printf("ScrollLock "); - printf("\n"); - printf("# Legend:\n" - "# n = Normal\n" - "# s = Shift\n" - "# c = Control\n" - "# C = CapsLock\n" - "# o = Option\n" - "# Key n s c o os C Cs Co Cos \n"); - - for (int idx = 0; idx < 128; idx++) { - char normalKey[32]; - char shiftKey[32]; - char controlKey[32]; - char optionKey[32]; - char optionShiftKey[32]; - char capsKey[32]; - char capsShiftKey[32]; - char optionCapsKey[32]; - char optionCapsShiftKey[32]; - - GetKey(fChars, fKeys.normal_map[idx], normalKey); - GetKey(fChars, fKeys.shift_map[idx], shiftKey); - GetKey(fChars, fKeys.control_map[idx], controlKey); - GetKey(fChars, fKeys.option_map[idx], optionKey); - GetKey(fChars, fKeys.option_shift_map[idx], optionShiftKey); - GetKey(fChars, fKeys.caps_map[idx], capsKey); - GetKey(fChars, fKeys.caps_shift_map[idx], capsShiftKey); - GetKey(fChars, fKeys.option_caps_map[idx], optionCapsKey); - GetKey(fChars, fKeys.option_caps_shift_map[idx], optionCapsShiftKey); - - printf("Key 0x%02x = %-9s%-9s%-9s%-9s%-9s%-9s%-9s%-9s%-9s\n", idx, normalKey, shiftKey, controlKey, - optionKey, optionShiftKey, capsKey, capsShiftKey, optionCapsKey, optionCapsShiftKey); - } - - int32* deadOffsets[] = { - fKeys.acute_dead_key, - fKeys.grave_dead_key, - fKeys.circumflex_dead_key, - fKeys.dieresis_dead_key, - fKeys.tilde_dead_key - }; - - char labels[][12] = { - "Acute", - "Grave", - "Circumflex", - "Diaeresis", - "Tilde" - }; - - uint32 deadTables[] = { - fKeys.acute_tables, - fKeys.grave_tables, - fKeys.circumflex_tables, - fKeys.dieresis_tables, - fKeys.tilde_tables - }; - - for (int i = 0; i<5; i++) { - for (int idx = 0; idx < 32; idx++ ) { - char deadKey[32]; - char secondKey[32]; - GetKey(fChars, deadOffsets[i][idx++], deadKey); - GetKey(fChars, deadOffsets[i][idx], secondKey); - printf("%s %-9s = %-9s\n", labels[i], deadKey, secondKey); - } - - printf("%sTab = ", labels[i]); - - if (deadTables[i] & B_NORMAL_TABLE) - printf("Normal "); - if (deadTables[i] & B_SHIFT_TABLE) - printf("Shift "); - if (deadTables[i] & B_CONTROL_TABLE) - printf("Control "); - if (deadTables[i] & B_OPTION_TABLE) - printf("Option "); - if (deadTables[i] & B_OPTION_SHIFT_TABLE) - printf("Option-Shift "); - if (deadTables[i] & B_CAPS_TABLE) - printf("CapsLock "); - if (deadTables[i] & B_CAPS_SHIFT_TABLE) - printf("CapsLock-Shift "); - if (deadTables[i] & B_OPTION_CAPS_TABLE) - printf("CapsLock-Option "); - if (deadTables[i] & B_OPTION_CAPS_SHIFT_TABLE) - printf("CapsLock-Option-Shift "); - printf("\n"); - } -} - - status_t Keymap::LoadCurrent() { #if (defined(__BEOS__) || defined(__HAIKU__)) - key_map *keys = NULL; + key_map* keys = NULL; get_key_map(&keys, &fChars); if (!keys) return B_ERROR; @@ -279,7 +221,6 @@ Keymap::LoadCurrent() memcpy(&fKeys, keys, sizeof(fKeys)); free(keys); return B_OK; - #else // ! __BEOS__ fprintf(stderr, "Unsupported operation on this platform!\n"); exit(1); @@ -287,26 +228,32 @@ Keymap::LoadCurrent() } -/*! - Load a map from a file. +/*! Load a map from a file. file format in big endian: struct key_map uint32 size of following charset - charset (offsets go into this with size of character followed by character) + charset (offsets go into this with size of character followed by + character) */ -status_t -Keymap::Load(entry_ref &ref) +status_t +Keymap::Load(const char* name) { - status_t err; + FILE* file = fopen(name, "r"); + if (file == NULL) + return errno; - BFile file(&ref, B_READ_ONLY); - if ((err = file.InitCheck()) != B_OK) - return err; + return Load(file); +} - if (file.Read(&fKeys, sizeof(fKeys)) < (ssize_t)sizeof(fKeys)) + +status_t +Keymap::Load(FILE* file) +{ + if (fread(&fKeys, sizeof(fKeys), 1, file) < 1) return B_BAD_VALUE; + // convert from big-endian for (uint32 i = 0; i < sizeof(fKeys) / 4; i++) { ((uint32*)&fKeys)[i] = B_BENDIAN_TO_HOST_INT32(((uint32*)&fKeys)[i]); } @@ -314,225 +261,59 @@ Keymap::Load(entry_ref &ref) if (fKeys.version != 3) return KEYMAP_ERROR_UNKNOWN_VERSION; - if (file.Read(&fCharsSize, sizeof(uint32)) < (ssize_t)sizeof(uint32)) + if (fread(&fCharsSize, sizeof(uint32), 1, file) < 1) return B_BAD_VALUE; fCharsSize = B_BENDIAN_TO_HOST_INT32(fCharsSize); - if (!fChars) - delete[] fChars; + if (fCharsSize > 16 * 1024) + return B_BAD_DATA; + + delete[] fChars; fChars = new char[fCharsSize]; - if ((unsigned)file.Read(fChars, fCharsSize) != fCharsSize) + + if (fread(fChars, 1, fCharsSize, file) != fCharsSize) return B_BAD_VALUE; return B_OK; } -void -Keymap::ComputeChars(const char *buffer, struct re_registers ®s, int i, int &offset) -{ - char *current = &fChars[offset + 1]; - char hexChars[12]; - uint32 length = 0; - if (strncmp(buffer + regs.start[i], "''", regs.end[i] - regs.start[i]) == 0) - length = 0; - else if (sscanf(buffer + regs.start[i], "'%s'", current) > 0) { - if (current[0] == '\\') - current[0] = current[1]; - else if (current[0] == '\'') - current[0] = ' '; - length = 1; - } else if (sscanf(buffer + regs.start[i], "0x%s", hexChars) > 0) { - length = strlen(hexChars) / 2; - for (uint32 j = 0; j < length; j++) - sscanf(hexChars + 2*j, "%02hhx", current + j); - } - fChars[offset] = length; - offset += length + 1; -} - - -void -Keymap::ComputeTables(const char *buffer, struct re_registers ®s, uint32 &table) -{ - for (int32 i=1; i<=9; i++) { - if (regs.end[i] - regs.start[i] <= 0) - break; - if (strncmp(buffer + regs.start[i], "Normal", regs.end[i] - regs.start[i]) == 0) - table |= B_NORMAL_TABLE; - else if (strncmp(buffer + regs.start[i], "Shift", regs.end[i] - regs.start[i]) == 0) - table |= B_SHIFT_TABLE; - else if (strncmp(buffer + regs.start[i], "Control", regs.end[i] - regs.start[i]) == 0) - table |= B_CONTROL_TABLE; - else if (strncmp(buffer + regs.start[i], "Option", regs.end[i] - regs.start[i]) == 0) - table |= B_OPTION_TABLE; - else if (strncmp(buffer + regs.start[i], "Option-Shift", regs.end[i] - regs.start[i]) == 0) - table |= B_OPTION_SHIFT_TABLE; - else if (strncmp(buffer + regs.start[i], "CapsLock", regs.end[i] - regs.start[i]) == 0) - table |= B_CAPS_TABLE; - else if (strncmp(buffer + regs.start[i], "CapsLock-Shift", regs.end[i] - regs.start[i]) == 0) - table |= B_CAPS_SHIFT_TABLE; - else if (strncmp(buffer + regs.start[i], "CapsLock-Option", regs.end[i] - regs.start[i]) == 0) - table |= B_OPTION_CAPS_TABLE; - else if (strncmp(buffer + regs.start[i], "CapsLock-Option-Shift", regs.end[i] - regs.start[i]) == 0) - table |= B_OPTION_CAPS_SHIFT_TABLE; - } -} - - -status_t -Keymap::LoadSourceFromRef(entry_ref &ref) -{ - status_t err; - - BFile file(&ref, B_READ_ONLY); - if ((err = file.InitCheck()) != B_OK) - return err; - - int fd = file.Dup(); - FILE* f = fdopen(fd, "r"); - if (f != NULL) { - err = LoadSource(f); - fclose(f); - } else - err = B_FILE_ERROR; - - return err; -} - - -// i couldn't put patterns and pattern bufs on the stack without segfaulting -// regexp patterns -const char versionPattern[] = "Version[[:space:]]+=[[:space:]]+\\([[:digit:]]+\\)"; -const char capslockPattern[] = "CapsLock[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)"; -const char scrolllockPattern[] = "ScrollLock[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)"; -const char numlockPattern[] = "NumLock[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)"; -const char lshiftPattern[] = "LShift[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)"; -const char rshiftPattern[] = "RShift[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)"; -const char lcommandPattern[] = "LCommand[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)"; -const char rcommandPattern[] = "RCommand[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)"; -const char lcontrolPattern[] = "LControl[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)"; -const char rcontrolPattern[] = "RControl[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)"; -const char loptionPattern[] = "LOption[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)"; -const char roptionPattern[] = "ROption[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)"; -const char menuPattern[] = "Menu[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)"; -const char locksettingsPattern[] = "LockSettings[[:space:]]+=[[:space:]]+\\([[:alnum:]]*\\)" - "[[:space:]]*\\([[:alnum:]]*\\)" - "[[:space:]]*\\([[:alnum:]]*\\)[[:space:]]*"; -const char keyPattern[] = "Key[[:space:]]+\\([[:alnum:]]+\\)[[:space:]]+=" - "[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)" - "[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)" - "[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)" - "[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)" - "[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)" - "[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)" - "[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)" - "[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)" - "[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)" - "[[:space:]]+"; - - -const char acutePattern[] = "Acute[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)[[:space:]]+"; -const char gravePattern[] = "Grave[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)[[:space:]]+"; -const char circumflexPattern[] = "Circumflex[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)[[:space:]]+"; -const char diaeresisPattern[] = "Diaeresis[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)[[:space:]]+"; -const char tildePattern[] = "Tilde[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)[[:space:]]+"; -const char acutetabPattern[] = "AcuteTab[[:space:]]+=" - "[[:space:]]+\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)[[:space:]]*" ; -const char gravetabPattern[] = "GraveTab[[:space:]]+=" - "[[:space:]]+\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)[[:space:]]*" ; -const char circumflextabPattern[] = "CircumflexTab[[:space:]]+=" - "[[:space:]]+\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)[[:space:]]*" ; -const char diaeresistabPattern[] = "DiaeresisTab[[:space:]]+=" - "[[:space:]]+\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)[[:space:]]*" ; -const char tildetabPattern[] = "TildeTab[[:space:]]+=" - "[[:space:]]+\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)" - "[[:space:]]*\\([[:alnum:]-]*\\)[[:space:]]*" ; - - -// re_pattern_buffer buffers -struct re_pattern_buffer versionBuf; -struct re_pattern_buffer capslockBuf; -struct re_pattern_buffer scrolllockBuf; -struct re_pattern_buffer numlockBuf; -struct re_pattern_buffer lshiftBuf; -struct re_pattern_buffer rshiftBuf; -struct re_pattern_buffer lcommandBuf; -struct re_pattern_buffer rcommandBuf; -struct re_pattern_buffer lcontrolBuf; -struct re_pattern_buffer rcontrolBuf; -struct re_pattern_buffer loptionBuf; -struct re_pattern_buffer roptionBuf; -struct re_pattern_buffer menuBuf; -struct re_pattern_buffer locksettingsBuf; -struct re_pattern_buffer keyBuf; -struct re_pattern_buffer acuteBuf; -struct re_pattern_buffer graveBuf; -struct re_pattern_buffer circumflexBuf; -struct re_pattern_buffer diaeresisBuf; -struct re_pattern_buffer tildeBuf; -struct re_pattern_buffer acutetabBuf; -struct re_pattern_buffer gravetabBuf; -struct re_pattern_buffer circumflextabBuf; -struct re_pattern_buffer diaeresistabBuf; -struct re_pattern_buffer tildetabBuf; - status_t -Keymap::LoadSource(FILE * f) +Keymap::LoadSource(const char* name) { + FILE* file = fopen(name, "r"); + if (file == NULL) + return errno; + + status_t status = LoadSource(file); + fclose(file); + + return status; +} + + +status_t +Keymap::LoadSource(FILE* file) +{ + // Setup regexp parser + reg_syntax_t syntax = RE_CHAR_CLASSES; re_set_syntax(syntax); - - const char* error; - error = re_compile_pattern(versionPattern, strlen(versionPattern), &versionBuf); + + const char* error = re_compile_pattern(versionPattern, + strlen(versionPattern), &versionBuf); if (error) fprintf(stderr, error); - error = re_compile_pattern(capslockPattern, strlen(capslockPattern), &capslockBuf); + error = re_compile_pattern(capslockPattern, strlen(capslockPattern), + &capslockBuf); if (error) fprintf(stderr, error); - error = re_compile_pattern(scrolllockPattern, strlen(scrolllockPattern), &scrolllockBuf); + error = re_compile_pattern(scrolllockPattern, strlen(scrolllockPattern), + &scrolllockBuf); if (error) fprintf(stderr, error); - error = re_compile_pattern(numlockPattern, strlen(numlockPattern), &numlockBuf); + error = re_compile_pattern(numlockPattern, strlen(numlockPattern), + &numlockBuf); if (error) fprintf(stderr, error); error = re_compile_pattern(lshiftPattern, strlen(lshiftPattern), &lshiftBuf); @@ -541,28 +322,35 @@ Keymap::LoadSource(FILE * f) error = re_compile_pattern(rshiftPattern, strlen(rshiftPattern), &rshiftBuf); if (error) fprintf(stderr, error); - error = re_compile_pattern(lcommandPattern, strlen(lcommandPattern), &lcommandBuf); + error = re_compile_pattern(lcommandPattern, strlen(lcommandPattern), + &lcommandBuf); if (error) fprintf(stderr, error); - error = re_compile_pattern(rcommandPattern, strlen(rcommandPattern), &rcommandBuf); + error = re_compile_pattern(rcommandPattern, strlen(rcommandPattern), + &rcommandBuf); if (error) fprintf(stderr, error); - error = re_compile_pattern(lcontrolPattern, strlen(lcontrolPattern), &lcontrolBuf); + error = re_compile_pattern(lcontrolPattern, strlen(lcontrolPattern), + &lcontrolBuf); if (error) fprintf(stderr, error); - error = re_compile_pattern(rcontrolPattern, strlen(rcontrolPattern), &rcontrolBuf); + error = re_compile_pattern(rcontrolPattern, strlen(rcontrolPattern), + &rcontrolBuf); if (error) fprintf(stderr, error); - error = re_compile_pattern(loptionPattern, strlen(loptionPattern), &loptionBuf); + error = re_compile_pattern(loptionPattern, strlen(loptionPattern), + &loptionBuf); if (error) fprintf(stderr, error); - error = re_compile_pattern(roptionPattern, strlen(roptionPattern), &roptionBuf); + error = re_compile_pattern(roptionPattern, strlen(roptionPattern), + &roptionBuf); if (error) fprintf(stderr, error); error = re_compile_pattern(menuPattern, strlen(menuPattern), &menuBuf); if (error) fprintf(stderr, error); - error = re_compile_pattern(locksettingsPattern, strlen(locksettingsPattern), &locksettingsBuf); + error = re_compile_pattern(locksettingsPattern, strlen(locksettingsPattern), + &locksettingsBuf); if (error) fprintf(stderr, error); error = re_compile_pattern(keyPattern, strlen(keyPattern), &keyBuf); @@ -574,32 +362,39 @@ Keymap::LoadSource(FILE * f) error = re_compile_pattern(gravePattern, strlen(gravePattern), &graveBuf); if (error) fprintf(stderr, error); - error = re_compile_pattern(circumflexPattern, strlen(circumflexPattern), &circumflexBuf); + error = re_compile_pattern(circumflexPattern, strlen(circumflexPattern), + &circumflexBuf); if (error) fprintf(stderr, error); - error = re_compile_pattern(diaeresisPattern, strlen(diaeresisPattern), &diaeresisBuf); + error = re_compile_pattern(diaeresisPattern, strlen(diaeresisPattern), + &diaeresisBuf); if (error) fprintf(stderr, error); error = re_compile_pattern(tildePattern, strlen(tildePattern), &tildeBuf); if (error) fprintf(stderr, error); - error = re_compile_pattern(acutetabPattern, strlen(acutetabPattern), ´tabBuf); + error = re_compile_pattern(acutetabPattern, strlen(acutetabPattern), + ´tabBuf); if (error) fprintf(stderr, error); - error = re_compile_pattern(gravetabPattern, strlen(gravetabPattern), &gravetabBuf); + error = re_compile_pattern(gravetabPattern, strlen(gravetabPattern), + &gravetabBuf); if (error) fprintf(stderr, error); - error = re_compile_pattern(circumflextabPattern, strlen(circumflextabPattern), &circumflextabBuf); + error = re_compile_pattern(circumflextabPattern, + strlen(circumflextabPattern), &circumflextabBuf); if (error) fprintf(stderr, error); - error = re_compile_pattern(diaeresistabPattern, strlen(diaeresistabPattern), &diaeresistabBuf); + error = re_compile_pattern(diaeresistabPattern, strlen(diaeresistabPattern), + &diaeresistabBuf); if (error) fprintf(stderr, error); - error = re_compile_pattern(tildetabPattern, strlen(tildetabPattern), &tildetabBuf); + error = re_compile_pattern(tildetabPattern, strlen(tildetabPattern), + &tildetabBuf); if (error) fprintf(stderr, error); - char buffer[1024]; + // Read file delete[] fChars; fChars = new char[CHARS_TABLE_MAXSIZE]; @@ -611,7 +406,7 @@ Keymap::LoadSource(FILE * f) int diaeresisOffset = 0; int tildeOffset = 0; - int32 *maps[] = { + int32* maps[] = { fKeys.normal_map, fKeys.shift_map, fKeys.control_map, @@ -623,93 +418,118 @@ Keymap::LoadSource(FILE * f) fKeys.option_caps_shift_map }; - while (fgets(buffer, 1024-1, f) != NULL) { + char buffer[1024]; + + while (fgets(buffer, sizeof(buffer) - 1, file) != NULL) { if (buffer[0] == '#' || buffer[0] == '\n') continue; + size_t length = strlen(buffer); + struct re_registers regs; - if (re_search(&versionBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { + if (re_search(&versionBuf, buffer, length, 0, length, ®s) >= 0) { sscanf(buffer + regs.start[1], "%ld", &fKeys.version); - } else if (re_search(&capslockBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { + } else if (re_search(&capslockBuf, buffer, length, 0, length, ®s) + >= 0) { sscanf(buffer + regs.start[1], "0x%lx", &fKeys.caps_key); - } else if (re_search(&scrolllockBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { + } else if (re_search(&scrolllockBuf, buffer, length, 0, length, ®s) + >= 0) { sscanf(buffer + regs.start[1], "0x%lx", &fKeys.scroll_key); - } else if (re_search(&numlockBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { + } else if (re_search(&numlockBuf, buffer, length, 0, length, ®s) + >= 0) { sscanf(buffer + regs.start[1], "0x%lx", &fKeys.num_key); - } else if (re_search(&lshiftBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { + } else if (re_search(&lshiftBuf, buffer, length, 0, length, ®s) + >= 0) { sscanf(buffer + regs.start[1], "0x%lx", &fKeys.left_shift_key); - } else if (re_search(&rshiftBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { + } else if (re_search(&rshiftBuf, buffer, length, 0, length, ®s) + >= 0) { sscanf(buffer + regs.start[1], "0x%lx", &fKeys.right_shift_key); - } else if (re_search(&lcommandBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { + } else if (re_search(&lcommandBuf, buffer, length, 0, length, ®s) + >= 0) { sscanf(buffer + regs.start[1], "0x%lx", &fKeys.left_command_key); - } else if (re_search(&rcommandBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { + } else if (re_search(&rcommandBuf, buffer, length, 0, length, ®s) + >= 0) { sscanf(buffer + regs.start[1], "0x%lx", &fKeys.right_command_key); - } else if (re_search(&lcontrolBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { + } else if (re_search(&lcontrolBuf, buffer, length, 0, length, ®s) + >= 0) { sscanf(buffer + regs.start[1], "0x%lx", &fKeys.left_control_key); - } else if (re_search(&rcontrolBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { + } else if (re_search(&rcontrolBuf, buffer, length, 0, length, ®s) + >= 0) { sscanf(buffer + regs.start[1], "0x%lx", &fKeys.right_control_key); - } else if (re_search(&loptionBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { + } else if (re_search(&loptionBuf, buffer, length, 0, length, ®s) + >= 0) { sscanf(buffer + regs.start[1], "0x%lx", &fKeys.left_option_key); - } else if (re_search(&roptionBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { + } else if (re_search(&roptionBuf, buffer, length, 0, length, ®s) + >= 0) { sscanf(buffer + regs.start[1], "0x%lx", &fKeys.right_option_key); - } else if (re_search(&menuBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { + } else if (re_search(&menuBuf, buffer, length, 0, length, ®s) >= 0) { sscanf(buffer + regs.start[1], "0x%lx", &fKeys.menu_key); - } else if (re_search(&locksettingsBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { + } else if (re_search(&locksettingsBuf, buffer, length, 0, length, ®s) + >= 0) { fKeys.lock_settings = 0; for (int32 i = 1; i <= 3; i++) { - if (regs.end[i] - regs.start[i] <= 0) + const char* start = buffer + regs.start[i]; + length = regs.end[i] - regs.start[i]; + if (length == 0) break; - if (strncmp(buffer + regs.start[i], "CapsLock", regs.end[i] - regs.start[i]) == 0) + if (!strncmp(start, "CapsLock", length)) fKeys.lock_settings |= B_CAPS_LOCK; - else if (strncmp(buffer + regs.start[i], "NumLock", regs.end[i] - regs.start[i]) == 0) + else if (!strncmp(start, "NumLock", length)) fKeys.lock_settings |= B_NUM_LOCK; - else if (strncmp(buffer + regs.start[i], "ScrollLock", regs.end[i] - regs.start[i]) == 0) + else if (!strncmp(start, "ScrollLock", length)) fKeys.lock_settings |= B_SCROLL_LOCK; } - } else if (re_search(&keyBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { - uint32 keyCode; + } else if (re_search(&keyBuf, buffer, length, 0, length, ®s) >= 0) { + uint32 keyCode; if (sscanf(buffer + regs.start[1], "0x%lx", &keyCode) > 0) { for (int i = 2; i <= 10; i++) { maps[i - 2][keyCode] = offset; - ComputeChars(buffer, regs, i, offset); + _ComputeChars(buffer, regs, i, offset); } } - } else if (re_search(´Buf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { + } else if (re_search(´Buf, buffer, length, 0, length, ®s) >= 0) { for (int i = 1; i <= 2; i++) { - fKeys.acute_dead_key[acuteOffset++] = offset; - ComputeChars(buffer, regs, i, offset); + fKeys.acute_dead_key[acuteOffset++] = offset; + _ComputeChars(buffer, regs, i, offset); } - } else if (re_search(&graveBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { + } else if (re_search(&graveBuf, buffer, length, 0, length, ®s) >= 0) { for (int i = 1; i <= 2; i++) { - fKeys.grave_dead_key[graveOffset++] = offset; - ComputeChars(buffer, regs, i, offset); + fKeys.grave_dead_key[graveOffset++] = offset; + _ComputeChars(buffer, regs, i, offset); } - } else if (re_search(&circumflexBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { + } else if (re_search(&circumflexBuf, buffer, length, 0, length, ®s) + >= 0) { for (int i = 1; i <= 2; i++) { - fKeys.circumflex_dead_key[circumflexOffset++] = offset; - ComputeChars(buffer, regs, i, offset); + fKeys.circumflex_dead_key[circumflexOffset++] = offset; + _ComputeChars(buffer, regs, i, offset); } - } else if (re_search(&diaeresisBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { + } else if (re_search(&diaeresisBuf, buffer, length, 0, length, ®s) + >= 0) { for (int i = 1; i <= 2; i++) { - fKeys.dieresis_dead_key[diaeresisOffset++] = offset; - ComputeChars(buffer, regs, i, offset); + fKeys.dieresis_dead_key[diaeresisOffset++] = offset; + _ComputeChars(buffer, regs, i, offset); } - } else if (re_search(&tildeBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { + } else if (re_search(&tildeBuf, buffer, length, 0, length, ®s) >= 0) { for (int i = 1; i <= 2; i++) { - fKeys.tilde_dead_key[tildeOffset++] = offset; - ComputeChars(buffer, regs, i, offset); + fKeys.tilde_dead_key[tildeOffset++] = offset; + _ComputeChars(buffer, regs, i, offset); } - } else if (re_search(´tabBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { - ComputeTables(buffer, regs, fKeys.acute_tables); - } else if (re_search(&gravetabBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { - ComputeTables(buffer, regs, fKeys.grave_tables); - } else if (re_search(&circumflextabBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { - ComputeTables(buffer, regs, fKeys.circumflex_tables); - } else if (re_search(&diaeresistabBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { - ComputeTables(buffer, regs, fKeys.dieresis_tables); - } else if (re_search(&tildetabBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { - ComputeTables(buffer, regs, fKeys.tilde_tables); + } else if (re_search(´tabBuf, buffer, length, 0, length, ®s) + >= 0) { + _ComputeTables(buffer, regs, fKeys.acute_tables); + } else if (re_search(&gravetabBuf, buffer, length, 0, length, ®s) + >= 0) { + _ComputeTables(buffer, regs, fKeys.grave_tables); + } else if (re_search(&circumflextabBuf, buffer, length, 0, length, ®s) + >= 0) { + _ComputeTables(buffer, regs, fKeys.circumflex_tables); + } else if (re_search(&diaeresistabBuf, buffer, length, 0, length, ®s) + >= 0) { + _ComputeTables(buffer, regs, fKeys.dieresis_tables); + } else if (re_search(&tildetabBuf, buffer, length, 0, length, ®s) + >= 0) { + _ComputeTables(buffer, regs, fKeys.tilde_tables); } } @@ -720,17 +540,41 @@ Keymap::LoadSource(FILE * f) return B_OK; } - -//! we save a map to a file -status_t -Keymap::Save(entry_ref &ref) + +status_t +Keymap::SaveAsCurrent() { - status_t err; +#if (defined(__BEOS__) || defined(__HAIKU__)) + BPath path; + status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path, true); + if (status != B_OK) + return status; - BFile file(&ref, B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE ); - if ((err = file.InitCheck()) != B_OK) - return err; + path.Append("Key_map"); + + status = Save(path.Path()); + if (status != B_OK) + return status; + + Use(); + return B_OK; +#else // ! __BEOS__ + fprintf(stderr, "Unsupported operation on this platform!\n"); + exit(1); +#endif // ! __BEOS__ +} + + +//! Save a binary keymap to a file. +status_t +Keymap::Save(const char* name) +{ + BFile file; + status_t status = file.SetTo(name, + B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE); + if (status != B_OK) + return status; // convert to big endian for (uint32 i = 0; i < sizeof(fKeys) / sizeof(uint32); i++) { @@ -767,35 +611,56 @@ Keymap::Save(entry_ref &ref) } -/*! - Save a keymap as C source file - this is used to get the default keymap - into the input_server, for example. -*/ -void -Keymap::SaveAsHeader(entry_ref &ref, const char *mapName) +status_t +Keymap::SaveAsSource(const char* name) { - BPath path; - status_t err = path.SetTo(&ref); - if (err < B_OK) - return; + FILE* file = fopen(name, "w"); + if (file == NULL) + return errno; + _SaveSourceText(file); + return B_OK; +} + + +status_t +Keymap::SaveAsSource(FILE* file) +{ + _SaveSourceText(file); + return B_OK; +} + + +/*! Save a keymap as C source file - this is used to get the default keymap + into the input_server, for example. + \a mapName is usually the path of the input keymap, and is used as the + name of the keymap (the path will be removed, as well as its suffix). +*/ +status_t +Keymap::SaveAsCppHeader(const char* fileName, const char* mapName) +{ BString name = mapName; - int slashidx = name.FindLast('/'); - if (slashidx > 0) { - // prune off path - name.Remove(0, slashidx + 1); - } - // prune ".keymap" - name.Remove(name.FindLast('.'), 7); - FILE* file = fopen(path.Path(), "w"); + // cut off path + int32 index = name.FindLast('/'); + if (index > 0) + name.Remove(0, index + 1); + + // prune ".keymap" + index = name.FindLast('.'); + if (index > 0) + name.Truncate(index); + + FILE* file = fopen(fileName, "w"); + if (file == NULL) + return errno; fprintf(file, "/*\n" " * Haiku Keymap\n" " * This file is generated automatically. Don't edit!\n" " */\n\n"); fprintf(file, "#include \n\n"); - fprintf(file, "const char *kSystemKeymapName = \"%s\";\n\n", name.String()); + fprintf(file, "const char *kSystemKeymapName = \"%s\";\n\n", name.String()); fprintf(file, "const key_map kSystemKeymap = {\n"); fprintf(file, "\tversion:%ld,\n", fKeys.version); fprintf(file, "\tcaps_key:0x%lx,\n", fKeys.caps_key); @@ -852,14 +717,29 @@ Keymap::SaveAsHeader(entry_ref &ref, const char *mapName) fprintf(file, "const uint32 kSystemKeyCharsSize = %ld;\n", fCharsSize); fclose(file); + + return B_OK; } -/*! - We need to know if a key is a modifier key to choose +//! We make our input server use the map in /boot/home/config/settings/Keymap +status_t +Keymap::Use() +{ +#if (defined(__BEOS__) || defined(__HAIKU__)) + return _restore_key_map_(); + +#else // ! __BEOS__ + fprintf(stderr, "Unsupported operation on this platform!\n"); + exit(1); +#endif // ! __BEOS__ +} + + +/*! We need to know if a key is a modifier key to choose a valid key when several are pressed together */ -bool +bool Keymap::IsModifierKey(uint32 keyCode) { return keyCode == fKeys.caps_key @@ -884,27 +764,55 @@ Keymap::IsDeadKey(uint32 keyCode, uint32 modifiers) uint32 tableMask = 0; switch (modifiers & 0xcf) { - case B_SHIFT_KEY: offset = fKeys.shift_map[keyCode]; tableMask = B_SHIFT_TABLE; break; - case B_CAPS_LOCK: offset = fKeys.caps_map[keyCode]; tableMask = B_CAPS_TABLE; break; - case B_CAPS_LOCK|B_SHIFT_KEY: offset = fKeys.caps_shift_map[keyCode]; tableMask = B_CAPS_SHIFT_TABLE; break; - case B_OPTION_KEY: offset = fKeys.option_map[keyCode]; tableMask = B_OPTION_TABLE; break; - case B_OPTION_KEY|B_SHIFT_KEY: offset = fKeys.option_shift_map[keyCode]; tableMask = B_OPTION_SHIFT_TABLE; break; - case B_OPTION_KEY|B_CAPS_LOCK: offset = fKeys.option_caps_map[keyCode]; tableMask = B_OPTION_CAPS_TABLE; break; - case B_OPTION_KEY|B_SHIFT_KEY|B_CAPS_LOCK: offset = fKeys.option_caps_shift_map[keyCode]; tableMask = B_OPTION_CAPS_SHIFT_TABLE; break; - case B_CONTROL_KEY: offset = fKeys.control_map[keyCode]; tableMask = B_CONTROL_TABLE; break; - default: offset = fKeys.normal_map[keyCode]; tableMask = B_NORMAL_TABLE; break; + case B_SHIFT_KEY: + offset = fKeys.shift_map[keyCode]; + tableMask = B_SHIFT_TABLE; + break; + case B_CAPS_LOCK: + offset = fKeys.caps_map[keyCode]; + tableMask = B_CAPS_TABLE; + break; + case B_CAPS_LOCK | B_SHIFT_KEY: + offset = fKeys.caps_shift_map[keyCode]; + tableMask = B_CAPS_SHIFT_TABLE; + break; + case B_OPTION_KEY: + offset = fKeys.option_map[keyCode]; + tableMask = B_OPTION_TABLE; + break; + case B_OPTION_KEY | B_SHIFT_KEY: + offset = fKeys.option_shift_map[keyCode]; + tableMask = B_OPTION_SHIFT_TABLE; + break; + case B_OPTION_KEY | B_CAPS_LOCK: + offset = fKeys.option_caps_map[keyCode]; + tableMask = B_OPTION_CAPS_TABLE; + break; + case B_OPTION_KEY | B_SHIFT_KEY | B_CAPS_LOCK: + offset = fKeys.option_caps_shift_map[keyCode]; + tableMask = B_OPTION_CAPS_SHIFT_TABLE; + break; + case B_CONTROL_KEY: + offset = fKeys.control_map[keyCode]; + tableMask = B_CONTROL_TABLE; + break; + + default: + offset = fKeys.normal_map[keyCode]; + tableMask = B_NORMAL_TABLE; + break; } if (offset <= 0) - return 0; + return 0; uint32 numBytes = fChars[offset]; if (!numBytes) return 0; - char chars[4]; - strncpy(chars, &(fChars[offset+1]), numBytes ); - chars[numBytes] = 0; + char chars[4]; + strncpy(chars, &(fChars[offset+1]), numBytes); + chars[numBytes] = 0; int32 deadOffsets[] = { fKeys.acute_dead_key[1], @@ -912,7 +820,7 @@ Keymap::IsDeadKey(uint32 keyCode, uint32 modifiers) fKeys.circumflex_dead_key[1], fKeys.dieresis_dead_key[1], fKeys.tilde_dead_key[1] - }; + }; uint32 deadTables[] = { fKeys.acute_tables, @@ -934,8 +842,8 @@ Keymap::IsDeadKey(uint32 keyCode, uint32 modifiers) if (!deadNumBytes) continue; - if (strncmp(chars, &(fChars[deadOffsets[i]+1]), deadNumBytes ) == 0) - return i+1; + if (strncmp(chars, &fChars[deadOffsets[i] + 1], deadNumBytes) == 0) + return i + 1; } return 0; } @@ -951,15 +859,34 @@ Keymap::IsDeadSecondKey(uint32 keyCode, uint32 modifiers, uint8 activeDeadKey) int32 offset; switch (modifiers & 0xcf) { - case B_SHIFT_KEY: offset = fKeys.shift_map[keyCode]; break; - case B_CAPS_LOCK: offset = fKeys.caps_map[keyCode]; break; - case B_CAPS_LOCK|B_SHIFT_KEY: offset = fKeys.caps_shift_map[keyCode]; break; - case B_OPTION_KEY: offset = fKeys.option_map[keyCode]; break; - case B_OPTION_KEY|B_SHIFT_KEY: offset = fKeys.option_shift_map[keyCode]; break; - case B_OPTION_KEY|B_CAPS_LOCK: offset = fKeys.option_caps_map[keyCode]; break; - case B_OPTION_KEY|B_SHIFT_KEY|B_CAPS_LOCK: offset = fKeys.option_caps_shift_map[keyCode]; break; - case B_CONTROL_KEY: offset = fKeys.control_map[keyCode]; break; - default: offset = fKeys.normal_map[keyCode]; break; + case B_SHIFT_KEY: + offset = fKeys.shift_map[keyCode]; + break; + case B_CAPS_LOCK: + offset = fKeys.caps_map[keyCode]; + break; + case B_CAPS_LOCK | B_SHIFT_KEY: + offset = fKeys.caps_shift_map[keyCode]; + break; + case B_OPTION_KEY: + offset = fKeys.option_map[keyCode]; + break; + case B_OPTION_KEY | B_SHIFT_KEY: + offset = fKeys.option_shift_map[keyCode]; + break; + case B_OPTION_KEY | B_CAPS_LOCK: + offset = fKeys.option_caps_map[keyCode]; + break; + case B_OPTION_KEY | B_SHIFT_KEY|B_CAPS_LOCK: + offset = fKeys.option_caps_shift_map[keyCode]; + break; + case B_CONTROL_KEY: + offset = fKeys.control_map[keyCode]; + break; + + default: + offset = fKeys.normal_map[keyCode]; + break; } uint32 numBytes = fChars[offset]; @@ -975,7 +902,7 @@ Keymap::IsDeadSecondKey(uint32 keyCode, uint32 modifiers, uint8 activeDeadKey) fKeys.tilde_dead_key }; - int32 *deadOffset = deadOffsets[activeDeadKey - 1]; + int32 *deadOffset = deadOffsets[activeDeadKey - 1]; for (int32 i = 0; i < 32; i++) { if (offset == deadOffset[i]) @@ -986,7 +913,8 @@ Keymap::IsDeadSecondKey(uint32 keyCode, uint32 modifiers, uint8 activeDeadKey) if (!deadNumBytes) continue; - if (strncmp(&(fChars[offset+1]), &(fChars[deadOffset[i]+1]), deadNumBytes) == 0) + if (strncmp(&fChars[offset + 1], &fChars[deadOffset[i] + 1], + deadNumBytes) == 0) return true; i++; @@ -1025,15 +953,34 @@ Keymap::GetChars(uint32 keyCode, uint32 modifiers, uint8 activeDeadKey, // here we choose the right map given the modifiers switch (modifiers & 0xcf) { - case B_SHIFT_KEY: offset = fKeys.shift_map[keyCode]; break; - case B_CAPS_LOCK: offset = fKeys.caps_map[keyCode]; break; - case B_CAPS_LOCK|B_SHIFT_KEY: offset = fKeys.caps_shift_map[keyCode]; break; - case B_OPTION_KEY: offset = fKeys.option_map[keyCode]; break; - case B_OPTION_KEY|B_SHIFT_KEY: offset = fKeys.option_shift_map[keyCode]; break; - case B_OPTION_KEY|B_CAPS_LOCK: offset = fKeys.option_caps_map[keyCode]; break; - case B_OPTION_KEY|B_SHIFT_KEY|B_CAPS_LOCK: offset = fKeys.option_caps_shift_map[keyCode]; break; - case B_CONTROL_KEY: offset = fKeys.control_map[keyCode]; break; - default: offset = fKeys.normal_map[keyCode]; break; + case B_SHIFT_KEY: + offset = fKeys.shift_map[keyCode]; + break; + case B_CAPS_LOCK: + offset = fKeys.caps_map[keyCode]; + break; + case B_CAPS_LOCK | B_SHIFT_KEY: + offset = fKeys.caps_shift_map[keyCode]; + break; + case B_OPTION_KEY: + offset = fKeys.option_map[keyCode]; + break; + case B_OPTION_KEY | B_SHIFT_KEY: + offset = fKeys.option_shift_map[keyCode]; + break; + case B_OPTION_KEY | B_CAPS_LOCK: + offset = fKeys.option_caps_map[keyCode]; + break; + case B_OPTION_KEY | B_SHIFT_KEY | B_CAPS_LOCK: + offset = fKeys.option_caps_shift_map[keyCode]; + break; + case B_CONTROL_KEY: + offset = fKeys.control_map[keyCode]; + break; + + default: + offset = fKeys.normal_map[keyCode]; + break; } // here we get the char size @@ -1043,56 +990,63 @@ Keymap::GetChars(uint32 keyCode, uint32 modifiers, uint8 activeDeadKey, return; // here we take an potential active dead key - int32 *dead_key; + int32* deadKey; switch (activeDeadKey) { - case 1: dead_key = fKeys.acute_dead_key; break; - case 2: dead_key = fKeys.grave_dead_key; break; - case 3: dead_key = fKeys.circumflex_dead_key; break; - case 4: dead_key = fKeys.dieresis_dead_key; break; - case 5: dead_key = fKeys.tilde_dead_key; break; + case 1: + deadKey = fKeys.acute_dead_key; + break; + case 2: + deadKey = fKeys.grave_dead_key; + break; + case 3: + deadKey = fKeys.circumflex_dead_key; + break; + case 4: + deadKey = fKeys.dieresis_dead_key; + break; + case 5: + deadKey = fKeys.tilde_dead_key; + break; - default: + default: // if not dead, we copy and return the char - char *str = *chars = new char[*numBytes + 1]; - strncpy(str, &(fChars[offset+1]), *numBytes ); + char *str = *chars = new char[*numBytes + 1]; + strncpy(str, &fChars[offset + 1], *numBytes); str[*numBytes] = 0; return; } - // if dead key, we search for our current offset char in the dead key offset table - // string comparison is needed + // If dead key, we search for our current offset char in the dead key offset + // table string comparison is needed for (int32 i = 0; i < 32; i++) { - if (strncmp(&(fChars[offset+1]), &(fChars[dead_key[i]+1]), *numBytes ) == 0) { - *numBytes = fChars[dead_key[i+1]]; + if (!strncmp(&fChars[offset + 1], &fChars[deadKey[i] + 1], *numBytes)) { + *numBytes = fChars[deadKey[i + 1]]; switch (*numBytes) { case 0: // Not mapped - *chars = NULL; - break; + *chars = NULL; + break; default: - // 1-, 2-, 3-, or 4-byte UTF-8 character - char *str = *chars = new char[*numBytes + 1]; - strncpy(str, &fChars[dead_key[i+1]+1], *numBytes ); - str[*numBytes] = 0; - break; + // 1-, 2-, 3-, or 4-byte UTF-8 character + char* str = *chars = new char[*numBytes + 1]; + strncpy(str, &fChars[deadKey[i + 1] + 1], *numBytes); + str[*numBytes] = 0; + break; } return; - } + } i++; } - // if not found we return the current char mapped + // if not found we return the current char mapped *chars = new char[*numBytes + 1]; - strncpy(*chars, &(fChars[offset+1]), *numBytes ); - (*chars)[*numBytes] = 0; + strncpy(*chars, &(fChars[offset+1]), *numBytes); + (*chars)[*numBytes] = 0; } -status_t _restore_key_map_(); - - void Keymap::RestoreSystemDefault() { @@ -1118,42 +1072,257 @@ Keymap::RestoreSystemDefault() } -void -Keymap::SaveAsCurrent() +/*static*/ void +Keymap::GetKey(char* chars, int32 offset, char* string) { -#if (defined(__BEOS__) || defined(__HAIKU__)) - BPath path; - if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK) - return; + int size = chars[offset++]; + char str[32]; + memset(str, 0, 32); + memset(string, 0, 32); - path.Append("Key_map"); + switch (size) { + case 0: + // Not mapped + sprintf(str, "''"); + break; - entry_ref ref; - get_ref_for_path(path.Path(), &ref); + case 1: + // 1-byte UTF-8/ASCII character + if ((uint8)chars[offset] < 0x20 + || (uint8)chars[offset] > 0x7e) + sprintf(str, "0x%02x", (uint8)chars[offset]); + else + sprintf(str, "'%s%c'", + (chars[offset] == '\\' || chars[offset] == '\'') ? "\\" : "", + chars[offset]); + break; - status_t err; - if ((err = Save(ref)) != B_OK) { - printf("error when saving : %s", strerror(err)); - return; + default: + // n-byte UTF-8/ASCII character + sprintf(str, "0x"); + for (int i = 0; i < size; i++) { + sprintf(str + 2*(i+1), "%02x", (uint8)chars[offset+i]); + } + break; } - Use(); -#else // ! __BEOS__ - fprintf(stderr, "Unsupported operation on this platform!\n"); - exit(1); -#endif // ! __BEOS__ + strncpy(string, str, strlen(str) < 12 ? strlen(str) : 12); + // TODO: Huh? } -//! We make our input server use the map in /boot/home/config/settings/Keymap -status_t -Keymap::Use() +void +Keymap::_SaveSourceText(FILE* file) { -#if (defined(__BEOS__) || defined(__HAIKU__)) - return _restore_key_map_(); + fprintf(file, "#!/bin/keymap -l\n" + "#\n" + "#\tRaw key numbering for 101 keyboard...\n" + "# [sys] [brk]\n" + "# 0x7e 0x7f\n" + "# [esc] [ f1] [ f2] [ f3] [ f4] [ f5] [ f6] [ f7] [ f8] [ f9] [f10] [f11] [f12] [prn] [scr] [pau]\n" + "# 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" + "#\n" + "# [ ` ] [ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 7 ] [ 8 ] [ 9 ] [ 0 ] [ - ] [ = ] [bck] [ins] [hme] [pup] [num] [ / ] [ * ] [ - ]\n" + "# 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f 0x20 0x21 0x22 0x23 0x24 0x25\n" + "#\n" + "# [tab] [ q ] [ w ] [ e ] [ r ] [ t ] [ y ] [ u ] [ i ] [ o ] [ p ] [ [ ] [ ] ] [ \\ ] [del] [end] [pdn] [ 7 ] [ 8 ] [ 9 ] [ + ]\n" + "# 0x26 0x27 0x28 0x29 0x2a 0x2b 0x2c 0x2d 0x2e 0x2f 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x3a\n" + "#\n" + "# [cap] [ a ] [ s ] [ d ] [ f ] [ g ] [ h ] [ j ] [ k ] [ l ] [ ; ] [ ' ] [ enter ] [ 4 ] [ 5 ] [ 6 ]\n" + "# 0x3b 0x3c 0x3d 0x3e 0x3f 0x40 0x41 0x42 0x43 0x44 0x45 0x46 0x47 0x48 0x49 0x4a\n" + "#\n" + "# [shift] [ z ] [ x ] [ c ] [ v ] [ b ] [ n ] [ m ] [ , ] [ . ] [ / ] [shift] [ up] [ 1 ] [ 2 ] [ 3 ] [ent]\n" + "# 0x4b 0x4c 0x4d 0x4e 0x4f 0x50 0x51 0x52 0x53 0x54 0x55 0x56 0x57 0x58 0x59 0x5a 0x5b\n" + "#\n" + "# [ctr] [cmd] [ space ] [cmd] [ctr] [lft] [dwn] [rgt] [ 0 ] [ . ]\n" + "# 0x5c 0x5d 0x5e 0x5f 0x60 0x61 0x62 0x63 0x64 0x65\n" + "#\n" + "#\tNOTE: On a Microsoft Natural Keyboard:\n" + "#\t\t\tleft option = 0x66\n" + "#\t\t\tright option = 0x67\n" + "#\t\t\tmenu key = 0x68\n" + "#\tNOTE: On an Apple Extended Keyboard:\n" + "#\t\t\tleft option = 0x66\n" + "#\t\t\tright option = 0x67\n" + "#\t\t\tkeypad '=' = 0x6a\n" + "#\t\t\tpower key = 0x6b\n"); -#else // ! __BEOS__ - fprintf(stderr, "Unsupported operation on this platform!\n"); - exit(1); -#endif // ! __BEOS__ + fprintf(file, "Version = %ld\n", fKeys.version); + fprintf(file, "CapsLock = 0x%02lx\n", fKeys.caps_key); + fprintf(file, "ScrollLock = 0x%02lx\n", fKeys.scroll_key); + fprintf(file, "NumLock = 0x%02lx\n", fKeys.num_key); + fprintf(file, "LShift = 0x%02lx\n", fKeys.left_shift_key); + fprintf(file, "RShift = 0x%02lx\n", fKeys.right_shift_key); + fprintf(file, "LCommand = 0x%02lx\n", fKeys.left_command_key); + fprintf(file, "RCommand = 0x%02lx\n", fKeys.right_command_key); + fprintf(file, "LControl = 0x%02lx\n", fKeys.left_control_key); + fprintf(file, "RControl = 0x%02lx\n", fKeys.right_control_key); + fprintf(file, "LOption = 0x%02lx\n", fKeys.left_option_key); + fprintf(file, "ROption = 0x%02lx\n", fKeys.right_option_key); + fprintf(file, "Menu = 0x%02lx\n", fKeys.menu_key); + fprintf(file, "#\n" + "# Lock settings\n" + "# To set NumLock, do the following:\n" + "# LockSettings = NumLock\n" + "#\n" + "# To set everything, do the following:\n" + "# LockSettings = CapsLock NumLock ScrollLock\n" + "#\n"); + fprintf(file, "LockSettings = "); + if (fKeys.lock_settings & B_CAPS_LOCK) + fprintf(file, "CapsLock "); + if (fKeys.lock_settings & B_NUM_LOCK) + fprintf(file, "NumLock "); + if (fKeys.lock_settings & B_SCROLL_LOCK) + fprintf(file, "ScrollLock "); + fprintf(file, "\n"); + fprintf(file, "# Legend:\n" + "# n = Normal\n" + "# s = Shift\n" + "# c = Control\n" + "# C = CapsLock\n" + "# o = Option\n" + "# Key n s c o os C Cs Co Cos \n"); + + for (int idx = 0; idx < 128; idx++) { + char normalKey[32]; + char shiftKey[32]; + char controlKey[32]; + char optionKey[32]; + char optionShiftKey[32]; + char capsKey[32]; + char capsShiftKey[32]; + char optionCapsKey[32]; + char optionCapsShiftKey[32]; + + GetKey(fChars, fKeys.normal_map[idx], normalKey); + GetKey(fChars, fKeys.shift_map[idx], shiftKey); + GetKey(fChars, fKeys.control_map[idx], controlKey); + GetKey(fChars, fKeys.option_map[idx], optionKey); + GetKey(fChars, fKeys.option_shift_map[idx], optionShiftKey); + GetKey(fChars, fKeys.caps_map[idx], capsKey); + GetKey(fChars, fKeys.caps_shift_map[idx], capsShiftKey); + GetKey(fChars, fKeys.option_caps_map[idx], optionCapsKey); + GetKey(fChars, fKeys.option_caps_shift_map[idx], optionCapsShiftKey); + + fprintf(file, "Key 0x%02x = %-9s%-9s%-9s%-9s%-9s%-9s%-9s%-9s%-9s\n", idx, + normalKey, shiftKey, controlKey, optionKey, optionShiftKey, capsKey, + capsShiftKey, optionCapsKey, optionCapsShiftKey); + } + + int32* deadOffsets[] = { + fKeys.acute_dead_key, + fKeys.grave_dead_key, + fKeys.circumflex_dead_key, + fKeys.dieresis_dead_key, + fKeys.tilde_dead_key + }; + + char labels[][12] = { + "Acute", + "Grave", + "Circumflex", + "Diaeresis", + "Tilde" + }; + + uint32 deadTables[] = { + fKeys.acute_tables, + fKeys.grave_tables, + fKeys.circumflex_tables, + fKeys.dieresis_tables, + fKeys.tilde_tables + }; + + for (int i = 0; i < 5; i++) { + for (int idx = 0; idx < 32; idx++) { + char deadKey[32]; + char secondKey[32]; + GetKey(fChars, deadOffsets[i][idx++], deadKey); + GetKey(fChars, deadOffsets[i][idx], secondKey); + fprintf(file, "%s %-9s = %-9s\n", labels[i], deadKey, secondKey); + } + + fprintf(file, "%sTab = ", labels[i]); + + if (deadTables[i] & B_NORMAL_TABLE) + fprintf(file, "Normal "); + if (deadTables[i] & B_SHIFT_TABLE) + fprintf(file, "Shift "); + if (deadTables[i] & B_CONTROL_TABLE) + fprintf(file, "Control "); + if (deadTables[i] & B_OPTION_TABLE) + fprintf(file, "Option "); + if (deadTables[i] & B_OPTION_SHIFT_TABLE) + fprintf(file, "Option-Shift "); + if (deadTables[i] & B_CAPS_TABLE) + fprintf(file, "CapsLock "); + if (deadTables[i] & B_CAPS_SHIFT_TABLE) + fprintf(file, "CapsLock-Shift "); + if (deadTables[i] & B_OPTION_CAPS_TABLE) + fprintf(file, "CapsLock-Option "); + if (deadTables[i] & B_OPTION_CAPS_SHIFT_TABLE) + fprintf(file, "CapsLock-Option-Shift "); + fprintf(file, "\n"); + } +} + + +void +Keymap::_ComputeChars(const char* buffer, struct re_registers& regs, int i, + int& offset) +{ + char* current = &fChars[offset + 1]; + char hexChars[12]; + uint32 length = 0; + + if (strncmp(buffer + regs.start[i], "''", regs.end[i] - regs.start[i]) == 0) + length = 0; + else if (sscanf(buffer + regs.start[i], "'%s'", current) > 0) { + if (current[0] == '\\') + current[0] = current[1]; + else if (current[0] == '\'') + current[0] = ' '; + length = 1; + } else if (sscanf(buffer + regs.start[i], "0x%s", hexChars) > 0) { + length = strlen(hexChars) / 2; + for (uint32 j = 0; j < length; j++) + sscanf(hexChars + 2*j, "%02hhx", current + j); + } + + fChars[offset] = length; + offset += length + 1; +} + + +void +Keymap::_ComputeTables(const char* buffer, struct re_registers& regs, + uint32& table) +{ + for (int32 i = 1; i <= 9; i++) { + int32 length = regs.end[i] - regs.start[i]; + if (length <= 0) + break; + + const char* start = buffer + regs.start[i]; + + if (strncmp(start, "Normal", length) == 0) + table |= B_NORMAL_TABLE; + else if (strncmp(start, "Shift", length) == 0) + table |= B_SHIFT_TABLE; + else if (strncmp(start, "Control", length) == 0) + table |= B_CONTROL_TABLE; + else if (strncmp(start, "Option", length) == 0) + table |= B_OPTION_TABLE; + else if (strncmp(start, "Option-Shift", length) == 0) + table |= B_OPTION_SHIFT_TABLE; + else if (strncmp(start, "CapsLock", length) == 0) + table |= B_CAPS_TABLE; + else if (strncmp(start, "CapsLock-Shift", length) == 0) + table |= B_CAPS_SHIFT_TABLE; + else if (strncmp(start, "CapsLock-Option", length) == 0) + table |= B_OPTION_CAPS_TABLE; + else if (strncmp(start, "CapsLock-Option-Shift", length) == 0) + table |= B_OPTION_CAPS_SHIFT_TABLE; + } } diff --git a/src/bin/keymap/Keymap.h b/src/bin/keymap/Keymap.h index 3f3b9a58b2..338884db87 100644 --- a/src/bin/keymap/Keymap.h +++ b/src/bin/keymap/Keymap.h @@ -1,10 +1,10 @@ /* - * Copyright (c) 2004-2006, Haiku, Inc. + * Copyright 2004-2009, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. * - * This software is part of the Haiku distribution and is covered - * by the Haiku license. - * - * Author: Jérôme Duval + * Authors: + * Jérôme Duval + * Axel Dörfler, axeld@pinc-software.de. */ #ifndef KEYMAP_H #define KEYMAP_H @@ -18,34 +18,44 @@ class Keymap { - public: - Keymap(); - ~Keymap(); +public: + Keymap(); + ~Keymap(); - status_t LoadCurrent(); - status_t Load(entry_ref &ref); - status_t Save(entry_ref &ref); - status_t LoadSource(FILE *f); - status_t LoadSourceFromRef(entry_ref &ref); - void SaveAsCurrent(); - void SaveAsHeader(entry_ref &ref, const char *mapname); - status_t Use(); - void Dump(); - bool IsModifierKey(uint32 keyCode); - uint8 IsDeadKey(uint32 keyCode, uint32 modifiers); - bool IsDeadSecondKey(uint32 keyCode, uint32 modifiers, uint8 activeDeadKey); - void GetChars(uint32 keyCode, uint32 modifiers, uint8 activeDeadKey, - char** chars, int32* numBytes); - void RestoreSystemDefault(); - static void GetKey(char *chars, int32 offset, char* string); + status_t LoadCurrent(); + status_t Load(const char* name); + status_t Load(FILE* file); + status_t LoadSource(const char* name); + status_t LoadSource(FILE* file); + status_t SaveAsCurrent(); + status_t Save(const char* name); + status_t SaveAsSource(const char* name); + status_t SaveAsSource(FILE* file); + status_t SaveAsCppHeader(const char* name, + const char* mapName); - private: - void ComputeChars(const char *buffer, struct re_registers ®s, int i, int &offset); - void ComputeTables(const char *buffer, struct re_registers ®s, uint32 &table); + status_t Use(); - char *fChars; - key_map fKeys; - uint32 fCharsSize; + bool IsModifierKey(uint32 keyCode); + uint8 IsDeadKey(uint32 keyCode, uint32 modifiers); + bool IsDeadSecondKey(uint32 keyCode, uint32 modifiers, + uint8 activeDeadKey); + void GetChars(uint32 keyCode, uint32 modifiers, + uint8 activeDeadKey, char** chars, + int32* numBytes); + void RestoreSystemDefault(); + static void GetKey(char* chars, int32 offset, char* string); + +private: + void _SaveSourceText(FILE* file); + void _ComputeChars(const char* buffer, + struct re_registers& regs, int i, int& offset); + void _ComputeTables(const char* buffer, + struct re_registers& regs, uint32& table); + + char* fChars; + key_map fKeys; + uint32 fCharsSize; }; #define KEYMAP_ERROR_UNKNOWN_VERSION (B_ERRORS_END + 1) diff --git a/src/bin/keymap/main.cpp b/src/bin/keymap/main.cpp index b2b59eb50c..3be5795c5c 100644 --- a/src/bin/keymap/main.cpp +++ b/src/bin/keymap/main.cpp @@ -1,13 +1,14 @@ /* - * Copyright (c) 2004-2006, Haiku, Inc. + * Copyright 2004-2009, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. * - * This software is part of the Haiku distribution and is covered - * by the MIT license. - * - * Author: Jérôme Duval + * Authors: + * Jérôme Duval + * Axel Dörfler, axeld@pinc-software.de. */ +#include #include #include #include @@ -24,21 +25,27 @@ static const char *sProgramName = __progname; static void -usage(void) +usage() { - printf("usage: %s {-o output_file} -[d|l|r|c|b|h input_file]\n" - " -o change output file to output_file (default:keymap.out)\n" - " -d dump key map to standard output\n" - " -l load key map from standard input\n" - " -b load binary key map from file\n" - " -r restore system default key map\n" - " -c compile source keymap to binary\n" - " -h compile source keymap to header\n", + printf("usage: %s {-o } [-[l|r] | -[b|h|c|d ]]\n" + " -o, --output Change output file to output-file (default: " + "keymap.out|h).\n" + " -d, --dump Decompile key map to standard output (can be " + "redirected\n" + " via -o).\n" + " -l, --load Load key map. If no input-file is specified, it " + "will be\n" + " read from standard input.\n" + " -s, --load-source Load source key map from standard input when no\n" + " input-file is specified.\n" + " -r, --restore Restore system default key map.\n" + " -c, --compile Compile source keymap to binary.\n" + " -h, --header Translate source keymap to C++ header.\n", sProgramName); } -static const char * +static const char* keymap_error(status_t status) { if (status == KEYMAP_ERROR_UNKNOWN_VERSION) @@ -49,15 +56,24 @@ keymap_error(status_t status) static void -load_keymap_source(Keymap& keymap, const char* name) +load_keymap(Keymap& keymap, const char* name, bool source) { - entry_ref ref; - get_ref_for_path(name, &ref); + status_t status; + if (source) { + if (name != NULL) + status = keymap.LoadSource(name); + else + status = keymap.LoadSource(stdin); + } else { + if (name != NULL) + status = keymap.Load(name); + else + status = keymap.Load(stdin); + } - status_t status = keymap.LoadSourceFromRef(ref); if (status != B_OK) { - fprintf(stderr, "%s: error when loading the keymap: %s\n", - sProgramName, keymap_error(status)); + fprintf(stderr, "%s: error when loading the keymap: %s\n", sProgramName, + keymap_error(status)); exit(1); } } @@ -66,81 +82,152 @@ load_keymap_source(Keymap& keymap, const char* name) int main(int argc, char **argv) { - char operation = ' '; - entry_ref outputRef; - get_ref_for_path("keymap.out", &outputRef); + const char* output = NULL; + const char* input = NULL; + enum { + kUnspecified, + kLoadBinary, + kLoadText, + kSaveText, + kRestore, + kCompile, + kSaveHeader, + } mode = kUnspecified; - for (int i = 1; i < argc; i++) { - if (strncmp(argv[i], "-", 1) == 0) { - if (strlen(argv[i]) > 1) - operation = argv[i][1]; - else + static struct option const kLongOptions[] = { + {"output", required_argument, 0, 'o'}, + {"dump", optional_argument, 0, 'd'}, + {"load", optional_argument, 0, 'l'}, + {"load-source", optional_argument, 0, 's'}, + {"restore", no_argument, 0, 'r'}, + {"compile", optional_argument, 0, 'c'}, + {"header", optional_argument, 0, 'h'}, + {"help", no_argument, 0, 'H'}, + {NULL} + }; + + int c; + while ((c = getopt_long(argc, argv, "o:dblsrchH", kLongOptions, + NULL)) != -1) { + switch (c) { + case 0: + break; + case 'o': + output = optarg; + break; + case 'd': + mode = kSaveText; + input = optarg; + break; + case 'l': + case 'b': + mode = kLoadBinary; + input = optarg; + break; + case 's': + mode = kLoadText; + input = optarg; + break; + case 'r': + mode = kRestore; + break; + case 'c': + mode = kCompile; + input = optarg; + break; + case 'h': + mode = kSaveHeader; + input = optarg; break; - if (operation == 'd') { - Keymap keymap; - if (keymap.LoadCurrent() != B_OK) { - fprintf(stderr, "%s: error while getting current keymap!\n", sProgramName); - return 1; - } - keymap.Dump(); - return 0; - } else if (operation == 'r') { - Keymap keymap; - keymap.RestoreSystemDefault(); - printf("System default key map restored.\n"); - return 0; - } else if (operation == 'l') { - Keymap keymap; - status_t status = keymap.LoadSource(stdin); - if (status != B_OK) { - fprintf(stderr, "%s: error when loading the keymap: %s\n", - sProgramName, keymap_error(status)); - return 1; - } - keymap.SaveAsCurrent(); - printf("Key map loaded.\n"); - return 0; - } - } else { - // TODO: the actual action should be issued *AFTER* the command line - // has been parsed, not mixed in. - if (operation == 'o') { - get_ref_for_path(argv[i], &outputRef); - } else if (operation == 'c') { - Keymap keymap; - load_keymap_source(keymap, argv[i]); - - status_t status = keymap.Save(outputRef); - if (status < B_OK) { - fprintf(stderr, "%s: error saving \"%s\": %s\n", sProgramName, - argv[i], strerror(status)); - return 1; - } - return 0; - } else if (operation == 'h') { - Keymap keymap; - load_keymap_source(keymap, argv[i]); - keymap.SaveAsHeader(outputRef, argv[i]); - return 0; - } else if (operation == 'b') { - entry_ref ref; - get_ref_for_path(argv[i], &ref); - Keymap keymap; - status_t status = keymap.Load(ref); - if (status != B_OK) { - fprintf(stderr, "%s: error when loading the keymap: %s\n", - sProgramName, keymap_error(status)); - return 1; - } - keymap.SaveAsCurrent(); - printf("Key map loaded.\n"); - return 0; - } else + case 'H': + default: + usage(); break; } } - usage(); - return 1; + if (argc > optind && input == NULL) + input = argv[optind]; + + Keymap keymap; + + switch (mode) { + case kUnspecified: + usage(); + break; + + case kLoadBinary: + case kLoadText: + { + load_keymap(keymap, input, mode == kLoadText); + + status_t status = keymap.SaveAsCurrent(); + if (status != B_OK) { + fprintf(stderr, "%s: error when saving as current: %s", + sProgramName, strerror(status)); + return 1; + } + + printf("Key map loaded.\n"); + break; + } + + case kSaveText: + { + if (input == NULL) { + status_t status = keymap.LoadCurrent(); + if (status != B_OK) { + fprintf(stderr, "%s: error while getting keymap: %s!\n", + sProgramName, keymap_error(status)); + return 1; + } + } else + load_keymap(keymap, input, false); + + if (output != NULL) + keymap.SaveAsSource(output); + else + keymap.SaveAsSource(stdout); + break; + } + + case kRestore: + keymap.RestoreSystemDefault(); + break; + + case kCompile: + { + load_keymap(keymap, input, true); + + if (output == NULL) + output = "keymap.out"; + + status_t status = keymap.Save(output); + if (status != B_OK) { + fprintf(stderr, "%s: error saving \"%s\": %s\n", sProgramName, + output, strerror(status)); + return 1; + } + break; + } + + case kSaveHeader: + { + load_keymap(keymap, input, true); + + if (output == NULL) + output = "keymap.h"; + + status_t status = keymap.SaveAsCppHeader(output, input); + if (status != B_OK) { + fprintf(stderr, "%s: error saving \"%s\": %s\n", sProgramName, + output, strerror(status)); + return 1; + } + break; + } + } + + return 0; }