Add VMod Text functions from xkbfile
[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 "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 XkbcModMaskText(unsigned mask, Bool cFormat)
252 {
253     int i, rem, bit;
254     char *str, *buf;
255
256     if ((mask & 0xff) == 0xff)
257         return (cFormat ? "0xff" : "all");
258
259     if ((mask & 0xff) == 0)
260         return (cFormat ? "0" : "none");
261
262     rem = 64;
263     buf = tbGetBuffer(rem);
264     str = buf;
265     buf[0] = '\0';
266     for (i = 0, bit = 1; i < XkbNumModifiers && rem > 1; i++, bit <<= 1) {
267         int len;
268
269         if (!(mask & bit))
270             continue;
271
272         len = snprintf(str, rem, "%s%s%s",
273                        (str != buf) ? (cFormat ? "|" : "+") : "",
274                        modNames[i],
275                        cFormat ? "Mask" : "");
276         rem -= len;
277         str += len;
278     }
279
280     return buf;
281 }
282
283 char *
284 XkbcConfigText(unsigned config)
285 {
286     switch (config) {
287     case XkmSemanticsFile:
288         return "Semantics";
289     case XkmLayoutFile:
290         return "Layout";
291     case XkmKeymapFile:
292         return "Keymap";
293     case XkmGeometryFile:
294     case XkmGeometryIndex:
295         return "Geometry";
296     case XkmTypesIndex:
297         return "Types";
298     case XkmCompatMapIndex:
299         return "CompatMap";
300     case XkmSymbolsIndex:
301         return "Symbols";
302     case XkmIndicatorsIndex:
303         return "Indicators";
304     case XkmKeyNamesIndex:
305         return "KeyNames";
306     case XkmVirtualModsIndex:
307         return "VirtualMods";
308     default:
309         return "unknown";
310     }
311 }
312
313 char *
314 XkbcGeomFPText(int val)
315 {
316     char *buf;
317     int whole, frac;
318
319     buf = tbGetBuffer(12);
320     whole = val / XkbGeomPtsPerMM;
321     frac = val % XkbGeomPtsPerMM;
322
323     if (frac != 0)
324         snprintf(buf, 12, "%d.%d", whole, frac);
325     else
326         snprintf(buf, 12, "%d", whole);
327
328     return buf;
329 }
330
331 static char *actionTypeNames[XkbSA_NumActions]= {
332     "NoAction",         /* XkbSA_NoAction */
333     "SetMods",          /* XkbSA_SetMods */
334     "LatchMods",        /* XkbSA_LatchMods */
335     "LockMods",         /* XkbSA_LockMods */
336     "SetGroup",         /* XkbSA_SetGroup */
337     "LatchGroup",       /* XkbSA_LatchGroup */
338     "LockGroup",        /* XkbSA_LockGroup */
339     "MovePtr",          /* XkbSA_MovePtr */
340     "PtrBtn",           /* XkbSA_PtrBtn */
341     "LockPtrBtn",       /* XkbSA_LockPtrBtn */
342     "SetPtrDflt",       /* XkbSA_SetPtrDflt */
343     "ISOLock",          /* XkbSA_ISOLock */
344     "Terminate",        /* XkbSA_Terminate */
345     "SwitchScreen",     /* XkbSA_SwitchScreen */
346     "SetControls",      /* XkbSA_SetControls */
347     "LockControls",     /* XkbSA_LockControls */
348     "ActionMessage",    /* XkbSA_ActionMessage */
349     "RedirectKey",      /* XkbSA_RedirectKey */
350     "DeviceBtn",        /* XkbSA_DeviceBtn */
351     "LockDeviceBtn",    /* XkbSA_LockDeviceBtn */
352     "DeviceValuator"    /* XkbSA_DeviceValuator */
353 };
354
355 char *
356 XkbcActionTypeText(unsigned type)
357 {
358     if (type <= XkbSA_LastAction)
359         return actionTypeNames[type];
360     return "Private";
361 }
362
363 char *
364 XkbcKeysymText(KeySym sym)
365 {
366     char *buf;
367
368     if (sym == NoSymbol)
369         return "NoSymbol";
370
371     if ((buf = XkbcKeysymToString(sym)))
372         return buf;
373
374     buf = tbGetBuffer(32);
375     snprintf(buf, 32, "0x%lx", (long)sym);
376     return buf;
377 }
378
379 char *
380 XkbcKeyNameText(char *name)
381 {
382     char *buf;
383     int len;
384
385     buf = tbGetBuffer(7);
386     buf[0] = '<';
387     strncpy(&buf[1], name, 4);
388     buf[5] = '\0';
389     len = strlen(buf);
390     buf[len++] = '>';
391     buf[len] = '\0';
392
393     return buf;
394 }
395
396 static char *siMatchText[5] = {
397     "NoneOf",       /* XkbSI_NoneOf */
398     "AnyOfOrNone",  /* XkbSI_AnyOfOrNone */
399     "AnyOf",        /* XkbSI_AnyOf */
400     "AllOf",        /* XkbSI_AllOf */
401     "Exactly"       /* XkbSI_Exactly */
402 };
403
404 char *
405 XkbcSIMatchText(unsigned type)
406 {
407     char *buf;
408
409     switch (type & XkbSI_OpMask) {
410     case XkbSI_NoneOf:
411         return siMatchText[0];
412     case XkbSI_AnyOfOrNone:
413         return siMatchText[1];
414     case XkbSI_AnyOf:
415         return siMatchText[2];
416     case XkbSI_AllOf:
417         return siMatchText[3];
418     case XkbSI_Exactly:
419         return siMatchText[4];
420     default:
421         buf = tbGetBuffer(40);
422         snprintf(buf, 40, "0x%x", type & XkbSI_OpMask);
423         return buf;
424     }
425 }