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