1.1.5
by Julien Cristau
Import upstream version 225 |
1 |
/* $XTermId: xtermcap.c,v 1.5 2007/03/18 22:34:20 tom Exp $ */
|
2 |
||
3 |
/*
|
|
4 |
* Copyright 2007 by Thomas E. Dickey
|
|
5 |
*
|
|
6 |
* All Rights Reserved
|
|
7 |
*
|
|
8 |
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
9 |
* copy of this software and associated documentation files (the
|
|
10 |
* "Software"), to deal in the Software without restriction, including
|
|
11 |
* without limitation the rights to use, copy, modify, merge, publish,
|
|
12 |
* distribute, sublicense, and/or sell copies of the Software, and to
|
|
13 |
* permit persons to whom the Software is furnished to do so, subject to
|
|
14 |
* the following conditions:
|
|
15 |
*
|
|
16 |
* The above copyright notice and this permission notice shall be included
|
|
17 |
* in all copies or substantial portions of the Software.
|
|
18 |
*
|
|
19 |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
20 |
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
21 |
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
22 |
* IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
|
|
23 |
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
24 |
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
25 |
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
26 |
*
|
|
27 |
* Except as contained in this notice, the name(s) of the above copyright
|
|
28 |
* holders shall not be used in advertising or otherwise to promote the
|
|
29 |
* sale, use or other dealings in this Software without prior written
|
|
30 |
* authorization.
|
|
31 |
*/
|
|
32 |
||
33 |
#include <xtermcap.h> |
|
34 |
||
35 |
#include <X11/keysym.h> |
|
36 |
||
37 |
#ifdef VMS
|
|
38 |
#include <X11/keysymdef.h> |
|
39 |
#endif
|
|
40 |
||
41 |
#include <xstrings.h> |
|
42 |
||
43 |
#if OPT_TCAP_QUERY || OPT_TCAP_FKEYS
|
|
44 |
||
45 |
typedef struct { |
|
46 |
char *tc; |
|
47 |
char *ti; |
|
48 |
int code; |
|
49 |
unsigned state; |
|
50 |
} TCAPINFO; |
|
51 |
/* *INDENT-OFF* */
|
|
52 |
#define DATA(tc,ti,x,y) { tc, ti, x, y }
|
|
53 |
static TCAPINFO table[] = { |
|
54 |
/* tcap terminfo code state */
|
|
55 |
DATA( "%1", "khlp", XK_Help, 0 ), |
|
56 |
DATA( "#1", "kHLP", XK_Help, ShiftMask ), |
|
57 |
DATA( "@0", "kfnd", XK_Find, 0 ), |
|
58 |
DATA( "*0", "kFND", XK_Find, ShiftMask ), |
|
59 |
DATA( "*6", "kslt", XK_Select, 0 ), |
|
60 |
DATA( "#6", "kSLT", XK_Select, ShiftMask ), |
|
61 |
||
62 |
DATA( "kh", "khome", XK_Home, 0 ), |
|
63 |
DATA( "#2", "kHOM", XK_Home, ShiftMask ), |
|
64 |
DATA( "@7", "kend", XK_End, 0 ), |
|
65 |
DATA( "*7", "kEND", XK_End, ShiftMask ), |
|
66 |
||
67 |
DATA( "kl", "kcub1", XK_Left, 0 ), |
|
68 |
DATA( "kr", "kcuf1", XK_Right, 0 ), |
|
69 |
DATA( "ku", "kcuu1", XK_Up, 0 ), |
|
70 |
DATA( "kd", "kcud1", XK_Down, 0 ), |
|
71 |
||
72 |
DATA( "#4", "kLFT", XK_Left, ShiftMask ), |
|
73 |
DATA( "%i", "kRIT", XK_Right, ShiftMask ), |
|
74 |
DATA( "%e", "kPRV", XK_Up, ShiftMask ), |
|
75 |
DATA( "%c", "kNXT", XK_Down, ShiftMask ), |
|
76 |
||
77 |
DATA( "k1", "kf1", XK_Fn(1), 0 ), |
|
78 |
DATA( "k2", "kf2", XK_Fn(2), 0 ), |
|
79 |
DATA( "k3", "kf3", XK_Fn(3), 0 ), |
|
80 |
DATA( "k4", "kf4", XK_Fn(4), 0 ), |
|
81 |
DATA( "k5", "kf5", XK_Fn(5), 0 ), |
|
82 |
DATA( "k6", "kf6", XK_Fn(6), 0 ), |
|
83 |
DATA( "k7", "kf7", XK_Fn(7), 0 ), |
|
84 |
DATA( "k8", "kf8", XK_Fn(8), 0 ), |
|
85 |
DATA( "k9", "kf9", XK_Fn(9), 0 ), |
|
86 |
DATA( "k;", "kf10", XK_Fn(10), 0 ), |
|
87 |
||
88 |
DATA( "F1", "kf11", XK_Fn(11), 0 ), |
|
89 |
DATA( "F2", "kf12", XK_Fn(12), 0 ), |
|
90 |
DATA( "F3", "kf13", XK_Fn(13), 0 ), |
|
91 |
DATA( "F4", "kf14", XK_Fn(14), 0 ), |
|
92 |
DATA( "F5", "kf15", XK_Fn(15), 0 ), |
|
93 |
DATA( "F6", "kf16", XK_Fn(16), 0 ), |
|
94 |
DATA( "F7", "kf17", XK_Fn(17), 0 ), |
|
95 |
DATA( "F8", "kf18", XK_Fn(18), 0 ), |
|
96 |
DATA( "F9", "kf19", XK_Fn(19), 0 ), |
|
97 |
DATA( "FA", "kf20", XK_Fn(20), 0 ), |
|
98 |
DATA( "FB", "kf21", XK_Fn(21), 0 ), |
|
99 |
DATA( "FC", "kf22", XK_Fn(22), 0 ), |
|
100 |
DATA( "FD", "kf23", XK_Fn(23), 0 ), |
|
101 |
DATA( "FE", "kf24", XK_Fn(24), 0 ), |
|
102 |
DATA( "FF", "kf25", XK_Fn(25), 0 ), |
|
103 |
DATA( "FG", "kf26", XK_Fn(26), 0 ), |
|
104 |
DATA( "FH", "kf27", XK_Fn(27), 0 ), |
|
105 |
DATA( "FI", "kf28", XK_Fn(28), 0 ), |
|
106 |
DATA( "FJ", "kf29", XK_Fn(29), 0 ), |
|
107 |
DATA( "FK", "kf30", XK_Fn(30), 0 ), |
|
108 |
DATA( "FL", "kf31", XK_Fn(31), 0 ), |
|
109 |
DATA( "FM", "kf32", XK_Fn(32), 0 ), |
|
110 |
DATA( "FN", "kf33", XK_Fn(33), 0 ), |
|
111 |
DATA( "FO", "kf34", XK_Fn(34), 0 ), |
|
112 |
DATA( "FP", "kf35", XK_Fn(35), 0 ), |
|
113 |
||
114 |
DATA( "FQ", "kf36", -36, 0 ), |
|
115 |
DATA( "FR", "kf37", -37, 0 ), |
|
116 |
DATA( "FS", "kf38", -38, 0 ), |
|
117 |
DATA( "FT", "kf39", -39, 0 ), |
|
118 |
DATA( "FU", "kf40", -40, 0 ), |
|
119 |
DATA( "FV", "kf41", -41, 0 ), |
|
120 |
DATA( "FW", "kf42", -42, 0 ), |
|
121 |
DATA( "FX", "kf43", -43, 0 ), |
|
122 |
DATA( "FY", "kf44", -44, 0 ), |
|
123 |
DATA( "FZ", "kf45", -45, 0 ), |
|
124 |
DATA( "Fa", "kf46", -46, 0 ), |
|
125 |
DATA( "Fb", "kf47", -47, 0 ), |
|
126 |
DATA( "Fc", "kf48", -48, 0 ), |
|
127 |
DATA( "Fd", "kf49", -49, 0 ), |
|
128 |
DATA( "Fe", "kf50", -50, 0 ), |
|
129 |
DATA( "Ff", "kf51", -51, 0 ), |
|
130 |
DATA( "Fg", "kf52", -52, 0 ), |
|
131 |
DATA( "Fh", "kf53", -53, 0 ), |
|
132 |
DATA( "Fi", "kf54", -54, 0 ), |
|
133 |
DATA( "Fj", "kf55", -55, 0 ), |
|
134 |
DATA( "Fk", "kf56", -56, 0 ), |
|
135 |
DATA( "Fl", "kf57", -57, 0 ), |
|
136 |
DATA( "Fm", "kf58", -58, 0 ), |
|
137 |
DATA( "Fn", "kf59", -59, 0 ), |
|
138 |
DATA( "Fo", "kf60", -60, 0 ), |
|
139 |
DATA( "Fp", "kf61", -61, 0 ), |
|
140 |
DATA( "Fq", "kf62", -62, 0 ), |
|
141 |
DATA( "Fr", "kf63", -63, 0 ), |
|
142 |
||
143 |
DATA( "K1", "ka1", XK_KP_Home, 0 ), |
|
144 |
DATA( "K4", "kc1", XK_KP_End, 0 ), |
|
145 |
||
146 |
#ifdef XK_ISO_Left_Tab
|
|
147 |
DATA( "kB", "kcbt", XK_ISO_Left_Tab, 0 ), |
|
148 |
#endif
|
|
149 |
DATA( "kC", "kclr", XK_Clear, 0 ), |
|
150 |
DATA( "kD", "kdch1", XK_Delete, 0 ), |
|
151 |
DATA( "kI", "kich1", XK_Insert, 0 ), |
|
152 |
DATA( "kN", "knp", XK_Next, 0 ), |
|
153 |
DATA( "kP", "kpp", XK_Prior, 0 ), |
|
154 |
DATA( "kb", "kbs", XK_BackSpace, 0 ), |
|
155 |
# if OPT_TCAP_QUERY && OPT_ISO_COLORS
|
|
156 |
/* XK_COLORS is a fake code. */
|
|
157 |
DATA( "Co", "colors", XK_COLORS, 0 ), |
|
158 |
# endif
|
|
159 |
};
|
|
160 |
#undef DATA
|
|
161 |
/* *INDENT-ON* */
|
|
162 |
||
163 |
#if OPT_TCAP_QUERY
|
|
164 |
static int |
|
165 |
hex2int(int c) |
|
166 |
{
|
|
167 |
if (c >= '0' && c <= '9') |
|
168 |
return c - '0'; |
|
169 |
if (c >= 'a' && c <= 'f') |
|
170 |
return c - 'a' + 10; |
|
171 |
if (c >= 'A' && c <= 'F') |
|
172 |
return c - 'A' + 10; |
|
173 |
return -1; |
|
174 |
}
|
|
175 |
||
176 |
static TCAPINFO * |
|
177 |
lookupTcapByName(const char *name) |
|
178 |
{
|
|
179 |
TCAPINFO *result = 0; |
|
180 |
Cardinal n; |
|
181 |
||
182 |
for (n = 0; n < XtNumber(table); n++) { |
|
183 |
if (!strcmp(table[n].ti, name) || !strcmp(table[n].tc, name)) { |
|
184 |
result = table + n; |
|
185 |
break; |
|
186 |
}
|
|
187 |
}
|
|
188 |
return result; |
|
189 |
}
|
|
190 |
||
191 |
/*
|
|
192 |
* Parse the termcap/terminfo name from the string, returning a positive number
|
|
193 |
* (the keysym) if found, otherwise -1. Update the string pointer.
|
|
194 |
* Returns the (shift, control) state in *state.
|
|
195 |
*
|
|
196 |
* This does not attempt to construct control/shift modifiers to construct
|
|
197 |
* function-key values. Instead, it sets the *fkey flag to pass to Input()
|
|
198 |
* and bypass the lookup of keysym altogether.
|
|
199 |
*/
|
|
200 |
int
|
|
201 |
xtermcapKeycode(XtermWidget xw, char **params, unsigned *state, Bool * fkey) |
|
202 |
{
|
|
203 |
TCAPINFO *data; |
|
204 |
unsigned len = 0; |
|
205 |
int code = -1; |
|
206 |
#define MAX_TNAME_LEN 6
|
|
207 |
char name[MAX_TNAME_LEN + 1]; |
|
208 |
char *p; |
|
209 |
||
210 |
TRACE(("xtermcapKeycode(%s)\n", *params)); |
|
211 |
||
212 |
/* Convert hex encoded name to ascii */
|
|
213 |
for (p = *params; hex2int(p[0]) >= 0 && hex2int(p[1]) >= 0; p += 2) { |
|
214 |
if (len >= MAX_TNAME_LEN) |
|
215 |
break; |
|
216 |
name[len++] = (hex2int(p[0]) << 4) + hex2int(p[1]); |
|
217 |
}
|
|
218 |
name[len] = 0; |
|
219 |
*params = p; |
|
220 |
||
221 |
*state = 0; |
|
222 |
*fkey = False; |
|
223 |
||
224 |
if (*p == 0 || *p == ';') { |
|
225 |
if ((data = lookupTcapByName(name)) != 0) { |
|
226 |
code = data->code; |
|
227 |
*state = data->state; |
|
228 |
if (IsFunctionKey(code)) { |
|
229 |
*fkey = True; |
|
230 |
} else if (code < 0) { |
|
231 |
*fkey = True; |
|
232 |
code = XK_Fn((-code)); |
|
233 |
}
|
|
234 |
#if OPT_SUN_FUNC_KEYS
|
|
235 |
if (*fkey && xw->keyboard.type == keyboardIsSun) { |
|
236 |
int num = code - XK_Fn(0); |
|
237 |
||
238 |
/* match function-key case in sunfuncvalue() */
|
|
239 |
if (num > 20) { |
|
240 |
if (num <= 30 || num > 47) { |
|
241 |
code = -1; |
|
242 |
} else { |
|
243 |
code -= 10; |
|
244 |
switch (num) { |
|
245 |
case 37: /* khome */ |
|
246 |
case 39: /* kpp */ |
|
247 |
case 41: /* kb2 */ |
|
248 |
case 43: /* kend */ |
|
249 |
case 45: /* knp */ |
|
250 |
code = -1; |
|
251 |
break; |
|
252 |
}
|
|
253 |
}
|
|
254 |
}
|
|
255 |
}
|
|
256 |
#endif
|
|
257 |
}
|
|
258 |
}
|
|
259 |
||
260 |
TRACE(("... xtermcapKeycode(%s, %u, %d) -> %#06x\n", |
|
261 |
name, *state, *fkey, code)); |
|
262 |
return code; |
|
263 |
}
|
|
264 |
#endif /* OPT_TCAP_QUERY */ |
|
265 |
||
266 |
#if OPT_TCAP_FKEYS
|
|
267 |
static TCAPINFO * |
|
268 |
lookupTcapByCode(int code, unsigned mask) |
|
269 |
{
|
|
270 |
TCAPINFO *result = 0; |
|
271 |
Cardinal n; |
|
272 |
||
273 |
for (n = 0; n < XtNumber(table); n++) { |
|
274 |
if (table[n].code == code && |
|
275 |
table[n].state == mask) { |
|
276 |
TRACE(("lookupTcapByCode %d:%s\n", n, table[n].ti)); |
|
277 |
result = table + n; |
|
278 |
break; |
|
279 |
}
|
|
280 |
}
|
|
281 |
return result; |
|
282 |
}
|
|
283 |
||
284 |
int
|
|
285 |
xtermcapString(XtermWidget xw, int keycode, unsigned mask) |
|
286 |
{
|
|
287 |
TCAPINFO *data; |
|
288 |
||
289 |
if ((data = lookupTcapByCode(keycode, mask)) != 0) { |
|
290 |
TScreen *screen = TScreenOf(xw); |
|
291 |
Cardinal which = data - table; |
|
292 |
char *fkey; |
|
293 |
||
294 |
if (screen->tcap_fkeys == 0) { |
|
295 |
Cardinal want = XtNumber(table); |
|
296 |
Cardinal have; |
|
297 |
char *area = screen->tcap_area; |
|
298 |
||
299 |
if ((screen->tcap_fkeys = TypeCallocN(char *, want)) == 0) |
|
300 |
return 0; |
|
301 |
for (have = 0; have < want; ++have) { |
|
302 |
if ((fkey = tgetstr(table[have].tc, &area)) != 0) { |
|
303 |
screen->tcap_fkeys[have] = x_strdup(fkey); |
|
304 |
}
|
|
305 |
}
|
|
306 |
}
|
|
307 |
if ((fkey = screen->tcap_fkeys[which]) != 0) { |
|
308 |
StringInput(xw, (Char *) fkey, strlen(fkey)); |
|
309 |
return 1; |
|
310 |
}
|
|
311 |
}
|
|
312 |
return 0; |
|
313 |
}
|
|
314 |
#endif /* OPT_TCAP_FKEYS */ |
|
315 |
||
316 |
#endif /* OPT_TCAP_QUERY || OPT_TCAP_FKEYS */ |
|
317 |
/*
|
|
318 |
* If we're linked to terminfo, tgetent() will return an empty buffer. We
|
|
319 |
* cannot use that to adjust the $TERMCAP variable.
|
|
320 |
*/
|
|
321 |
Bool
|
|
322 |
get_termcap(char *name, char *buffer) |
|
323 |
{
|
|
324 |
*buffer = 0; /* initialize, in case we're using terminfo's tgetent */ |
|
325 |
||
326 |
if (name != 0) { |
|
327 |
if (tgetent(buffer, name) == 1) { |
|
328 |
TRACE(("get_termcap(%s) succeeded (%s)\n", name, |
|
329 |
(*buffer |
|
330 |
? "ok:termcap, we can update $TERMCAP" |
|
331 |
: "assuming this is terminfo"))); |
|
332 |
return True; |
|
333 |
} else { |
|
334 |
*buffer = 0; /* just in case */ |
|
335 |
}
|
|
336 |
}
|
|
337 |
return False; |
|
338 |
}
|