xref: /openbsd/usr.bin/mg/keymap.c (revision 4cfece93)
1 /*	$OpenBSD: keymap.c,v 1.58 2015/12/29 19:44:32 lum Exp $	*/
2 
3 /* This file is in the public domain. */
4 
5 /*
6  * Keyboard maps.  This is character set dependent.  The terminal specific
7  * parts of building the keymap has been moved to a better place.
8  */
9 
10 #include <sys/queue.h>
11 #include <signal.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 
16 #include "def.h"
17 #include "kbd.h"
18 
19 /*
20  * initial keymap declarations, deepest first
21  */
22 
23 static PF cHcG[] = {
24 	ctrlg,			/* ^G */
25 	help_help		/* ^H */
26 };
27 
28 static PF cHa[] = {
29 	apropos_command,	/* a */
30 	wallchart,		/* b */
31 	desckey			/* c */
32 };
33 
34 struct KEYMAPE (2) helpmap = {
35 	2,
36 	2,
37 	rescan,
38 	{
39 		{
40 			CCHR('G'), CCHR('H'), cHcG, NULL
41 		},
42 		{
43 			'a', 'c', cHa, NULL
44 		}
45 	}
46 };
47 
48 static PF cCsc[] = {
49 	cscallerfuncs,		/* c */
50 	csdefinition,		/* d */
51 	csegrep,		/* e */
52 	csfindfile,		/* f */
53 	rescan,			/* g */
54 	rescan,			/* h */
55 	csfindinc,		/* i */
56 	rescan,			/* j */
57 	rescan,			/* k */
58 	rescan,			/* l */
59 	rescan,			/* m */
60 	csnextmatch,		/* n */
61 	rescan,			/* o */
62 	csprevmatch,		/* p */
63 	rescan,			/* q */
64 	rescan, 		/* r */
65 	cssymbol,		/* s */
66 	csfindtext		/* t */
67 };
68 
69 static struct KEYMAPE (1) cCsmap = {
70 	1,
71 	1,
72 	rescan,
73 	{
74 		{
75 			'c', 't', cCsc, NULL
76 		}
77 	}
78 };
79 
80 static PF cCs[] = {
81 	NULL			/* s */
82 };
83 
84 struct KEYMAPE (2) ccmap = {
85 	2,
86 	2,
87 	rescan,
88 	{
89 		{
90 			CCHR('@'), CCHR('@'), (PF[]){ rescan }, NULL
91 		},
92 		{
93 			's', 's', cCs, (KEYMAP *) & cCsmap
94 		}
95 	}
96 };
97 
98 static PF cX4cF[] = {
99 	poptofile,		/* ^f */
100 	ctrlg			/* ^g */
101 };
102 static PF cX4b[] = {
103 	poptobuffer,		/* b */
104 	rescan,			/* c */
105 	rescan,			/* d */
106 	rescan,			/* e */
107 	poptofile		/* f */
108 };
109 static struct KEYMAPE (2) cX4map = {
110 	2,
111 	2,
112 	rescan,
113 	{
114 		{
115 			CCHR('F'), CCHR('G'), cX4cF, NULL
116 		},
117 		{
118 			'b', 'f', cX4b, NULL
119 		}
120 	}
121 };
122 
123 static PF cXcB[] = {
124 	listbuffers,		/* ^B */
125 	quit,			/* ^C */
126 	rescan,			/* ^D */
127 	rescan,			/* ^E */
128 	filevisit,		/* ^F */
129 	ctrlg			/* ^G */
130 };
131 
132 static PF cXcL[] = {
133 	lowerregion,		/* ^L */
134 	rescan,			/* ^M */
135 	rescan,			/* ^N */
136 	deblank,		/* ^O */
137 	rescan,			/* ^P */
138 	togglereadonly,		/* ^Q */
139 	filevisitro,		/* ^R */
140 	filesave,		/* ^S */
141 	rescan,			/* ^T */
142 	upperregion,		/* ^U */
143 	filevisitalt,		/* ^V */
144 	filewrite,		/* ^W */
145 	swapmark		/* ^X */
146 };
147 
148 static PF cXlp[] = {
149 	definemacro,		/* ( */
150 	finishmacro		/* ) */
151 };
152 
153 static PF cX0[] = {
154 	delwind,		/* 0 */
155 	onlywind,		/* 1 */
156 	splitwind,		/* 2 */
157 	rescan,			/* 3 */
158 	NULL			/* 4 */
159 };
160 
161 static PF cXeq[] = {
162 	showcpos		/* = */
163 };
164 
165 static PF cXcar[] = {
166 	enlargewind,		/* ^ */
167 	rescan,			/* _ */
168 	next_error,		/* ` */
169 	rescan,			/* a */
170 	usebuffer,		/* b */
171 	rescan,			/* c */
172 	rescan,			/* d */
173 	executemacro,		/* e */
174 	setfillcol,		/* f */
175 	gotoline,		/* g */
176 	markbuffer,		/* h */
177 	fileinsert,		/* i */
178 	rescan,			/* j */
179 	killbuffer_cmd,		/* k */
180 	rescan,			/* l */
181 	rescan,			/* m */
182 	nextwind,		/* n */
183 	nextwind,		/* o */
184 	prevwind,		/* p */
185 	rescan,			/* q */
186 	rescan,			/* r */
187 	savebuffers,		/* s */
188 	rescan,			/* t */
189 	undo			/* u */
190 };
191 
192 struct KEYMAPE (6) cXmap = {
193 	6,
194 	6,
195 	rescan,
196 	{
197 		{
198 			CCHR('B'), CCHR('G'), cXcB, NULL
199 		},
200 		{
201 			CCHR('L'), CCHR('X'), cXcL, NULL
202 		},
203 		{
204 			'(', ')', cXlp, NULL
205 		},
206 		{
207 			'0', '4', cX0, (KEYMAP *) & cX4map
208 		},
209 		{
210 			'=', '=', cXeq, NULL
211 		},
212 		{
213 			'^', 'u', cXcar, NULL
214 		}
215 	}
216 };
217 
218 static PF metacG[] = {
219 	ctrlg			/* ^G */
220 };
221 
222 static PF metacV[] = {
223 	pagenext		/* ^V */
224 };
225 
226 static PF metaspex[] = {
227 	justone,		/* space */
228 	shellcommand		/* ! */
229 };
230 
231 static PF metapct[] = {
232 	queryrepl		/* % */
233 };
234 
235 static PF metami[] = {
236 	poptag,                 /* * */
237 	rescan,                 /* + */
238 	rescan,                 /* , */
239 	negative_argument,	/* - */
240 	findtag,		/* . */
241 	rescan,			/* / */
242 	digit_argument,		/* 0 */
243 	digit_argument,		/* 1 */
244 	digit_argument,		/* 2 */
245 	digit_argument,		/* 3 */
246 	digit_argument,		/* 4 */
247 	digit_argument,		/* 5 */
248 	digit_argument,		/* 6 */
249 	digit_argument,		/* 7 */
250 	digit_argument,		/* 8 */
251 	digit_argument,		/* 9 */
252 	rescan,			/* : */
253 	rescan,			/* ; */
254 	gotobob,		/* < */
255 	rescan,			/* = */
256 	gotoeob			/* > */
257 };
258 
259 static PF metasqf[] = {
260 	NULL,			/* [ */
261 	delwhite,		/* \ */
262 	rescan,			/* ] */
263 	joinline,		/* ^ */
264 	rescan,			/* _ */
265 	rescan,			/* ` */
266 	rescan,			/* a */
267 	backword,		/* b */
268 	capword,		/* c */
269 	delfword,		/* d */
270 	rescan,			/* e */
271 	forwword,		/* f */
272 	rescan,			/* g */
273 	markpara		/* h */
274 };
275 
276 static PF metal[] = {
277 	lowerword,		/* l */
278 	backtoindent,		/* m */
279 	rescan,			/* n */
280 	rescan,			/* o */
281 	rescan,			/* p */
282 	fillpara,		/* q */
283 	backsearch,		/* r */
284 	forwsearch,		/* s */
285 	transposeword,		/* t */
286 	upperword,		/* u */
287 	backpage,		/* v */
288 	copyregion,		/* w */
289 	extend,			/* x */
290 	rescan,			/* y */
291 	rescan,			/* z */
292 	gotobop,		/* { */
293 	piperegion,		/* | */
294 	gotoeop			/* } */
295 };
296 
297 static PF metasqlZ[] = {
298 	rescan			/* Z */
299 };
300 
301 static PF metatilde[] = {
302 	notmodified,		/* ~ */
303 	delbword		/* DEL */
304 };
305 
306 struct KEYMAPE (1) metasqlmap = {
307 	1,
308 	1,
309 	rescan,
310 	{
311 		{
312 			'Z', 'Z', metasqlZ, NULL
313 		}
314 	}
315 };
316 
317 struct KEYMAPE (8) metamap = {
318 	8,
319 	8,
320 	rescan,
321 	{
322 		{
323 			CCHR('G'), CCHR('G'), metacG, NULL
324 		},
325 		{
326 			CCHR('V'), CCHR('V'), metacV, NULL
327 		},
328 		{
329 			' ', '!', metaspex, NULL
330 		},
331 		{
332 			'%', '%', metapct, NULL
333 		},
334 		{
335 			'*', '>', metami, NULL
336 		},
337 		{
338 			'[', 'h', metasqf, (KEYMAP *) &metasqlmap
339 		},
340 		{
341 			'l', '}', metal, NULL
342 		},
343 		{
344 			'~', CCHR('?'), metatilde, NULL
345 		}
346 	}
347 };
348 
349 static PF fund_at[] = {
350 	setmark,		/* ^@ */
351 	gotobol,		/* ^A */
352 	backchar,		/* ^B */
353 	NULL,			/* ^C */
354 	forwdel,		/* ^D */
355 	gotoeol,		/* ^E */
356 	forwchar,		/* ^F */
357 	ctrlg,			/* ^G */
358 };
359 
360 static PF fund_h[] = {
361 	NULL,			/* ^H */
362 };
363 
364 
365 /* ^I is selfinsert */
366 static PF fund_CJ[] = {
367 	lfindent,		/* ^J */
368 	killline,		/* ^K */
369 	reposition,		/* ^L */
370 	enewline,		/* ^M */
371 	forwline,		/* ^N */
372 	openline,		/* ^O */
373 	backline,		/* ^P */
374 	quote,			/* ^Q */
375 	backisearch,		/* ^R */
376 	forwisearch,		/* ^S */
377 	twiddle,		/* ^T */
378 	universal_argument,	/* ^U */
379 	forwpage,		/* ^V */
380 	killregion,		/* ^W */
381 	NULL,			/* ^X */
382 	yank,			/* ^Y */
383 	spawncli		/* ^Z */
384 };
385 
386 static PF fund_esc[] = {
387 	NULL,			/* esc */
388 	rescan,			/* ^\ selfinsert is default on fundamental */
389 	rescan,			/* ^] */
390 	rescan,			/* ^^ */
391 	undo			/* ^_ */
392 };
393 
394 static PF fund_del[] = {
395 	backdel			/* DEL */
396 };
397 
398 static PF fund_cb[] = {
399 	showmatch		/* ) ] }  */
400 };
401 
402 static struct KEYMAPE (8) fundmap = {
403 	8,
404 	8,
405 	selfinsert,
406 	{
407 		{
408 			CCHR('@'), CCHR('G'), fund_at, (KEYMAP *) & ccmap
409 		},
410 		{
411 			CCHR('H'), CCHR('H'), fund_h, (KEYMAP *) & helpmap
412 		},
413 		{
414 			CCHR('J'), CCHR('Z'), fund_CJ, (KEYMAP *) & cXmap
415 		},
416 		{
417 			CCHR('['), CCHR('_'), fund_esc, (KEYMAP *) & metamap
418 		},
419 		{
420 			')', ')', fund_cb, NULL
421 		},
422 		{
423 			']', ']', fund_cb, NULL
424 		},
425 		{
426 			'}', '}', fund_cb, NULL
427 		},
428 		{
429 			CCHR('?'), CCHR('?'), fund_del, NULL
430 		},
431 	}
432 };
433 
434 static PF fill_sp[] = {
435 	fillword		/* ' ' */
436 };
437 
438 static struct KEYMAPE (1) fillmap = {
439 	1,
440 	1,
441 	rescan,
442 	{
443 		{ ' ', ' ', fill_sp, NULL }
444 	}
445 };
446 
447 static PF indent_lf[] = {
448 	enewline,		/* ^J */
449 	rescan,			/* ^K */
450 	rescan,			/* ^L */
451 	lfindent		/* ^M */
452 };
453 
454 static struct KEYMAPE (1) indntmap = {
455 	1,
456 	1,
457 	rescan,
458 	{
459 		{
460 			CCHR('J'), CCHR('M'), indent_lf, NULL
461 		}
462 	}
463 };
464 
465 #ifdef NOTAB
466 static PF notab_tab[] = {
467 	space_to_tabstop	/* ^I */
468 };
469 
470 static struct KEYMAPE (1) notabmap = {
471 	1,
472 	1,
473 	rescan,
474 	{
475 		{
476 			CCHR('I'), CCHR('I'), notab_tab, NULL
477 		}
478 	}
479 };
480 #endif /* NOTAB */
481 
482 static struct KEYMAPE (1) overwmap = {
483 	0,
484 	1,		/* 1 to avoid 0 sized array */
485 	rescan,
486 	{
487 		/* unused dummy entry for VMS C */
488 		{
489 			(KCHAR)0, (KCHAR)0, NULL, NULL
490 		}
491 	}
492 };
493 
494 
495 /*
496  * The basic (root) keyboard map
497  */
498 struct maps_s	fundamental_mode = { (KEYMAP *)&fundmap, "fundamental" };
499 
500 /*
501  * give names to the maps, for use by help etc. If the map is to be bindable,
502  * it must also be listed in the function name table below with the same
503  * name. Maps created dynamically currently don't get added here, thus are
504  * unnamed. Modes are just named keymaps with functions to add/subtract them
505  * from a buffer's list of modes.  If you change a mode name, change it in
506  * modes.c also.
507  */
508 
509 static struct maps_s map_table[] = {
510 	{(KEYMAP *) &fillmap, "fill",},
511 	{(KEYMAP *) &indntmap, "indent",},
512 #ifdef NOTAB
513 	{(KEYMAP *) &notabmap, "notab",},
514 #endif /* NOTAB */
515 	{(KEYMAP *) &overwmap, "overwrite",},
516 	{(KEYMAP *) &metamap, "esc prefix",},
517 	{(KEYMAP *) &cXmap, "c-x prefix",},
518 	{(KEYMAP *) &cX4map, "c-x 4 prefix",},
519 	{(KEYMAP *) &helpmap, "help",},
520 	{NULL, NULL}
521 };
522 
523 struct maps_s *maps;
524 
525 void
526 maps_init(void)
527 {
528 	int	 i;
529 	struct maps_s	*mp;
530 
531 	maps = &fundamental_mode;
532 	for (i = 0; map_table[i].p_name != NULL; i++) {
533 		mp = &map_table[i];
534 		mp->p_next = maps;
535 		maps = mp;
536 	}
537 }
538 
539 /*
540  * Insert a new (named) keymap at the head of the keymap list.
541  */
542 int
543 maps_add(KEYMAP *map, const char *name)
544 {
545 	struct maps_s	*mp;
546 
547 	if ((mp = malloc(sizeof(*mp))) == NULL)
548 		return (FALSE);
549 
550 	mp->p_name = name;
551 	mp->p_map = map;
552 	mp->p_next = maps;
553 	maps = mp;
554 
555 	return (TRUE);
556 }
557 
558 struct maps_s *
559 name_mode(const char *name)
560 {
561 	struct maps_s	*mp;
562 
563 	for (mp = maps; mp != NULL; mp = mp->p_next)
564 		if (strcmp(mp->p_name, name) == 0)
565 			return (mp);
566 	return (NULL);
567 }
568 
569 KEYMAP *
570 name_map(const char *name)
571 {
572 	struct maps_s	*mp;
573 
574 	return ((mp = name_mode(name)) == NULL ? NULL : mp->p_map);
575 }
576