XKB: Text: Use keysym <-> string conversion from keysym.c
[platform/upstream/libxkbcommon.git] / src / text.c
1 /************************************************************
2  Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
3
4  Permission to use, copy, modify, and distribute this
5  software and its documentation for any purpose and without
6  fee is hereby granted, provided that the above copyright
7  notice appear in all copies and that both that copyright
8  notice and this permission notice appear in supporting
9  documentation, and that the name of Silicon Graphics not be
10  used in advertising or publicity pertaining to distribution
11  of the software without specific prior written permission.
12  Silicon Graphics makes no representation about the suitability
13  of this software for any purpose. It is provided "as is"
14  without any express or implied warranty.
15
16  SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17  SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18  AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19  GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20  DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21  DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22  OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23  THE USE OR PERFORMANCE OF THIS SOFTWARE.
24
25  ********************************************************/
26
27 #ifdef HAVE_CONFIG_H
28 #include <config.h>
29 #endif
30 #include "xkbmisc.h"
31 #include "X11/extensions/XKBcommon.h"
32 #include "XKBcommonint.h"
33 #include <X11/extensions/XKM.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include <ctype.h>
37
38 #define BUFFER_SIZE 512
39 static char textBuffer[BUFFER_SIZE];
40 static int tbNext = 0;
41
42 static char *
43 tbGetBuffer(unsigned size)
44 {
45     char *rtrn;
46
47     if (size >= BUFFER_SIZE)
48         return NULL;
49
50     if ((BUFFER_SIZE - tbNext) <= size)
51         tbNext = 0;
52
53     rtrn = &textBuffer[tbNext];
54     tbNext += size;
55
56     return rtrn;
57 }
58
59 static char *
60 XkbStringText(char *str)
61 {
62     char *buf, *in, *out;
63     int len;
64     Bool ok;
65
66     if (!str) {
67         buf = tbGetBuffer(2);
68         buf[0] = '\0';
69         return buf;
70     }
71
72     /* Find if there are any non-printable characters */
73     for (ok = True, len = 0, in = str; *in != '\0'; in++, len++) {
74         if (isprint(*in))
75             continue;
76
77         ok = False;
78         switch (*in) {
79         case '\n': case '\t': case '\v':
80         case '\b': case '\r': case '\f':
81             len++;
82             break;
83         default:
84             /* octal: \0ooo */
85             len += 4;
86             break;
87         }
88     }
89
90     if (ok)
91         return str;
92
93     /* Cleanup non-printable characters */
94     buf = tbGetBuffer(len + 1);
95     for (in = str, out = buf; *in != '\0'; in++) {
96         if (isprint(*in)) {
97             *out++ = *in;
98             continue;
99         }
100
101         *out++ = '\\';
102         switch (*in) {
103         case '\n':
104             *out++ = 'n';
105             break;
106         case '\t':
107             *out++ = 't';
108             break;
109         case '\v':
110             *out++ = 'v';
111             break;
112         case '\b':
113             *out++ = 'b';
114             break;
115         case '\r':
116             *out++ = 'r';
117             break;
118         case '\f':
119             *out++ = 'f';
120             break;
121         default:
122             *out++ = '0';
123             snprintf(out, 3, "%o", *in);
124             while (*out != '\0')
125                 out++;
126         }
127     }
128
129     *out++ = '\0';
130     return buf;
131 }
132
133 char *
134 XkbcAtomText(Atom atm)
135 {
136     char *tmp, *rtrn;
137     int len;
138
139     tmp = XkbcAtomGetString(atm);
140
141     if (!tmp)
142         return "";
143
144     len = strlen(tmp) + 1;
145     if (len >= BUFFER_SIZE)
146         len = BUFFER_SIZE - 2;
147
148     rtrn = tbGetBuffer(len);
149     strncpy(rtrn, tmp, len);
150     rtrn[len] = '\0';
151
152     _XkbFree(tmp);
153
154     return XkbStringText(rtrn);
155 }
156
157 char *
158 XkbcVModIndexText(XkbcDescPtr xkb, unsigned ndx)
159 {
160     int len;
161     Atom *vmodNames;
162     char *rtrn, *tmp = NULL;
163
164     if (xkb && xkb->names)
165         vmodNames = xkb->names->vmods;
166     else
167         vmodNames = NULL;
168
169     if (ndx >= XkbNumVirtualMods)
170          tmp = strdup("illegal");
171     else if (vmodNames && (vmodNames[ndx] != None))
172          tmp = XkbcAtomGetString(vmodNames[ndx]);
173
174     if (!tmp) {
175         tmp = _XkbAlloc(20 * sizeof(char));
176         snprintf(tmp, 20, "%d", ndx);
177     }
178
179     len = strlen(tmp) + 1;
180     if (len >= BUFFER_SIZE)
181         len = BUFFER_SIZE - 1;
182
183     rtrn = tbGetBuffer(len);
184     strncpy(rtrn, tmp, len);
185
186     _XkbFree(tmp);
187
188     return rtrn;
189 }
190
191 char *
192 XkbcVModMaskText(XkbcDescPtr xkb, unsigned modMask, unsigned mask)
193 {
194     int i, bit, len, rem;
195     char *mm = NULL, *rtrn, *str;
196     char buf[BUFFER_SIZE];
197
198     if ((modMask == 0) && (mask == 0))
199         return "none";
200
201     if (modMask != 0)
202         mm = XkbcModMaskText(modMask, False);
203
204     str = buf;
205     buf[0]= '\0';
206     rem = BUFFER_SIZE;
207
208     if (mask) {
209         for (i = 0, bit = 1; i < XkbNumVirtualMods && rem > 1; i++, bit <<= 1)
210         {
211             if (!(mask & bit))
212                 continue;
213
214             len = snprintf(str, rem, "%s%s",
215                            (str != buf) ? "+" : "",
216                            XkbcVModIndexText(xkb, i));
217             rem -= len;
218             str += len;
219         }
220
221         str = buf;
222     }
223     else
224         str = NULL;
225
226     len = ((str) ? strlen(str) : 0) + ((mm) ? strlen(mm) : 0) +
227           ((str && mm) ? 1 : 0);
228     if (len >= BUFFER_SIZE)
229         len = BUFFER_SIZE - 1;
230
231     rtrn = tbGetBuffer(len + 1);
232     rtrn[0] = '\0';
233
234     snprintf(rtrn, len + 1, "%s%s%s", (mm) ? mm : "",
235              (mm && str) ? "+" : "", (str) ? str : "");
236
237     return rtrn;
238 }
239
240 static char *modNames[XkbNumModifiers] = {
241     "Shift",
242     "Lock",
243     "Control",
244     "Mod1",
245     "Mod2",
246     "Mod3",
247     "Mod4",
248     "Mod5"
249 };
250
251 char *
252 XkbcModIndexText(unsigned ndx)
253 {
254     char *buf;
255
256     if (ndx < XkbNumModifiers)
257         return modNames[ndx];
258     else if (ndx == XkbNoModifier)
259         return "none";
260
261     buf = tbGetBuffer(32);
262     snprintf(buf, 32, "ILLEGAL_%02x", ndx);
263
264     return buf;
265 }
266
267 char *
268 XkbcModMaskText(unsigned mask, Bool cFormat)
269 {
270     int i, rem, bit;
271     char *str, *buf;
272
273     if ((mask & 0xff) == 0xff)
274         return (cFormat ? "0xff" : "all");
275
276     if ((mask & 0xff) == 0)
277         return (cFormat ? "0" : "none");
278
279     rem = 64;
280     buf = tbGetBuffer(rem);
281     str = buf;
282     buf[0] = '\0';
283     for (i = 0, bit = 1; i < XkbNumModifiers && rem > 1; i++, bit <<= 1) {
284         int len;
285
286         if (!(mask & bit))
287             continue;
288
289         len = snprintf(str, rem, "%s%s%s",
290                        (str != buf) ? (cFormat ? "|" : "+") : "",
291                        modNames[i],
292                        cFormat ? "Mask" : "");
293         rem -= len;
294         str += len;
295     }
296
297     return buf;
298 }
299
300 char *
301 XkbcConfigText(unsigned config)
302 {
303     switch (config) {
304     case XkmSemanticsFile:
305         return "Semantics";
306     case XkmLayoutFile:
307         return "Layout";
308     case XkmKeymapFile:
309         return "Keymap";
310     case XkmGeometryFile:
311     case XkmGeometryIndex:
312         return "Geometry";
313     case XkmTypesIndex:
314         return "Types";
315     case XkmCompatMapIndex:
316         return "CompatMap";
317     case XkmSymbolsIndex:
318         return "Symbols";
319     case XkmIndicatorsIndex:
320         return "Indicators";
321     case XkmKeyNamesIndex:
322         return "KeyNames";
323     case XkmVirtualModsIndex:
324         return "VirtualMods";
325     default:
326         return "unknown";
327     }
328 }
329
330 char *
331 XkbcGeomFPText(int val)
332 {
333     char *buf;
334     int whole, frac;
335
336     buf = tbGetBuffer(12);
337     whole = val / XkbGeomPtsPerMM;
338     frac = val % XkbGeomPtsPerMM;
339
340     if (frac != 0)
341         snprintf(buf, 12, "%d.%d", whole, frac);
342     else
343         snprintf(buf, 12, "%d", whole);
344
345     return buf;
346 }
347
348 static char *actionTypeNames[XkbSA_NumActions]= {
349     "NoAction",         /* XkbSA_NoAction */
350     "SetMods",          /* XkbSA_SetMods */
351     "LatchMods",        /* XkbSA_LatchMods */
352     "LockMods",         /* XkbSA_LockMods */
353     "SetGroup",         /* XkbSA_SetGroup */
354     "LatchGroup",       /* XkbSA_LatchGroup */
355     "LockGroup",        /* XkbSA_LockGroup */
356     "MovePtr",          /* XkbSA_MovePtr */
357     "PtrBtn",           /* XkbSA_PtrBtn */
358     "LockPtrBtn",       /* XkbSA_LockPtrBtn */
359     "SetPtrDflt",       /* XkbSA_SetPtrDflt */
360     "ISOLock",          /* XkbSA_ISOLock */
361     "Terminate",        /* XkbSA_Terminate */
362     "SwitchScreen",     /* XkbSA_SwitchScreen */
363     "SetControls",      /* XkbSA_SetControls */
364     "LockControls",     /* XkbSA_LockControls */
365     "ActionMessage",    /* XkbSA_ActionMessage */
366     "RedirectKey",      /* XkbSA_RedirectKey */
367     "DeviceBtn",        /* XkbSA_DeviceBtn */
368     "LockDeviceBtn",    /* XkbSA_LockDeviceBtn */
369     "DeviceValuator"    /* XkbSA_DeviceValuator */
370 };
371
372 char *
373 XkbcActionTypeText(unsigned type)
374 {
375     if (type <= XkbSA_LastAction)
376         return actionTypeNames[type];
377     return "Private";
378 }
379
380 char *
381 XkbcKeysymText(KeySym sym)
382 {
383     return XkbcKeysymToString(sym);
384 }
385
386 char *
387 XkbcKeyNameText(char *name)
388 {
389     char *buf;
390     int len;
391
392     buf = tbGetBuffer(7);
393     buf[0] = '<';
394     strncpy(&buf[1], name, 4);
395     buf[5] = '\0';
396     len = strlen(buf);
397     buf[len++] = '>';
398     buf[len] = '\0';
399
400     return buf;
401 }
402
403 static char *siMatchText[5] = {
404     "NoneOf",       /* XkbSI_NoneOf */
405     "AnyOfOrNone",  /* XkbSI_AnyOfOrNone */
406     "AnyOf",        /* XkbSI_AnyOf */
407     "AllOf",        /* XkbSI_AllOf */
408     "Exactly"       /* XkbSI_Exactly */
409 };
410
411 char *
412 XkbcSIMatchText(unsigned type)
413 {
414     char *buf;
415
416     switch (type & XkbSI_OpMask) {
417     case XkbSI_NoneOf:
418         return siMatchText[0];
419     case XkbSI_AnyOfOrNone:
420         return siMatchText[1];
421     case XkbSI_AnyOf:
422         return siMatchText[2];
423     case XkbSI_AllOf:
424         return siMatchText[3];
425     case XkbSI_Exactly:
426         return siMatchText[4];
427     default:
428         buf = tbGetBuffer(40);
429         snprintf(buf, 40, "0x%x", type & XkbSI_OpMask);
430         return buf;
431     }
432 }