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