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