/* Copyright 1998 Acorn Computers Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <stdlib.h> #include <stdio.h> #include <string.h> #include "swis.h" #include "Unicode/iso10646.h" #include "unicdata.h" char keypad_codes[]={ 0x23, 0x24, 0x25, 0x37, 0x38, 0x39, 0x3A, 0x48, 0x49, 0x4A, 0x4B, 0x5A, 0x5B, 0x5C, 0x65, 0x66, 0x67, 0 }; int default_keypad[17][2] = { 0x2F, 0x2F, 0x2A, 0x2A, 0x23, 0x23, 0x1E, 0x37, 0x8F, 0x38, 0x9F, 0x39, 0x2D, 0x2D, 0x8C, 0x34, -1, 0x35, 0x8D, 0x36, 0x2B, 0x2B, 0x8B, 0x31, 0x8E, 0x32, 0x9E, 0x33, 0xCD, 0x30, 0x7F, 0x2E, 0x0D, 0x0D }; int our_keypad[17][2]; int is_keypad_key(int key) { return key != 0 && strchr(keypad_codes, key) != NULL; } const char *dead_latin1[] = { "GRAVE ACCENT", "ACUTE ACCENT", "CIRCUMFLEX ACCENT", "TILDE", "DIAERESIS", "RING ABOVE", "CEDILLA" }; const char *dead_latin2[] = { "OGONEK", "STROKE", "CARON", "ACUTE ACCENT", "CEDILLA", "DOT ABOVE", "CIRCUMFLEX ACCENT", "BREVE", "DIAERESIS", "DOUBLE ACUTE" }; const char *dead_latin3[] = { "STROKE", "CIRCUMFLEX ACCENT", "DOT ABOVE", "CEDILLA", "BREVE", "GRAVE ACCENT", "ACUTE ACCENT", "DIAERESIS", "TILDE" }; const char *dead_latin4[] = { "OGONEK", "CEDILLA", "TILDE", "CARON", "MACRON", "STROKE", "DIAERESIS", "RING ABOVE", "ACUTE ACCENT", "DOT ABOVE", "CIRCUMFLEX ACCENT" }; const char *dead_welsh[] = { "GRAVE ACCENT", "ACUTE ACCENT", "CIRCUMFLEX ACCENT", "TILDE", "DIAERESIS", "RING ABOVE", "CEDILLA" }; const char *dead_greek[] = { "GREEK TONOS", "GREEK DIALYTIKA", "GREEK DIALYTIKA TONOS" }; const int dead_alphabets[] = { 101, 102, 103, 104, 107, 110, 0 }; const char **dead_tables[] = { dead_latin1, dead_latin2, dead_latin3, dead_latin4, dead_greek, dead_welsh }; void error(const char *p) { fprintf(stderr, "%s\n", p); exit(1); } void *xmalloc(size_t s) { void *ret = malloc(s); if (!ret) error("Out of memory"); return ret; } char *read_string(FILE *f) { int type = fgetc(f); int len; char *ret; if (type != 0) error("Type mismatch"); len = fgetc(f); ret = xmalloc(len+1); ret[len] = 0; while (len > 0) ret[--len] = fgetc(f); return ret; } int read_int(FILE *f) { int type = fgetc(f); int ret; if (type != 0x40) error("Type mismatch"); ret = fgetc(f); ret = (ret << 8) + fgetc(f); ret = (ret << 8) + fgetc(f); ret = (ret << 8) + fgetc(f); return ret; } char *function_name(int code, int key, int pos) { char buffer[256]; const char *ctrlshift; static const char *ctrlshifttab[] = { "", "SHIFT-", "CTRL-", "CTRL-SHIFT-" }; ctrlshift = ctrlshifttab[pos & 3]; if (key==0x00 && code == 27) sprintf(buffer, "FUNCTION KEY %sESCAPE", ctrlshift); else if (key==0x1E && code == 8) sprintf(buffer, "FUNCTION KEY %sBACKSPACE", ctrlshift); else if ((key==0x20 || key == 0x37) && code == 30) sprintf(buffer, "FUNCTION KEY %sHOME", ctrlshift); else if ((key==0x47 || key == 0x67) && code == 13) sprintf(buffer, "FUNCTION KEY %sENTER", ctrlshift); else if (code < 32) sprintf(buffer, "FUNCTION KEY CTRL-%c", "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"[code]); else if (code == 0x7F) sprintf(buffer, "FUNCTION KEY DELETE"); else { int shift = code & 0x10; int ctrl = code & 0x20; const char *s; static const char *func[32] = { "PRINT", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "BREAK", "END", "LEFT", "RIGHT", "DOWN", "UP", "ACORN", "MENU", "WIDTH", "KANJI", "EISUU", "NO CONVERT", "CONVERT", "KANA", "ALL CANDIDATES", "KANJI NUMBER", "F10", "F11", "F12", "INSERT", "&1CE", "&1CF" }; code &= ~0x30; code -= 0x180; if (code >= 0x40) code -= 0x30; s = func[code]; if ((key == 0x21 || key == 0x39) && code == 0x0F || (key == 0x36 || key == 0x5C) && code == 0x0E) { shift ^= 0x10; s = code == 0x0E ? "PAGE DOWN" : "PAGE UP"; } sprintf(buffer, "FUNCTION KEY %s%s%s", ctrl ? "CTRL-" : "", shift ? "SHIFT-" : "", s); } return buffer; } int main(int argc, char **argv) { FILE *in, *out; char *cno, *alphabet; int lastkey, flags, i, j, n, alphabet_no, notclaimed, same; const UCS4 *alphabet_table; const char **dead_table; if (argc != 3) { fprintf(stderr, "Usage: keyconvert <in-file> <out-file>\n"); return 1; } load_unidata("UniData215"); in = fopen(argv[1], "r"); if (!in) { perror(argv[1]); exit(1); } out = fopen(argv[2], "w"); if (!out) { perror(argv[2]); exit(1); } cno = read_string(in); alphabet = read_string(in); lastkey = read_int(in); flags = read_int(in); _swix(OS_ServiceCall, _INR(1,3)|_OUT(1)|_OUT(4), 0x43, 1, alphabet, ¬claimed, &alphabet_no); if (notclaimed) error("Unknown alphabet"); _swix(OS_ServiceCall, _INR(1,3)|_OUT(1)|_OUT(4), 0x43, 8, alphabet_no, ¬claimed, &alphabet_table); if (notclaimed || !alphabet_table) error("Can't find table for alphabet"); dead_table = NULL; for (i=0; dead_alphabets[i]; i++) if (dead_alphabets[i] == alphabet_no) { dead_table = dead_tables[i]; break; } fprintf(out, "# Layout converted by keyconvert\n#\n"); fprintf(out, "# Default alphabet: %s\n", alphabet); fprintf(out, "# Extra key 1D %sfitted\n", flags & 2 ? "" : "not "); fprintf(out, "# Extra key 4D %sfitted\n", flags & 1 ? "" : "not "); fprintf(out, "# Extra key 6E %sfitted\n", flags & 8 ? "" : "not "); fprintf(out, "# Enter key in %s position\n", flags & 4 ? "USA" : "UK"); fprintf(out, "\n$Country %s\n", cno); fprintf(out, "\n$Layer 0\n\n"); for (i=0; i<=lastkey; i++) { int null = 1; for (j=0; j<8; j++) { int code = read_int(in); if (code != -1 || (i==0x01&&j==0x06) || (i==0x02&&j==0x06) || (i==0x0C&&j==0x06) || i==0x34) null = 0; } if (null) continue; if (i >= 0x6B) continue; /* Hard coded hack to strip extra keys from layouts */ fseek(in, -8*5L, SEEK_CUR); fprintf(out, "%02X\n", i); for (j=0; j<8; j++) { int code = read_int(in); const char *caps=""; if ((code &~ 0xFF) == 0x200) { static const char brack[8][2] = { "[", "]", "<", ">", "{", "}", "(", ")" }; code -= 0x200; caps = brack[j]; } if (i==0x01 && j == 6) { fprintf(out, "SPECIAL KEY DEFAULT KEYBOARD\n"); continue; } if (i==0x02 && j == 6) { fprintf(out, "SPECIAL KEY CONFIGURED KEYBOARD\n"); continue; } if (i==0x0C && j ==6) { fprintf(out, "SPECIAL KEY DIAL KEYBOARD\n"); continue; } if (i==0x34 && j < 4) { fprintf(out, "SPECIAL KEY DELETE\n"); continue; } if (code == -1) fprintf(out, "-\n"); else if (code < 32) fprintf(out, "%s\n", function_name(code, i, j)); else if (code == 127) fprintf(out, "FUNCTION KEY CTRL-?\n"); else if (code < 0x100) fprintf(out, "%s%s\n", caps, name_from_UCS(alphabet_table[code])); else if (code < 0x180) error("I don't grok codes from &100 to &17F"); else if (code < 0x200) fprintf(out, "%s\n", function_name(code, i, j)); else if (code >= 0x300 && code <= 0x3FF) { if (!dead_table) error("I don't know the dead keys for this alphabet"); fprintf(out, "DEAD KEY %s\n", dead_table[code-0x301]); } else error("Unknown code"); } } fprintf(out, "\n$EndLayer\n"); for (n=0,i=0; i<=lastkey; i++) { if (!is_keypad_key(i)) { read_int(in); read_int(in); continue; } our_keypad[n][0] = read_int(in); our_keypad[n][1] = read_int(in); n++; } same = 1; for (n=0; n<17; n++) { for (j=0; j<2; j++) { if (our_keypad[n][j] != default_keypad[n][j]) same = 0; } } if (!same) { int c0, c1; const char *s; fprintf(out, "\n$Keypad\n"); for (n = 0; n<17; n++) { int count; c0 = our_keypad[n][1]; c1 = our_keypad[n][0]; if (c0 >= 0x80 && c0 <= 0xFF) c0 += 0x100; if (c1 >= 0x80 && c1 <= 0xFF) c1 += 0x100; if (c0 == -1) s = "-"; else if (c0 < 32 || c0 == 0x7F || c0 >= 0x180) s = function_name(c0, keypad_codes[n], 0); else s = name_from_UCS(c0); fprintf(out, "%s%n", s, &count); if (c0 == c1) { fprintf(out, "\n"); } else { if (c1 == -1) s = "-"; else if (c1 < 32 || c1 == 0x7F || c1 >= 0x180) s = function_name(c1, keypad_codes[n], 0); else s = name_from_UCS(c1); fputc(';', out); while (count < 19) { fputc(' ', out); count++; } fprintf(out, "%s\n", s); } } fprintf(out, "$EndKeypad\n"); } return 0; }