Add XkbModIndexText replacement
[profile/ivi/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 "X11/extensions/XKBcommon.h"
31 #include "XKBcommonint.h"
32 #include <X11/extensions/XKM.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <ctype.h>
36
37 #define BUFFER_SIZE 512
38 static char textBuffer[BUFFER_SIZE];
39 static int tbNext = 0;
40
41 static char *
42 tbGetBuffer(unsigned size)
43 {
44     char *rtrn;
45
46     if (size >= BUFFER_SIZE)
47         return NULL;
48
49     if ((BUFFER_SIZE - tbNext) <= size)
50         tbNext = 0;
51
52     rtrn = &textBuffer[tbNext];
53     tbNext += size;
54
55     return rtrn;
56 }
57
58 static char *
59 XkbStringText(char *str)
60 {
61     char *buf, *in, *out;
62     int len;
63     Bool ok;
64
65     if (!str) {
66         buf = tbGetBuffer(2);
67         buf[0] = '\0';
68         return buf;
69     }
70
71     /* Find if there are any non-printable characters */
72     for (ok = True, len = 0, in = str; *in != '\0'; in++, len++) {
73         if (isprint(*in))
74             continue;
75
76         ok = False;
77         switch (*in) {
78         case '\n': case '\t': case '\v':
79         case '\b': case '\r': case '\f':
80             len++;
81             break;
82         default:
83             /* octal: \0ooo */
84             len += 4;
85             break;
86         }
87     }
88
89     if (ok)
90         return str;
91
92     /* Cleanup non-printable characters */
93     buf = tbGetBuffer(len + 1);
94     for (in = str, out = buf; *in != '\0'; in++) {
95         if (isprint(*in)) {
96             *out++ = *in;
97             continue;
98         }
99
100         *out++ = '\\';
101         switch (*in) {
102         case '\n':
103             *out++ = 'n';
104             break;
105         case '\t':
106             *out++ = 't';
107             break;
108         case '\v':
109             *out++ = 'v';
110             break;
111         case '\b':
112             *out++ = 'b';
113             break;
114         case '\r':
115             *out++ = 'r';
116             break;
117         case '\f':
118             *out++ = 'f';
119             break;
120         default:
121             *out++ = '0';
122             snprintf(out, 3, "%o", *in);
123             while (*out != '\0')
124                 out++;
125         }
126     }
127
128     *out++ = '\0';
129     return buf;
130 }
131
132 char *
133 XkbcAtomText(Atom atm)
134 {
135     char *tmp, *rtrn;
136     int len;
137
138     tmp = XkbcAtomGetString(atm);
139
140     if (!tmp)
141         return "";
142
143     len = strlen(tmp) + 1;
144     if (len >= BUFFER_SIZE)
145         len = BUFFER_SIZE - 2;
146
147     rtrn = tbGetBuffer(len);
148     strncpy(rtrn, tmp, len);
149     rtrn[len] = '\0';
150
151     _XkbFree(tmp);
152
153     return XkbStringText(rtrn);
154 }
155
156 char *
157 XkbcVModIndexText(XkbcDescPtr xkb, unsigned ndx)
158 {
159     int len;
160     Atom *vmodNames;
161     char *rtrn, *tmp = NULL;
162
163     if (xkb && xkb->names)
164         vmodNames = xkb->names->vmods;
165     else
166         vmodNames = NULL;
167
168     if (ndx >= XkbNumVirtualMods)
169          tmp = strdup("illegal");
170     else if (vmodNames && (vmodNames[ndx] != None))
171          tmp = XkbcAtomGetString(vmodNames[ndx]);
172
173     if (!tmp) {
174         tmp = _XkbAlloc(20 * sizeof(char));
175         snprintf(tmp, 20, "%d", ndx);
176     }
177
178     len = strlen(tmp) + 1;
179     if (len >= BUFFER_SIZE)
180         len = BUFFER_SIZE - 1;
181
182     rtrn = tbGetBuffer(len);
183     strncpy(rtrn, tmp, len);
184
185     _XkbFree(tmp);
186
187     return rtrn;
188 }
189
190 char *
191 XkbcVModMaskText(XkbcDescPtr xkb, unsigned modMask, unsigned mask)
192 {
193     int i, bit, len, rem;
194     char *mm = NULL, *rtrn, *str;
195     char buf[BUFFER_SIZE];
196
197     if ((modMask == 0) && (mask == 0))
198         return "none";
199
200     if (modMask != 0)
201         mm = XkbcModMaskText(modMask, False);
202
203     str = buf;
204     buf[0]= '\0';
205     rem = BUFFER_SIZE;
206
207     if (mask) {
208         for (i = 0, bit = 1; i < XkbNumVirtualMods && rem > 1; i++, bit <<= 1)
209         {
210             if (!(mask & bit))
211                 continue;
212
213             len = snprintf(str, rem, "%s%s",
214                            (str != buf) ? "+" : "",
215                            XkbcVModIndexText(xkb, i));
216             rem -= len;
217             str += len;
218         }
219
220         str = buf;
221     }
222     else
223         str = NULL;
224
225     len = ((str) ? strlen(str) : 0) + ((mm) ? strlen(mm) : 0) +
226           ((str && mm) ? 1 : 0);
227     if (len >= BUFFER_SIZE)
228         len = BUFFER_SIZE - 1;
229
230     rtrn = tbGetBuffer(len + 1);
231     rtrn[0] = '\0';
232
233     snprintf(rtrn, len + 1, "%s%s%s", (mm) ? mm : "",
234              (mm && str) ? "+" : "", (str) ? str : "");
235
236     return rtrn;
237 }
238
239 static char *modNames[XkbNumModifiers] = {
240     "Shift",
241     "Lock",
242     "Control",
243     "Mod1",
244     "Mod2",
245     "Mod3",
246     "Mod4",
247     "Mod5"
248 };
249
250 char *
251 XkbcModIndexText(unsigned ndx)
252 {
253     char *buf;
254
255     if (ndx < XkbNumModifiers)
256         return modNames[ndx];
257     else if (ndx == XkbNoModifier)
258         return "none";
259
260     buf = tbGetBuffer(32);
261     snprintf(buf, 32, "ILLEGAL_%02x", ndx);
262
263     return buf;
264 }
265
266 char *
267 XkbcModMaskText(unsigned mask, Bool cFormat)
268 {
269     int i, rem, bit;
270     char *str, *buf;
271
272     if ((mask & 0xff) == 0xff)
273         return (cFormat ? "0xff" : "all");
274
275     if ((mask & 0xff) == 0)
276         return (cFormat ? "0" : "none");
277
278     rem = 64;
279     buf = tbGetBuffer(rem);
280     str = buf;
281     buf[0] = '\0';
282     for (i = 0, bit = 1; i < XkbNumModifiers && rem > 1; i++, bit <<= 1) {
283         int len;
284
285         if (!(mask & bit))
286             continue;
287
288         len = snprintf(str, rem, "%s%s%s",
289                        (str != buf) ? (cFormat ? "|" : "+") : "",
290                        modNames[i],
291                        cFormat ? "Mask" : "");
292         rem -= len;
293         str += len;
294     }
295
296     return buf;
297 }
298
299 char *
300 XkbcConfigText(unsigned config)
301 {
302     switch (config) {
303     case XkmSemanticsFile:
304         return "Semantics";
305     case XkmLayoutFile:
306         return "Layout";
307     case XkmKeymapFile:
308         return "Keymap";
309     case XkmGeometryFile:
310     case XkmGeometryIndex:
311         return "Geometry";
312     case XkmTypesIndex:
313         return "Types";
314     case XkmCompatMapIndex:
315         return "CompatMap";
316     case XkmSymbolsIndex:
317         return "Symbols";
318     case XkmIndicatorsIndex:
319         return "Indicators";
320     case XkmKeyNamesIndex:
321         return "KeyNames";
322     case XkmVirtualModsIndex:
323         return "VirtualMods";
324     default:
325         return "unknown";
326     }
327 }
328
329 char *
330 XkbcGeomFPText(int val)
331 {
332     char *buf;
333     int whole, frac;
334
335     buf = tbGetBuffer(12);
336     whole = val / XkbGeomPtsPerMM;
337     frac = val % XkbGeomPtsPerMM;
338
339     if (frac != 0)
340         snprintf(buf, 12, "%d.%d", whole, frac);
341     else
342         snprintf(buf, 12, "%d", whole);
343
344     return buf;
345 }
346
347 static char *actionTypeNames[XkbSA_NumActions]= {
348     "NoAction",         /* XkbSA_NoAction */
349     "SetMods",          /* XkbSA_SetMods */
350     "LatchMods",        /* XkbSA_LatchMods */
351     "LockMods",         /* XkbSA_LockMods */
352     "SetGroup",         /* XkbSA_SetGroup */
353     "LatchGroup",       /* XkbSA_LatchGroup */
354     "LockGroup",        /* XkbSA_LockGroup */
355     "MovePtr",          /* XkbSA_MovePtr */
356     "PtrBtn",           /* XkbSA_PtrBtn */
357     "LockPtrBtn",       /* XkbSA_LockPtrBtn */
358     "SetPtrDflt",       /* XkbSA_SetPtrDflt */
359     "ISOLock",          /* XkbSA_ISOLock */
360     "Terminate",        /* XkbSA_Terminate */
361     "SwitchScreen",     /* XkbSA_SwitchScreen */
362     "SetControls",      /* XkbSA_SetControls */
363     "LockControls",     /* XkbSA_LockControls */
364     "ActionMessage",    /* XkbSA_ActionMessage */
365     "RedirectKey",      /* XkbSA_RedirectKey */
366     "DeviceBtn",        /* XkbSA_DeviceBtn */
367     "LockDeviceBtn",    /* XkbSA_LockDeviceBtn */
368     "DeviceValuator"    /* XkbSA_DeviceValuator */
369 };
370
371 char *
372 XkbcActionTypeText(unsigned type)
373 {
374     if (type <= XkbSA_LastAction)
375         return actionTypeNames[type];
376     return "Private";
377 }
378
379 char *
380 XkbcKeysymText(KeySym sym)
381 {
382     char *buf;
383
384     if (sym == NoSymbol)
385         return "NoSymbol";
386
387     if ((buf = XkbcKeysymToString(sym)))
388         return buf;
389
390     buf = tbGetBuffer(32);
391     snprintf(buf, 32, "0x%lx", (long)sym);
392     return buf;
393 }
394
395 char *
396 XkbcKeyNameText(char *name)
397 {
398     char *buf;
399     int len;
400
401     buf = tbGetBuffer(7);
402     buf[0] = '<';
403     strncpy(&buf[1], name, 4);
404     buf[5] = '\0';
405     len = strlen(buf);
406     buf[len++] = '>';
407     buf[len] = '\0';
408
409     return buf;
410 }
411
412 static char *siMatchText[5] = {
413     "NoneOf",       /* XkbSI_NoneOf */
414     "AnyOfOrNone",  /* XkbSI_AnyOfOrNone */
415     "AnyOf",        /* XkbSI_AnyOf */
416     "AllOf",        /* XkbSI_AllOf */
417     "Exactly"       /* XkbSI_Exactly */
418 };
419
420 char *
421 XkbcSIMatchText(unsigned type)
422 {
423     char *buf;
424
425     switch (type & XkbSI_OpMask) {
426     case XkbSI_NoneOf:
427         return siMatchText[0];
428     case XkbSI_AnyOfOrNone:
429         return siMatchText[1];
430     case XkbSI_AnyOf:
431         return siMatchText[2];
432     case XkbSI_AllOf:
433         return siMatchText[3];
434     case XkbSI_Exactly:
435         return siMatchText[4];
436     default:
437         buf = tbGetBuffer(40);
438         snprintf(buf, 40, "0x%x", type & XkbSI_OpMask);
439         return buf;
440     }
441 }