Root/
Source at commit 2741 created 8 years 11 months ago. By ifabio, Add data for new logo and clut (grey) from macosxbootloader (Credits to Pike R. Alpha) | |
---|---|
1 | /*␊ |
2 | * cham-mklayout.c␊ |
3 | * Chameleon␊ |
4 | *␊ |
5 | * Created by JrCs on 30/08/11.␊ |
6 | * Copyright 2011. All rights reserved.␊ |
7 | *␊ |
8 | */␊ |
9 | ␊ |
10 | #include <stdio.h>␊ |
11 | #include <stdlib.h>␊ |
12 | #include <string.h>␊ |
13 | #include <getopt.h>␊ |
14 | #include <errno.h>␊ |
15 | #include "stdint.h"␊ |
16 | #include "term.h"␊ |
17 | #include "Keylayout.h"␊ |
18 | ␊ |
19 | #define PACKAGE_NAME␉"chameleon"␊ |
20 | #define PROGRAM_VERSION␉"1.0"␊ |
21 | ␊ |
22 | static struct keyboard_layout default_layout = {␊ |
23 | ␉.keyboard_map = {␊ |
24 | ␉␉/* 0x00 */ 0, KEY_ESC, '1', '2', '3', '4', '5', '6',␊ |
25 | ␉␉/* 0x08 */ '7', '8', '9', '0', '-', '=', KEY_BKSP, KEY_TAB,␊ |
26 | ␉␉/* 0x10 */ 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',␊ |
27 | ␉␉/* 0x18 */ 'o', 'p', '[', ']', KEY_ENTER, 0, 'a', 's',␊ |
28 | ␉␉/* 0x20 */ 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',␊ |
29 | ␉␉/* 0x28 */ '\'', '`', 0, '\\', 'z', 'x', 'c', 'v',␊ |
30 | ␉␉/* 0x30 */ 'b', 'n', 'm', ',', '.', '/', 0, 0␊ |
31 | ␉},␊ |
32 | ␉.keyboard_map_shift = {␊ |
33 | ␉␉/* 0x00 */ 0, KEY_ESC, '!', '@', '#', '$', '%', '^',␊ |
34 | ␉␉/* 0x08 */ '&', '*', '(', ')', '_', '+', KEY_BKSP, 0,␊ |
35 | ␉␉/* 0x10 */ 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',␊ |
36 | ␉␉/* 0x18 */ 'O', 'P', '{', '}', KEY_ENTER, 0, 'A', 'S',␊ |
37 | ␉␉/* 0x20 */ 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',␊ |
38 | ␉␉/* 0x28 */ '"', '~', 0, '|', 'Z', 'X', 'C', 'V',␊ |
39 | ␉␉/* 0x30 */ 'B', 'N', 'M', '<', '>', '?', 0, 0,␊ |
40 | ␉},␊ |
41 | ␉.keyboard_map_alt = {␊ |
42 | ␉␉/* 0x00 */ 0, KEY_NOECHO, 0, 0, 0, 0, 0, 0,␊ |
43 | ␉␉/* 0x08 */ 0, 0, 0, 0, 0, 0, KEY_NOECHO, KEY_NOECHO,␊ |
44 | ␉␉/* 0x10 */ 0, 0, 0, 0, 0, 0, 0, 0,␊ |
45 | ␉␉/* 0x18 */ 0, 0, KEY_NOECHO, KEY_NOECHO, KEY_NOECHO, KEY_NOECHO, 0, 0,␊ |
46 | ␉␉/* 0x20 */ 0, 0, 0, 0, 0, 0, 0, KEY_NOECHO,␊ |
47 | ␉␉/* 0x28 */ KEY_NOECHO, KEY_NOECHO, KEY_NOECHO, KEY_NOECHO, 0, 0, 0, 0,␊ |
48 | ␉␉/* 0x30 */ 0, 0, 0, KEY_NOECHO, KEY_NOECHO, KEY_NOECHO, KEY_NOECHO, KEY_NOECHO,␊ |
49 | ␉},␊ |
50 | };␊ |
51 | ␊ |
52 | const char* program_name;␊ |
53 | ␊ |
54 | static struct option options[] = {␊ |
55 | ␉{"input", required_argument, 0, 'i'},␊ |
56 | ␉{"output", required_argument, 0, 'o'},␊ |
57 | ␉{"keysyms", no_argument, 0, 'k'},␊ |
58 | ␉{"help", no_argument, 0, 'h'},␊ |
59 | ␉{"version", no_argument, 0, 'V'},␊ |
60 | ␉{0, 0, 0, 0}␊ |
61 | };␊ |
62 | ␊ |
63 | struct hash␊ |
64 | {␊ |
65 | const char *keysym;␊ |
66 | int code;␊ |
67 | };␊ |
68 | ␊ |
69 | static struct hash keysym_to_code[] = {␊ |
70 | ␉{"BackSpace",␉KEY_BKSP},␊ |
71 | ␉{"Tab",␉␉␉KEY_TAB},␊ |
72 | ␉{"Linefeed",␉0x000a},␊ |
73 | ␉{"Space",␉␉0x0020},␊ |
74 | ␉{"Exclam",␉␉0x0021},␊ |
75 | ␉{"QuoteDbl",␉0x0022},␊ |
76 | ␉{"NumberSign",␉0x0023},␊ |
77 | ␉{"Dollar",␉␉0x0024},␊ |
78 | ␉{"Percent",␉␉0x0025},␊ |
79 | ␉{"Ampersand",␉0x0026},␊ |
80 | ␉{"Apostrophe",␉0x0027},␊ |
81 | ␉{"Parenleft",␉0x0028},␊ |
82 | ␉{"Parenright",␉0x0029},␊ |
83 | ␉{"Asterisk",␉0x002a},␊ |
84 | ␉{"Plus",␉␉0x002b},␊ |
85 | ␉{"Comma",␉␉0x002c},␊ |
86 | ␉{"Minus",␉␉0x002d},␊ |
87 | ␉{"Period",␉␉0x002e},␊ |
88 | ␉{"Slash",␉␉0x002f},␊ |
89 | ␉{"Zero",␉␉0x0030},␊ |
90 | ␉{"One",␉␉␉0x0031},␊ |
91 | ␉{"Two",␉␉␉0x0032},␊ |
92 | ␉{"Three",␉␉0x0033},␊ |
93 | ␉{"Four",␉␉0x0034},␊ |
94 | ␉{"Five",␉␉0x0035},␊ |
95 | ␉{"Six",␉␉␉0x0036},␊ |
96 | ␉{"Seven",␉␉0x0037},␊ |
97 | ␉{"Eight",␉␉0x0038},␊ |
98 | ␉{"Nine",␉␉0x0039},␊ |
99 | ␉{"Colon",␉␉0x003a},␊ |
100 | ␉{"SemiColon",␉0x003b},␊ |
101 | ␉{"Less",␉␉0x003c},␊ |
102 | ␉{"Equal",␉␉0x003d},␊ |
103 | ␉{"Greater",␉␉0x003e},␊ |
104 | ␉{"Question",␉0x003f},␊ |
105 | ␉{"At",␉␉␉0x0040},␊ |
106 | ␉{"BracketLeft", 0x005b},␊ |
107 | ␉{"Backslash",␉0x005c},␊ |
108 | ␉{"BracketRight",0x005d},␊ |
109 | ␉{"AsciiCircum", 0x005e},␊ |
110 | ␉{"Underscore",␉0x005f},␊ |
111 | ␉{"Grave",␉␉0x0060},␊ |
112 | ␉{"BraceLeft",␉0x007b},␊ |
113 | ␉{"Bar",␉␉␉0x007c},␊ |
114 | ␉{"BraceRight",␉0x007d},␊ |
115 | ␉{"AsciiTilde",␉0x007e},␊ |
116 | ␉{"Enter",␉␉KEY_ENTER},␊ |
117 | ␉{"Escape",␉␉KEY_ESC},␊ |
118 | ␉{"PrintScreen",␉KEY_PRTSC},␊ |
119 | ␉{"Left",␉␉KEY_LEFT},␊ |
120 | ␉{"Right",␉␉KEY_RIGHT},␊ |
121 | ␉{"Up",␉␉␉KEY_UP},␊ |
122 | ␉{"Down",␉␉KEY_DOWN},␊ |
123 | ␉{"Home",␉␉KEY_HOME},␊ |
124 | ␉{"End",␉␉␉KEY_END},␊ |
125 | ␉{"Center",␉␉KEY_CENTER},␊ |
126 | ␉{"Insert",␉␉KEY_INS},␊ |
127 | ␉{"Delete",␉␉KEY_DEL},␊ |
128 | ␉{"PageUp",␉␉KEY_PGUP},␊ |
129 | ␉{"PageDown",␉KEY_PGDN},␊ |
130 | ␉{"F1",␉␉␉KEY_F1},␊ |
131 | ␉{"F2",␉␉␉KEY_F2},␊ |
132 | ␉{"F3",␉␉␉KEY_F3},␊ |
133 | ␉{"F4",␉␉␉KEY_F4},␊ |
134 | ␉{"F5",␉␉␉KEY_F5},␊ |
135 | ␉{"F6",␉␉␉KEY_F6},␊ |
136 | ␉{"F7",␉␉␉KEY_F7},␊ |
137 | ␉{"F8",␉␉␉KEY_F8},␊ |
138 | ␉{"F9",␉␉␉KEY_F9},␊ |
139 | ␉{"F10",␉␉␉KEY_F10},␊ |
140 | ␉{"F11",␉␉␉KEY_F11},␊ |
141 | ␉{"F12",␉␉␉KEY_F12},␊ |
142 | ␉{"VoidSymbol",␉KEY_NOECHO},␊ |
143 | ␉{NULL, 0}␊ |
144 | };␊ |
145 | ␊ |
146 | ␊ |
147 | static void usage (int status) {␊ |
148 | if (status)␊ |
149 | fprintf (stderr, "Try `%s --help' for more information.\n", program_name);␊ |
150 | else␊ |
151 | printf ("\␊ |
152 | Usage: %s [OPTIONS]\n\␊ |
153 | -i, --input␉␉set input filename.\n\␊ |
154 | -o, --output␉␉set output filename.\n\␊ |
155 | -k, --keysyms␉␉list recognized keysyms.\n\␊ |
156 | -h, --help␉␉display this message and exit.\n\␊ |
157 | -V, --version␉␉print version information and exit.\n\␊ |
158 | \n", program_name);␊ |
159 | ␊ |
160 | exit (status);␊ |
161 | }␊ |
162 | ␊ |
163 | static void list_keysyms (void) {␊ |
164 | ␉int i;␊ |
165 | ␉for (i = 0; keysym_to_code[i].keysym != NULL; i++) {␊ |
166 | ␉␉printf("0x%04x\t %s\n", keysym_to_code[i].code, keysym_to_code[i].keysym);␊ |
167 | ␉}␊ |
168 | }␊ |
169 | ␊ |
170 | static int hash_lookup (const char *keysym, unsigned int *code) {␊ |
171 | ␉int i;␊ |
172 | ␉for (i = 0; keysym_to_code[i].keysym != NULL; i++) {␊ |
173 | ␉␉if (strcasecmp (keysym, keysym_to_code[i].keysym) == 0) {␊ |
174 | ␉␉␉*code = keysym_to_code[i].code;␊ |
175 | ␉␉␉return 0;␊ |
176 | ␉␉}␊ |
177 | ␉}␊ |
178 | ␉return -1;␊ |
179 | }␊ |
180 | ␊ |
181 | static int parse_keysym(const char* str, unsigned int *code) {␊ |
182 | ␉// Single character␊ |
183 | ␉if (strlen(str) == 1) {␊ |
184 | ␉␉*code=(unsigned char)(str[0]);␊ |
185 | ␉␉if (*code > ASCII_KEY_MASK)␊ |
186 | ␉␉␉return -1;␊ |
187 | ␉␉return 0;␊ |
188 | ␉}␊ |
189 | ␊ |
190 | ␉// Hex character code␊ |
191 | ␉if (sscanf(str, "0x%x", code))␊ |
192 | ␉␉return 0;␊ |
193 | ␊ |
194 | ␉// Keysym␊ |
195 | ␉if (hash_lookup(str, code) == 0)␊ |
196 | ␉␉return 0;␊ |
197 | ␊ |
198 | ␉return -1;␊ |
199 | }␊ |
200 | ␊ |
201 | int parse_scancode(int linenum, char* code, unsigned int* scancode) {␊ |
202 | ␊ |
203 | ␉char* tmp;␊ |
204 | ␉errno = 0; // clear errno␊ |
205 | ␊ |
206 | ␉float parse_value = strtof(code, &tmp);␊ |
207 | ␉int rest = strlen(code) - ((void*) tmp - (void*)code);␊ |
208 | ␉if (rest != 0 || errno != 0) {␊ |
209 | ␉␉printf("Ignoring line %d: invalid scancode `%s'\n", linenum, code);␊ |
210 | ␉␉return -1;␊ |
211 | ␉}␊ |
212 | ␊ |
213 | ␉*scancode = parse_value;␊ |
214 | ␊ |
215 | ␉// Only the first scancodes can be translated␊ |
216 | ␉if (*scancode >= KEYBOARD_MAP_SIZE) {␊ |
217 | ␉␉printf("Ignoring line %d: invalid scancode 0x%02x. Scancode must be <= 0x%02x.\n", linenum, *scancode,␊ |
218 | ␉␉␉ KEYBOARD_MAP_SIZE);␊ |
219 | ␉␉return -1;␊ |
220 | ␉}␊ |
221 | ␉return 0;␊ |
222 | }␊ |
223 | ␊ |
224 | void assign_keycode(int linenum, unsigned int scancode, const char* arg, uint16_t* map) {␊ |
225 | ␉unsigned int value;␊ |
226 | ␉if (parse_keysym(arg, &value) == -1) {␊ |
227 | ␉␉printf("Warning line %d (keycode 0x%02x): invalid symbol %s (must be a true ascii character)\n",␊ |
228 | ␉␉␉ linenum, scancode, arg);␊ |
229 | ␉␉value = KEY_NOECHO; // VoidSymbol␊ |
230 | ␉}␊ |
231 | ␉map[scancode] = value;␊ |
232 | }␊ |
233 | ␊ |
234 | struct keyboard_layout* create_keylayout(FILE* in) {␊ |
235 | ␉char line[128], code[sizeof(line)];␊ |
236 | ␉char arg1[sizeof(line)], arg2[sizeof(line)], arg3[sizeof(line)],␊ |
237 | ␉␉ arg4[sizeof(line)];␊ |
238 | ␉int n, linenum = 0;␊ |
239 | ␉unsigned int scancode;␊ |
240 | ␊ |
241 | ␉struct keyboard_layout* new_layout= malloc(sizeof(*new_layout));␊ |
242 | ␉if (!new_layout)␊ |
243 | ␉␉return NULL;␊ |
244 | ␊ |
245 | ␉// Initialize new keybord layout␊ |
246 | ␉memcpy(new_layout, &default_layout, sizeof(*new_layout));␊ |
247 | ␊ |
248 | ␉while(fgets(line, sizeof(line), in)) {␊ |
249 | ␉␉linenum++;␊ |
250 | ␉␉n = sscanf (line, "keycode %s = %s %s %s %s", code, arg1, arg2, arg3, arg4);␊ |
251 | ␉␉if (n > 1) {␊ |
252 | ␉␉␉if (parse_scancode(linenum, code, &scancode) == -1)␊ |
253 | ␉␉␉␉continue;␊ |
254 | ␉␉␉if (n >= 2)␊ |
255 | ␉␉␉␉assign_keycode(linenum, scancode, arg1,␊ |
256 | ␉␉␉␉␉␉␉ new_layout->keyboard_map);␊ |
257 | ␉␉␉if (n >= 3)␊ |
258 | ␉␉␉␉assign_keycode(linenum, scancode, arg2,␊ |
259 | ␉␉␉␉␉␉␉ new_layout->keyboard_map_shift);␊ |
260 | ␉␉␉if (n >= 4)␊ |
261 | ␉␉␉␉assign_keycode(linenum, scancode, arg3,␊ |
262 | ␉␉␉␉␉␉␉ new_layout->keyboard_map_alt);␊ |
263 | ␉␉␉if (n >= 5)␊ |
264 | ␉␉␉␉assign_keycode(linenum, scancode, arg4,␊ |
265 | ␉␉␉␉␉␉␉ new_layout->keyboard_map_shift_alt);␊ |
266 | ␉␉} else if (sscanf (line, "shift keycode %s = %s", code, arg1) == 2) {␊ |
267 | ␉␉␉if (parse_scancode(linenum, code, &scancode) == -1)␊ |
268 | ␉␉␉␉continue;␊ |
269 | ␉␉␉assign_keycode(linenum, scancode, arg1,␊ |
270 | ␉␉␉␉␉␉ new_layout->keyboard_map_shift);␊ |
271 | ␉␉} else if (sscanf (line, "alt keycode %s = %s", code, arg1) == 2) {␊ |
272 | ␉␉␉if (parse_scancode(linenum, code, &scancode) == -1)␊ |
273 | ␉␉␉␉continue;␊ |
274 | ␉␉␉assign_keycode(linenum, scancode, arg1,␊ |
275 | ␉␉␉␉␉␉ new_layout->keyboard_map_alt);␊ |
276 | ␉␉} else if (sscanf (line, "shift alt keycode %s = %s", code, arg1) == 2) {␊ |
277 | ␉␉␉if (parse_scancode(linenum, code, &scancode) == -1)␊ |
278 | ␉␉␉␉continue;␊ |
279 | ␉␉␉assign_keycode(linenum, scancode, arg1,␊ |
280 | ␉␉␉␉␉␉ new_layout->keyboard_map_shift_alt);␊ |
281 | ␉␉}␊ |
282 | ␉}␊ |
283 | ␉return new_layout;␊ |
284 | }␊ |
285 | ␊ |
286 | void write_layout(struct keyboard_layout* layout, FILE* out) {␊ |
287 | ␉// Create the header␊ |
288 | ␉uint32_t version = KEYBOARD_LAYOUTS_VERSION;␊ |
289 | ␉fwrite(KEYBOARD_LAYOUTS_MAGIC, KEYBOARD_LAYOUTS_MAGIC_SIZE, 1, out);␊ |
290 | ␉fwrite(&version, 1, sizeof(version), out);␊ |
291 | ␉// Seek to start of layout␊ |
292 | ␉fseek(out, KEYBOARD_LAYOUTS_MAP_OFFSET, SEEK_SET);␊ |
293 | ␉// Write layout␊ |
294 | ␉fwrite(layout, sizeof(*layout), 1, out);␊ |
295 | }␊ |
296 | ␊ |
297 | void set_program_name(const char* arg) {␊ |
298 | ␉const char* last_slash;␊ |
299 | ␉last_slash = strrchr(arg, '/');␊ |
300 | ␉program_name = (last_slash != NULL) ? last_slash + 1 : arg;␊ |
301 | }␊ |
302 | ␊ |
303 | int main (int argc, char *argv[]) {␊ |
304 | ␉int ch;␊ |
305 | ␉char *infile_name = NULL;␊ |
306 | ␉char *outfile_name = NULL;␊ |
307 | ␉FILE *in, *out;␊ |
308 | ␊ |
309 | ␉set_program_name (argv[0]);␊ |
310 | ␊ |
311 | ␉/* Check for options. */␊ |
312 | ␉while ((ch = getopt_long (argc, argv, "i:o:hkV", options, 0)) != -1) {␊ |
313 | ␉␉switch (ch) {␊ |
314 | ␉␉␉case 'h':␉␊ |
315 | ␉␉␉␉usage (0);␊ |
316 | ␉␉␉␉break;␊ |
317 | ␉␉␉␉␊ |
318 | ␉␉␉case 'k':␊ |
319 | ␉␉␉␉list_keysyms();␊ |
320 | ␉␉␉␉exit(0);␊ |
321 | ␉␉␉␉break;␊ |
322 | ␊ |
323 | ␉␉␉case 'i':␊ |
324 | ␉␉␉␉infile_name = optarg;␊ |
325 | ␉␉␉␉break;␊ |
326 | ␊ |
327 | ␉␉␉case 'o':␊ |
328 | ␉␉␉␉outfile_name = optarg;␊ |
329 | ␉␉␉␉break;␊ |
330 | ␉␉␉␉␊ |
331 | ␉␉␉case 'V':␊ |
332 | ␉␉␉␉printf ("%s v%s (%s)\n", program_name, PROGRAM_VERSION, PACKAGE_NAME);␊ |
333 | ␉␉␉␉return 0;␊ |
334 | ␉␉␉␉␊ |
335 | ␉␉␉default:␊ |
336 | ␉␉␉␉usage (1);␊ |
337 | ␉␉␉␉break;␊ |
338 | ␉␉}␊ |
339 | ␉}␊ |
340 | ␉␊ |
341 | ␉if (infile_name == NULL) {␊ |
342 | ␉␉fprintf(stderr, "You must specify an input file\n");␊ |
343 | ␉␉usage(1);␊ |
344 | ␉}␊ |
345 | ␊ |
346 | ␉if (outfile_name == NULL) {␊ |
347 | ␉␉fprintf(stderr, "You must specify an output file\n");␊ |
348 | ␉␉usage(1);␊ |
349 | ␉}␊ |
350 | ␉␊ |
351 | ␉in = fopen (infile_name, "r");␊ |
352 | ␉if (!in) {␊ |
353 | ␉␉fprintf(stderr, "Couldn't open input file `%s': %s\n",␊ |
354 | ␉␉␉␉infile_name, strerror (errno));␊ |
355 | ␉␉exit(1);␊ |
356 | }␊ |
357 | ␊ |
358 | ␉out = fopen (outfile_name, "wb");␊ |
359 | ␉if (!out) {␊ |
360 | ␉␉fprintf(stderr, "Couldn't open output file `%s': %s\n",␊ |
361 | ␉␉␉␉outfile_name, strerror (errno));␊ |
362 | ␉␉exit(1);␊ |
363 | }␊ |
364 | ␊ |
365 | ␉struct keyboard_layout* new_layout = create_keylayout(in);␊ |
366 | ␉if (new_layout)␊ |
367 | ␉␉write_layout(new_layout, out);␊ |
368 | ␊ |
369 | fclose(out);␊ |
370 | ␉fclose(in);␊ |
371 | ␊ |
372 | ␉return 0;␊ |
373 | }␊ |
374 |