01807476ff43662ea8e62e0857f94c8c29004b65
[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 static char *modNames[XkbNumModifiers] = {
157     "Shift",
158     "Lock",
159     "Control",
160     "Mod1",
161     "Mod2",
162     "Mod3",
163     "Mod4",
164     "Mod5"
165 };
166
167 char *
168 XkbcModMaskText(unsigned mask, Bool cFormat)
169 {
170     int i, rem, bit;
171     char *str, *buf;
172
173     if ((mask & 0xff) == 0xff)
174         return (cFormat ? "0xff" : "all");
175
176     if ((mask & 0xff) == 0)
177         return (cFormat ? "0" : "none");
178
179     rem = 64;
180     buf = tbGetBuffer(rem);
181     str = buf;
182     buf[0] = '\0';
183     for (i = 0, bit = 1; i < XkbNumModifiers && rem > 1; i++, bit <<= 1) {
184         int len;
185
186         if (!(mask & bit))
187             continue;
188
189         len = snprintf(str, rem, "%s%s%s",
190                        (str != buf) ? (cFormat ? "|" : "+") : "",
191                        modNames[i],
192                        cFormat ? "Mask" : "");
193         rem -= len;
194         str += len;
195     }
196
197     return buf;
198 }
199
200 char *
201 XkbcConfigText(unsigned config)
202 {
203     switch (config) {
204     case XkmSemanticsFile:
205         return "Semantics";
206     case XkmLayoutFile:
207         return "Layout";
208     case XkmKeymapFile:
209         return "Keymap";
210     case XkmGeometryFile:
211     case XkmGeometryIndex:
212         return "Geometry";
213     case XkmTypesIndex:
214         return "Types";
215     case XkmCompatMapIndex:
216         return "CompatMap";
217     case XkmSymbolsIndex:
218         return "Symbols";
219     case XkmIndicatorsIndex:
220         return "Indicators";
221     case XkmKeyNamesIndex:
222         return "KeyNames";
223     case XkmVirtualModsIndex:
224         return "VirtualMods";
225     default:
226         return "unknown";
227     }
228 }
229
230 char *
231 XkbcGeomFPText(int val)
232 {
233     char *buf;
234     int whole, frac;
235
236     buf = tbGetBuffer(12);
237     whole = val / XkbGeomPtsPerMM;
238     frac = val % XkbGeomPtsPerMM;
239
240     if (frac != 0)
241         snprintf(buf, 12, "%d.%d", whole, frac);
242     else
243         snprintf(buf, 12, "%d", whole);
244
245     return buf;
246 }
247
248 static char *actionTypeNames[XkbSA_NumActions]= {
249     "NoAction",         /* XkbSA_NoAction */
250     "SetMods",          /* XkbSA_SetMods */
251     "LatchMods",        /* XkbSA_LatchMods */
252     "LockMods",         /* XkbSA_LockMods */
253     "SetGroup",         /* XkbSA_SetGroup */
254     "LatchGroup",       /* XkbSA_LatchGroup */
255     "LockGroup",        /* XkbSA_LockGroup */
256     "MovePtr",          /* XkbSA_MovePtr */
257     "PtrBtn",           /* XkbSA_PtrBtn */
258     "LockPtrBtn",       /* XkbSA_LockPtrBtn */
259     "SetPtrDflt",       /* XkbSA_SetPtrDflt */
260     "ISOLock",          /* XkbSA_ISOLock */
261     "Terminate",        /* XkbSA_Terminate */
262     "SwitchScreen",     /* XkbSA_SwitchScreen */
263     "SetControls",      /* XkbSA_SetControls */
264     "LockControls",     /* XkbSA_LockControls */
265     "ActionMessage",    /* XkbSA_ActionMessage */
266     "RedirectKey",      /* XkbSA_RedirectKey */
267     "DeviceBtn",        /* XkbSA_DeviceBtn */
268     "LockDeviceBtn",    /* XkbSA_LockDeviceBtn */
269     "DeviceValuator"    /* XkbSA_DeviceValuator */
270 };
271
272 char *
273 XkbcActionTypeText(unsigned type)
274 {
275     if (type <= XkbSA_LastAction)
276         return actionTypeNames[type];
277     return "Private";
278 }
279
280 char *
281 XkbcKeysymText(KeySym sym)
282 {
283     char *buf;
284
285     if (sym == NoSymbol)
286         return "NoSymbol";
287
288     if ((buf = XkbcKeysymToString(sym)))
289         return buf;
290
291     buf = tbGetBuffer(32);
292     snprintf(buf, 32, "0x%lx", (long)sym);
293     return buf;
294 }
295
296 char *
297 XkbcKeyNameText(char *name)
298 {
299     char *buf;
300     int len;
301
302     buf = tbGetBuffer(7);
303     buf[0] = '<';
304     strncpy(&buf[1], name, 4);
305     buf[5] = '\0';
306     len = strlen(buf);
307     buf[len++] = '>';
308     buf[len] = '\0';
309
310     return buf;
311 }
312
313 static char *siMatchText[5] = {
314     "NoneOf",       /* XkbSI_NoneOf */
315     "AnyOfOrNone",  /* XkbSI_AnyOfOrNone */
316     "AnyOf",        /* XkbSI_AnyOf */
317     "AllOf",        /* XkbSI_AllOf */
318     "Exactly"       /* XkbSI_Exactly */
319 };
320
321 char *
322 XkbcSIMatchText(unsigned type)
323 {
324     char *buf;
325
326     switch (type & XkbSI_OpMask) {
327     case XkbSI_NoneOf:
328         return siMatchText[0];
329     case XkbSI_AnyOfOrNone:
330         return siMatchText[1];
331     case XkbSI_AnyOf:
332         return siMatchText[2];
333     case XkbSI_AllOf:
334         return siMatchText[3];
335     case XkbSI_Exactly:
336         return siMatchText[4];
337     default:
338         buf = tbGetBuffer(40);
339         snprintf(buf, 40, "0x%x", type & XkbSI_OpMask);
340         return buf;
341     }
342 }