~ubuntu-branches/ubuntu/intrepid/xterm/intrepid-security

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
}