GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/mg/kbd.c Lines: 0 200 0.0 %
Date: 2016-12-06 Branches: 0 186 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: kbd.c,v 1.30 2015/09/26 21:51:58 jasper Exp $	*/
2
3
/* This file is in the public domain. */
4
5
/*
6
 *	Terminal independent keyboard handling.
7
 */
8
9
#include <sys/queue.h>
10
#include <signal.h>
11
#include <stdio.h>
12
13
#include "def.h"
14
#include "kbd.h"
15
#include "key.h"
16
#include "macro.h"
17
18
#define METABIT 0x80
19
20
#define PROMPTL 80
21
char	 prompt[PROMPTL] = "", *promptp = prompt;
22
23
static int mgwrap(PF, int, int);
24
25
static int	 use_metakey = TRUE;
26
static int	 pushed = FALSE;
27
static int	 pushedc;
28
29
struct map_element	*ele;
30
31
struct key key;
32
33
/*
34
 * Toggle the value of use_metakey
35
 */
36
int
37
do_meta(int f, int n)
38
{
39
	if (f & FFARG)
40
		use_metakey = n > 0;
41
	else
42
		use_metakey = !use_metakey;
43
	ewprintf("Meta keys %sabled", use_metakey ? "en" : "dis");
44
	return (TRUE);
45
}
46
47
static int	 bs_map = 0;
48
49
/*
50
 * Toggle backspace mapping
51
 */
52
int
53
bsmap(int f, int n)
54
{
55
	if (f & FFARG)
56
		bs_map = n > 0;
57
	else
58
		bs_map = !bs_map;
59
	ewprintf("Backspace mapping %sabled", bs_map ? "en" : "dis");
60
	return (TRUE);
61
}
62
63
void
64
ungetkey(int c)
65
{
66
	if (use_metakey && pushed && c == CCHR('['))
67
		pushedc |= METABIT;
68
	else
69
		pushedc = c;
70
	pushed = TRUE;
71
}
72
73
int
74
getkey(int flag)
75
{
76
	int	 c;
77
78
	if (flag && !pushed) {
79
		if (prompt[0] != '\0' && ttwait(2000)) {
80
			/* avoid problems with % */
81
			ewprintf("%s", prompt);
82
			/* put the cursor back */
83
			update(CMODE);
84
			epresf = KCLEAR;
85
		}
86
		if (promptp > prompt)
87
			*(promptp - 1) = ' ';
88
	}
89
	if (pushed) {
90
		c = pushedc;
91
		pushed = FALSE;
92
	} else
93
		c = ttgetc();
94
95
	if (bs_map) {
96
		if (c == CCHR('H'))
97
			c = CCHR('?');
98
		else if (c == CCHR('?'))
99
			c = CCHR('H');
100
	}
101
	if (use_metakey && (c & METABIT)) {
102
		pushedc = c & ~METABIT;
103
		pushed = TRUE;
104
		c = CCHR('[');
105
	}
106
	if (flag && promptp < &prompt[PROMPTL - 5]) {
107
		promptp = getkeyname(promptp,
108
		    sizeof(prompt) - (promptp - prompt) - 1, c);
109
		*promptp++ = '-';
110
		*promptp = '\0';
111
	}
112
	return (c);
113
}
114
115
/*
116
 * doscan scans a keymap for a keyboard character and returns a pointer
117
 * to the function associated with that character.  Sets ele to the
118
 * keymap element the keyboard was found in as a side effect.
119
 */
120
PF
121
doscan(KEYMAP *map, int c, KEYMAP **newmap)
122
{
123
	struct map_element	*elec = &map->map_element[0];
124
	struct map_element	*last = &map->map_element[map->map_num];
125
	PF		 ret;
126
127
	while (elec < last && c > elec->k_num)
128
		elec++;
129
130
	/* used by prefix and binding code */
131
	ele = elec;
132
	if (elec >= last || c < elec->k_base)
133
		ret = map->map_default;
134
	else
135
		ret = elec->k_funcp[c - elec->k_base];
136
	if (ret == NULL && newmap != NULL)
137
		*newmap = elec->k_prefmap;
138
139
	return (ret);
140
}
141
142
int
143
doin(void)
144
{
145
	KEYMAP	*curmap;
146
	PF	 funct;
147
148
	*(promptp = prompt) = '\0';
149
	curmap = curbp->b_modes[curbp->b_nmodes]->p_map;
150
	key.k_count = 0;
151
	while ((funct = doscan(curmap, (key.k_chars[key.k_count++] =
152
	    getkey(TRUE)), &curmap)) == NULL)
153
		/* nothing */;
154
155
	if (macrodef && macrocount < MAXMACRO)
156
		macro[macrocount++].m_funct = funct;
157
158
	return (mgwrap(funct, 0, 1));
159
}
160
161
int
162
rescan(int f, int n)
163
{
164
	int	 c;
165
	KEYMAP	*curmap;
166
	int	 i;
167
	PF	 fp = NULL;
168
	int	 md = curbp->b_nmodes;
169
170
	for (;;) {
171
		if (ISUPPER(key.k_chars[key.k_count - 1])) {
172
			c = TOLOWER(key.k_chars[key.k_count - 1]);
173
			curmap = curbp->b_modes[md]->p_map;
174
			for (i = 0; i < key.k_count - 1; i++) {
175
				if ((fp = doscan(curmap, (key.k_chars[i]),
176
				    &curmap)) != NULL)
177
					break;
178
			}
179
			if (fp == NULL) {
180
				if ((fp = doscan(curmap, c, NULL)) == NULL)
181
					while ((fp = doscan(curmap,
182
					    key.k_chars[key.k_count++] =
183
					    getkey(TRUE), &curmap)) == NULL)
184
						/* nothing */;
185
				if (fp != rescan) {
186
					if (macrodef && macrocount <= MAXMACRO)
187
						macro[macrocount - 1].m_funct
188
						    = fp;
189
					return (mgwrap(fp, f, n));
190
				}
191
			}
192
		}
193
		/* try previous mode */
194
		if (--md < 0)
195
			return (ABORT);
196
		curmap = curbp->b_modes[md]->p_map;
197
		for (i = 0; i < key.k_count; i++) {
198
			if ((fp = doscan(curmap, (key.k_chars[i]), &curmap)) != NULL)
199
				break;
200
		}
201
		if (fp == NULL) {
202
			while ((fp = doscan(curmap, key.k_chars[i++] =
203
			    getkey(TRUE), &curmap)) == NULL)
204
				/* nothing */;
205
			key.k_count = i;
206
		}
207
		if (fp != rescan && i >= key.k_count - 1) {
208
			if (macrodef && macrocount <= MAXMACRO)
209
				macro[macrocount - 1].m_funct = fp;
210
			return (mgwrap(fp, f, n));
211
		}
212
	}
213
}
214
215
int
216
universal_argument(int f, int n)
217
{
218
	KEYMAP	*curmap;
219
	PF	 funct;
220
	int	 c, nn = 4;
221
222
	if (f & FFUNIV)
223
		nn *= n;
224
	for (;;) {
225
		key.k_chars[0] = c = getkey(TRUE);
226
		key.k_count = 1;
227
		if (c == '-')
228
			return (negative_argument(f, nn));
229
		if (c >= '0' && c <= '9')
230
			return (digit_argument(f, nn));
231
		curmap = curbp->b_modes[curbp->b_nmodes]->p_map;
232
		while ((funct = doscan(curmap, c, &curmap)) == NULL) {
233
			key.k_chars[key.k_count++] = c = getkey(TRUE);
234
		}
235
		if (funct != universal_argument) {
236
			if (macrodef && macrocount < MAXMACRO - 1) {
237
				if (f & FFARG)
238
					macrocount--;
239
				macro[macrocount++].m_count = nn;
240
				macro[macrocount++].m_funct = funct;
241
			}
242
			return (mgwrap(funct, FFUNIV, nn));
243
		}
244
		nn <<= 2;
245
	}
246
}
247
248
/* ARGSUSED */
249
int
250
digit_argument(int f, int n)
251
{
252
	KEYMAP	*curmap;
253
	PF	 funct;
254
	int	 nn, c;
255
256
	nn = key.k_chars[key.k_count - 1] - '0';
257
	for (;;) {
258
		c = getkey(TRUE);
259
		if (c < '0' || c > '9')
260
			break;
261
		nn *= 10;
262
		nn += c - '0';
263
	}
264
	key.k_chars[0] = c;
265
	key.k_count = 1;
266
	curmap = curbp->b_modes[curbp->b_nmodes]->p_map;
267
	while ((funct = doscan(curmap, c, &curmap)) == NULL) {
268
		key.k_chars[key.k_count++] = c = getkey(TRUE);
269
	}
270
	if (macrodef && macrocount < MAXMACRO - 1) {
271
		if (f & FFARG)
272
			macrocount--;
273
		else
274
			macro[macrocount - 1].m_funct = universal_argument;
275
		macro[macrocount++].m_count = nn;
276
		macro[macrocount++].m_funct = funct;
277
	}
278
	return (mgwrap(funct, FFOTHARG, nn));
279
}
280
281
int
282
negative_argument(int f, int n)
283
{
284
	KEYMAP	*curmap;
285
	PF	 funct;
286
	int	 c;
287
	int	 nn = 0;
288
289
	for (;;) {
290
		c = getkey(TRUE);
291
		if (c < '0' || c > '9')
292
			break;
293
		nn *= 10;
294
		nn += c - '0';
295
	}
296
	if (nn)
297
		nn = -nn;
298
	else
299
		nn = -n;
300
	key.k_chars[0] = c;
301
	key.k_count = 1;
302
	curmap = curbp->b_modes[curbp->b_nmodes]->p_map;
303
	while ((funct = doscan(curmap, c, &curmap)) == NULL) {
304
		key.k_chars[key.k_count++] = c = getkey(TRUE);
305
	}
306
	if (macrodef && macrocount < MAXMACRO - 1) {
307
		if (f & FFARG)
308
			macrocount--;
309
		else
310
			macro[macrocount - 1].m_funct = universal_argument;
311
		macro[macrocount++].m_count = nn;
312
		macro[macrocount++].m_funct = funct;
313
	}
314
	return (mgwrap(funct, FFNEGARG, nn));
315
}
316
317
/*
318
 * Insert a character.	While defining a macro, create a "LINE" containing
319
 * all inserted characters.
320
 */
321
int
322
selfinsert(int f, int n)
323
{
324
	struct line	*lp;
325
	int	 c;
326
	int	 count;
327
328
	if (n < 0)
329
		return (FALSE);
330
	if (n == 0)
331
		return (TRUE);
332
	c = key.k_chars[key.k_count - 1];
333
334
	if (macrodef && macrocount < MAXMACRO) {
335
		if (f & FFARG)
336
			macrocount -= 2;
337
338
		/* last command was insert -- tack on the end */
339
		if (lastflag & CFINS) {
340
			macrocount--;
341
			/* Ensure the line can handle the new characters */
342
			if (maclcur->l_size < maclcur->l_used + n) {
343
				if (lrealloc(maclcur, maclcur->l_used + n) ==
344
				    FALSE)
345
					return (FALSE);
346
			}
347
			maclcur->l_used += n;
348
			/* Copy in the new data */
349
			for (count = maclcur->l_used - n;
350
			    count < maclcur->l_used; count++)
351
				maclcur->l_text[count] = c;
352
		} else {
353
			macro[macrocount - 1].m_funct = insert;
354
			if ((lp = lalloc(n)) == NULL)
355
				return (FALSE);
356
			lp->l_bp = maclcur;
357
			lp->l_fp = maclcur->l_fp;
358
			maclcur->l_fp = lp;
359
			maclcur = lp;
360
			for (count = 0; count < n; count++)
361
				lp->l_text[count] = c;
362
		}
363
		thisflag |= CFINS;
364
	}
365
	if (c == '\n') {
366
		do {
367
			count = lnewline();
368
		} while (--n && count == TRUE);
369
		return (count);
370
	}
371
372
	/* overwrite mode */
373
	if (curbp->b_flag & BFOVERWRITE) {
374
		lchange(WFEDIT);
375
		while (curwp->w_doto < llength(curwp->w_dotp) && n--)
376
			lputc(curwp->w_dotp, curwp->w_doto++, c);
377
		if (n <= 0)
378
			return (TRUE);
379
	}
380
	return (linsert(n, c));
381
}
382
383
/*
384
 * This could be implemented as a keymap with everything defined as self-insert.
385
 */
386
int
387
quote(int f, int n)
388
{
389
	int	 c;
390
391
	key.k_count = 1;
392
	if ((key.k_chars[0] = getkey(TRUE)) >= '0' && key.k_chars[0] <= '7') {
393
		key.k_chars[0] -= '0';
394
		if ((c = getkey(TRUE)) >= '0' && c <= '7') {
395
			key.k_chars[0] <<= 3;
396
			key.k_chars[0] += c - '0';
397
			if ((c = getkey(TRUE)) >= '0' && c <= '7') {
398
				key.k_chars[0] <<= 3;
399
				key.k_chars[0] += c - '0';
400
			} else
401
				ungetkey(c);
402
		} else
403
			ungetkey(c);
404
	}
405
	return (selfinsert(f, n));
406
}
407
408
/*
409
 * Wraper function to count invocation repeats.
410
 * We ignore any function whose sole purpose is to get us
411
 * to the intended function.
412
 */
413
static int
414
mgwrap(PF funct, int f, int n)
415
{
416
	static	 PF ofp;
417
418
	if (funct != rescan &&
419
	    funct != negative_argument &&
420
	    funct != digit_argument &&
421
	    funct != universal_argument) {
422
		if (funct == ofp)
423
			rptcount++;
424
		else
425
			rptcount = 0;
426
		ofp = funct;
427
	}
428
429
	return ((*funct)(f, n));
430
}