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