1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25: static int get_keysym(const char *name)
26: {
27: name2keysym_t *p;
28: for(p = name2keysym; p->name != NULL; p++) {
29: if (!strcmp(p->name, name))
30: return p->keysym;
31: }
32: return 0;
33: }
34:
35: struct key_range {
36: int start;
37: int end;
38: struct key_range *next;
39: };
40:
41: #define MAX_NORMAL_KEYCODE 512
42: #define MAX_EXTRA_COUNT 256
43: typedef struct {
44: uint16_t keysym2keycode[MAX_NORMAL_KEYCODE];
45: struct {
46: int keysym;
47: uint16_t keycode;
48: } keysym2keycode_extra[MAX_EXTRA_COUNT];
49: int extra_count;
50: struct key_range *keypad_range;
51: struct key_range *numlock_range;
52: } kbd_layout_t;
53:
54: static void add_to_key_range(struct key_range **krp, int code) {
55: struct key_range *kr;
56: for (kr = *krp; kr; kr = kr->next) {
57: if (code >= kr->start && code <= kr->end)
58: break;
59: if (code == kr->start - 1) {
60: kr->start--;
61: break;
62: }
63: if (code == kr->end + 1) {
64: kr->end++;
65: break;
66: }
67: }
68: if (kr == NULL) {
69: kr = qemu_mallocz(sizeof(*kr));
70: if (kr) {
71: kr->start = kr->end = code;
72: kr->next = *krp;
73: *krp = kr;
74: }
75: }
76: }
77:
78: static kbd_layout_t *parse_keyboard_layout(const char *language,
79: kbd_layout_t * k)
80: {
81: FILE *f;
82: char file_name[1024];
83: char line[1024];
84: int len;
85:
86: snprintf(file_name, sizeof(file_name),
87: "%s/keymaps/%s", bios_dir, language);
88:
89: if (!k)
90: k = qemu_mallocz(sizeof(kbd_layout_t));
91: if (!k)
92: return 0;
93: if (!(f = fopen(file_name, "r"))) {
94: fprintf(stderr,
95: "Could not read keymap file: '%s'\n", file_name);
96: return 0;
97: }
98: for(;;) {
99: if (fgets(line, 1024, f) == NULL)
100: break;
101: len = strlen(line);
102: if (len > 0 && line[len - 1] == '\n')
103: line[len - 1] = '\0';
104: if (line[0] == '#')
105: continue;
106: if (!strncmp(line, "map ", 4))
107: continue;
108: if (!strncmp(line, "include ", 8)) {
109: parse_keyboard_layout(line + 8, k);
110: } else {
111: char *end_of_keysym = line;
112: while (*end_of_keysym != 0 && *end_of_keysym != ' ')
113: end_of_keysym++;
114: if (*end_of_keysym) {
115: int keysym;
116: *end_of_keysym = 0;
117: keysym = get_keysym(line);
118: if (keysym == 0) {
119:
120: } else {
121: const char *rest = end_of_keysym + 1;
122: char *rest2;
123: int keycode = strtol(rest, &rest2, 0);
124:
125: if (rest && strstr(rest, "numlock")) {
126: add_to_key_range(&k->keypad_range, keycode);
127: add_to_key_range(&k->numlock_range, keysym);
128:
129: }
130:
131:
132:
133: if (keysym < MAX_NORMAL_KEYCODE) {
134:
135: k->keysym2keycode[keysym] = keycode;
136: } else {
137: if (k->extra_count >= MAX_EXTRA_COUNT) {
138: fprintf(stderr,
139: "Warning: Could not assign keysym %s (0x%x) because of memory constraints.\n",
140: line, keysym);
141: } else {
142: #if 0
143: fprintf(stderr, "Setting %d: %d,%d\n",
144: k->extra_count, keysym, keycode);
145: #endif
146: k->keysym2keycode_extra[k->extra_count].
147: keysym = keysym;
148: k->keysym2keycode_extra[k->extra_count].
149: keycode = keycode;
150: k->extra_count++;
151: }
152: }
153: }
154: }
155: }
156: }
157: fclose(f);
158: return k;
159: }
160:
161: static void *init_keyboard_layout(const char *language)
162: {
163: return parse_keyboard_layout(language, 0);
164: }
165:
166: static int keysym2scancode(void *kbd_layout, int keysym)
167: {
168: kbd_layout_t *k = kbd_layout;
169: if (keysym < MAX_NORMAL_KEYCODE) {
170: if (k->keysym2keycode[keysym] == 0)
171: fprintf(stderr, "Warning: no scancode found for keysym %d\n",
172: keysym);
173: return k->keysym2keycode[keysym];
174: } else {
175: int i;
176: #ifdef XK_ISO_Left_Tab
177: if (keysym == XK_ISO_Left_Tab)
178: keysym = XK_Tab;
179: #endif
180: for (i = 0; i < k->extra_count; i++)
181: if (k->keysym2keycode_extra[i].keysym == keysym)
182: return k->keysym2keycode_extra[i].keycode;
183: }
184: return 0;
185: }
186:
187: static inline int keycode_is_keypad(void *kbd_layout, int keycode)
188: {
189: kbd_layout_t *k = kbd_layout;
190: struct key_range *kr;
191:
192: for (kr = k->keypad_range; kr; kr = kr->next)
193: if (keycode >= kr->start && keycode <= kr->end)
194: return 1;
195: return 0;
196: }
197:
198: static inline int keysym_is_numlock(void *kbd_layout, int keysym)
199: {
200: kbd_layout_t *k = kbd_layout;
201: struct key_range *kr;
202:
203: for (kr = k->numlock_range; kr; kr = kr->next)
204: if (keysym >= kr->start && keysym <= kr->end)
205: return 1;
206: return 0;
207: }