Rename LKFLAG_* on LK_FLAG_*
[platform/upstream/kbd.git] / src / libkeymap / kmap.c
1 #include <stdlib.h>
2 #include <string.h>
3
4 #include "nls.h"
5 #include "kbd.h"
6
7 #include "keymap.h"
8
9 #include "ksyms.h"
10 #include "modifiers.h"
11
12 int
13 lk_add_map(struct keymap *kmap, int i)
14 {
15         if (i < 0 || i >= MAX_NR_KEYMAPS) {
16                 ERR(kmap, _("lk_add_map called with bad index %d"), i);
17                 return -1;
18         }
19
20         if (kmap->defining[i])
21                 return 0;
22
23         kmap->defining[i] = i + 1;
24
25         if (kmap->max_keymap <= i)
26                 kmap->max_keymap = i + 1;
27
28         return 0;
29 }
30
31 int
32 lk_get_key(struct keymap *kmap, int k_table, int k_index)
33 {
34         if (k_index < 0 || k_index >= NR_KEYS) {
35                 ERR(kmap, _("lk_get_key called with bad index %d"), k_index);
36                 return -1;
37         }
38
39         if (k_table < 0 || k_table >= MAX_NR_KEYMAPS) {
40                 ERR(kmap, _("lk_get_key called with bad table %d"), k_table);
41                 return -1;
42         }
43
44         if (!(kmap->keymap_was_set[k_table]))
45                 return -1;
46
47         return (kmap->key_map[k_table])[k_index];
48 }
49
50 int
51 lk_del_key(struct keymap *kmap, int k_table, int k_index)
52 {
53         /* roughly: addkey(k_index, k_table, K_HOLE); */
54
55         if (k_index < 0 || k_index >= NR_KEYS) {
56                 ERR(kmap, _("lk_del_key called with bad index %d"), k_index);
57                 return -1;
58         }
59
60         if (k_table < 0 || k_table >= MAX_NR_KEYMAPS) {
61                 ERR(kmap, _("lk_del_key called with bad table %d"), k_table);
62                 return -1;
63         }
64
65         if (kmap->key_map[k_table])
66                 (kmap->key_map[k_table])[k_index] = K_HOLE;
67
68         if (kmap->keymap_was_set[k_table])
69                 (kmap->keymap_was_set[k_table])[k_index] = 0;
70
71         return 0;
72 }
73
74 int
75 lk_add_key(struct keymap *kmap, int k_table, int k_index, int keycode)
76 {
77         int i;
78
79         if (keycode == CODE_FOR_UNKNOWN_KSYM) {
80                 /* is safer not to be silent in this case, 
81                  * it can be caused by coding errors as well. */
82                 ERR(kmap, _("lk_add_key called with bad keycode %d"), keycode);
83                 return -1;
84         }
85
86         if (k_index < 0 || k_index >= NR_KEYS) {
87                 ERR(kmap, _("lk_add_key called with bad index %d"), k_index);
88                 return -1;
89         }
90
91         if (k_table < 0 || k_table >= MAX_NR_KEYMAPS) {
92                 ERR(kmap, _("lk_add_key called with bad table %d"), k_table);
93                 return -1;
94         }
95
96         if (!k_index && keycode == K_NOSUCHMAP)
97                 return 0;
98
99         if (!kmap->defining[k_table]) {
100                 if (kmap->keywords & LK_KEYWORD_KEYMAPS) {
101                         ERR(kmap, _("adding map %d violates explicit keymaps line"),
102                             k_table);
103                         return -1;
104                 }
105
106                 if (lk_add_map(kmap, k_table) < 0)
107                         return -1;
108         }
109
110         if (!kmap->key_map[k_table]) {
111                 kmap->key_map[k_table] = (u_short *)malloc(NR_KEYS * sizeof(u_short));
112
113                 if (!kmap->key_map[k_table]) {
114                         ERR(kmap, _("out of memory"));
115                         return -1;
116                 }
117
118                 for (i = 0; i < NR_KEYS; i++)
119                         (kmap->key_map[k_table])[i] = K_HOLE;
120         }
121
122         if (!kmap->keymap_was_set[k_table]) {
123                 kmap->keymap_was_set[k_table] = (char *)malloc(NR_KEYS);
124
125                 if (!kmap->key_map[k_table]) {
126                         ERR(kmap, _("out of memory"));
127                         return -1;
128                 }
129
130                 for (i = 0; i < NR_KEYS; i++)
131                         (kmap->keymap_was_set[k_table])[i] = 0;
132         }
133
134         if ((kmap->keywords & LK_KEYWORD_ALTISMETA) &&
135             keycode == K_HOLE
136             && (kmap->keymap_was_set[k_table])[k_index])
137                 return 0;
138
139         (kmap->key_map[k_table])[k_index] = keycode;
140         (kmap->keymap_was_set[k_table])[k_index] = 1;
141
142         if (kmap->keywords & LK_KEYWORD_ALTISMETA) {
143                 int alttable = k_table | M_ALT;
144                 int type = KTYP(keycode);
145                 int val = KVAL(keycode);
146
147                 if (alttable != k_table && kmap->defining[alttable] &&
148                     (!kmap->keymap_was_set[alttable] ||
149                      !(kmap->keymap_was_set[alttable])[k_index]) &&
150                     (type == KT_LATIN || type == KT_LETTER) && val < 128) {
151                         if (lk_add_key(kmap, alttable, k_index, K(KT_META, val)) < 0)
152                                 return -1;
153                 }
154         }
155         return 0;
156 }
157
158 int
159 lk_get_func(struct keymap *kmap, struct kbsentry *kbs)
160 {
161         int x = kbs->kb_func;
162
163         if (x >= MAX_NR_FUNC) {
164                 ERR(kmap, _("bad index %d"), x);
165                 return -1;
166         }
167
168         if(!(kmap->func_table[x])) {
169                 ERR(kmap, _("func %d not allocated"), x);
170                 return -1;
171         }
172
173         strncpy((char *)kbs->kb_string, kmap->func_table[x],
174                 sizeof(kbs->kb_string));
175         kbs->kb_string[sizeof(kbs->kb_string) - 1] = 0;
176
177         return 0;
178 }
179
180
181 int
182 lk_add_func(struct keymap *kmap, struct kbsentry kbs)
183 {
184         int x;
185
186         x = kbs.kb_func;
187
188         if (x >= MAX_NR_FUNC) {
189                 ERR(kmap, _("bad func %d"), kbs.kb_func);
190                 return -1;
191         }
192
193         if(kmap->func_table[x]) {
194                 free(kmap->func_table[x]);
195                 kmap->func_table[x] = NULL;
196         }
197
198         kmap->func_table[x] = strdup((char *)kbs.kb_string);
199
200         if (!kmap->func_table[x]) {
201                 ERR(kmap, _("out of memory"));
202                 return -1;
203         }
204
205         return 0;
206 }
207
208 int
209 lk_add_diacr(struct keymap *kmap, unsigned int diacr, unsigned int base, unsigned int res)
210 {
211         accent_entry *ptr;
212
213         if (kmap->accent_table_size == MAX_DIACR) {
214                 ERR(kmap, _("table overflow"));
215                 return -1;
216         }
217
218         ptr = &(kmap->accent_table[kmap->accent_table_size++]);
219         ptr->diacr  = diacr;
220         ptr->base   = base;
221         ptr->result = res;
222
223         return 0;
224 }
225
226 int
227 lk_add_compose(struct keymap *kmap,
228                unsigned int diacr,
229                unsigned int base,
230                unsigned int res)
231 {
232         int direction = TO_8BIT;
233
234 #ifdef KDSKBDIACRUC
235         if (kmap->flags & LK_FLAG_PREFER_UNICODE)
236                 direction = TO_UNICODE;
237 #endif
238         return lk_add_diacr(kmap,
239                 convert_code(kmap, diacr, direction),
240                 convert_code(kmap, base, direction),
241                 convert_code(kmap, res, direction)
242         );
243 }
244
245 static int
246 do_constant_key(struct keymap *kmap, int i, u_short key)
247 {
248         int typ, val, j;
249
250         typ = KTYP(key);
251         val = KVAL(key);
252
253         if ((typ == KT_LATIN || typ == KT_LETTER) &&
254             ((val >= 'a' && val <= 'z') || (val >= 'A' && val <= 'Z'))) {
255                 u_short defs[16];
256                 defs[0] = K(KT_LETTER, val);
257                 defs[1] = K(KT_LETTER, val ^ 32);
258                 defs[2] = defs[0];
259                 defs[3] = defs[1];
260
261                 for (j = 4; j < 8; j++)
262                         defs[j] = K(KT_LATIN, val & ~96);
263
264                 for (j = 8; j < 16; j++)
265                         defs[j] = K(KT_META, KVAL(defs[j - 8]));
266
267                 for (j = 0; j < kmap->max_keymap; j++) {
268                         if (!kmap->defining[j])
269                                 continue;
270
271                         if (j > 0 &&
272                             kmap->keymap_was_set[j] && (kmap->keymap_was_set[j])[i])
273                                 continue;
274
275                         if (lk_add_key(kmap, j, i, defs[j % 16]) < 0)
276                                 return -1;
277                 }
278
279         } else {
280                 /* do this also for keys like Escape,
281                    as promised in the man page */
282                 for (j = 1; j < kmap->max_keymap; j++) {
283                         if (!kmap->defining[j])
284                                 continue;
285
286                         if (kmap->keymap_was_set[j] && (kmap->keymap_was_set[j])[i])
287                                 continue;
288
289                         if (lk_add_key(kmap, j, i, key) < 0)
290                                 return -1;
291                 }
292         }
293         return 0;
294 }
295
296 int
297 lk_add_constants(struct keymap *kmap)
298 {
299         int i, r0 = 0;
300
301         if (kmap->keywords & LK_KEYWORD_KEYMAPS) {
302                 while (r0 < kmap->max_keymap && !kmap->defining[r0])
303                         r0++;
304         }
305
306         for (i = 0; i < NR_KEYS; i++) {
307                 u_short key;
308
309                 if (!kmap->key_is_constant[i])
310                         continue;
311
312                 if (!kmap->key_map[r0]) {
313                         ERR(kmap, _("impossible error in lk_add_constants"));
314                         return -1;
315                 }
316
317                 key = lk_get_key(kmap, r0, i);
318
319                 if (do_constant_key(kmap, i, key) < 0)
320                         return -1;
321         }
322         return 0;
323 }