xref: /openbsd-src/usr.bin/mg/keymap.c (revision 4c1e55dc91edd6e69ccc60ce855900fbc12cf34f)
1 /*	$OpenBSD: keymap.c,v 1.50 2012/06/07 15:15:04 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 metasp[] = {
221 	justone			/* space */
222 };
223 
224 static PF metapct[] = {
225 	queryrepl		/* % */
226 };
227 
228 static PF metami[] = {
229 	poptag,                 /* * */
230 	rescan,                 /* + */
231 	rescan,                 /* , */
232 	negative_argument,	/* - */
233 	findtag,		/* . */
234 	rescan,			/* / */
235 	digit_argument,		/* 0 */
236 	digit_argument,		/* 1 */
237 	digit_argument,		/* 2 */
238 	digit_argument,		/* 3 */
239 	digit_argument,		/* 4 */
240 	digit_argument,		/* 5 */
241 	digit_argument,		/* 6 */
242 	digit_argument,		/* 7 */
243 	digit_argument,		/* 8 */
244 	digit_argument,		/* 9 */
245 	rescan,			/* : */
246 	rescan,			/* ; */
247 	gotobob,		/* < */
248 	rescan,			/* = */
249 	gotoeob			/* > */
250 };
251 
252 static PF metasqf[] = {
253 	NULL,			/* [ */
254 	delwhite,		/* \ */
255 	rescan,			/* ] */
256 	joinline,		/* ^ */
257 	rescan,			/* _ */
258 	rescan,			/* ` */
259 	rescan,			/* a */
260 	backword,		/* b */
261 	capword,		/* c */
262 	delfword,		/* d */
263 	rescan,			/* e */
264 	forwword		/* f */
265 };
266 
267 static PF metal[] = {
268 	lowerword,		/* l */
269 	backtoindent,		/* m */
270 	rescan,			/* n */
271 	rescan,			/* o */
272 	rescan,			/* p */
273 	fillpara,		/* q */
274 	backsearch,		/* r */
275 	forwsearch,		/* s */
276 	rescan,			/* t */
277 	upperword,		/* u */
278 	backpage,		/* v */
279 	copyregion,		/* w */
280 	extend,			/* x */
281 	rescan,			/* y */
282 	rescan,			/* z */
283 	gotobop,		/* { */
284 	piperegion,		/* | */
285 	gotoeop			/* } */
286 };
287 
288 static PF metasqlZ[] = {
289 	rescan			/* Z */
290 };
291 
292 static PF metatilde[] = {
293 	notmodified,		/* ~ */
294 	delbword		/* DEL */
295 };
296 
297 struct KEYMAPE (1 + IMAPEXT) metasqlmap = {
298 	1,
299 	1 + IMAPEXT,
300 	rescan,
301 	{
302 		{
303 			'Z', 'Z', metasqlZ, NULL
304 		}
305 	}
306 };
307 
308 struct KEYMAPE (8 + IMAPEXT) metamap = {
309 	8,
310 	8 + IMAPEXT,
311 	rescan,
312 	{
313 		{
314 			CCHR('G'), CCHR('G'), metacG, NULL
315 		},
316 		{
317 			CCHR('V'), CCHR('V'), metacV, NULL
318 		},
319 		{
320 			' ', ' ', metasp, NULL
321 		},
322 		{
323 			'%', '%', metapct, NULL
324 		},
325 		{
326 			'*', '>', metami, NULL
327 		},
328 		{
329 			'[', 'f', metasqf, (KEYMAP *) &metasqlmap
330 		},
331 		{
332 			'l', '}', metal, NULL
333 		},
334 		{
335 			'~', CCHR('?'), metatilde, NULL
336 		}
337 	}
338 };
339 
340 static PF fund_at[] = {
341 	setmark,		/* ^@ */
342 	gotobol,		/* ^A */
343 	backchar,		/* ^B */
344 	NULL,			/* ^C */
345 	forwdel,		/* ^D */
346 	gotoeol,		/* ^E */
347 	forwchar,		/* ^F */
348 	ctrlg,			/* ^G */
349 };
350 
351 static PF fund_h[] = {
352 	NULL,			/* ^H */
353 };
354 
355 
356 /* ^I is selfinsert */
357 static PF fund_CJ[] = {
358 	lfindent,		/* ^J */
359 	killline,		/* ^K */
360 	reposition,		/* ^L */
361 	newline,		/* ^M */
362 	forwline,		/* ^N */
363 	openline,		/* ^O */
364 	backline,		/* ^P */
365 	quote,			/* ^Q */
366 	backisearch,		/* ^R */
367 	forwisearch,		/* ^S */
368 	twiddle,		/* ^T */
369 	universal_argument,	/* ^U */
370 	forwpage,		/* ^V */
371 	killregion,		/* ^W */
372 	NULL,			/* ^X */
373 	yank,			/* ^Y */
374 	spawncli		/* ^Z */
375 };
376 
377 static PF fund_esc[] = {
378 	NULL,			/* esc */
379 	rescan,			/* ^\ selfinsert is default on fundamental */
380 	rescan,			/* ^] */
381 	rescan,			/* ^^ */
382 	undo			/* ^_ */
383 };
384 
385 static PF fund_del[] = {
386 	backdel			/* DEL */
387 };
388 
389 static PF fund_cb[] = {
390 	showmatch		/* )  */
391 };
392 
393 #ifndef	FUND_XMAPS
394 #define NFUND_XMAPS	0	/* extra map sections after normal ones */
395 #endif
396 
397 static struct KEYMAPE (6 + NFUND_XMAPS + IMAPEXT) fundmap = {
398 	6 + NFUND_XMAPS,
399 	6 + NFUND_XMAPS + IMAPEXT,
400 	selfinsert,
401 	{
402 		{
403 			CCHR('@'), CCHR('G'), fund_at, (KEYMAP *) & ccmap
404 		},
405 		{
406 			CCHR('H'), CCHR('H'), fund_h, (KEYMAP *) & helpmap
407 		},
408 		{
409 			CCHR('J'), CCHR('Z'), fund_CJ, (KEYMAP *) & cXmap
410 		},
411 		{
412 			CCHR('['), CCHR('_'), fund_esc, (KEYMAP *) & metamap
413 		},
414 		{
415 			')', ')', fund_cb, NULL
416 		},
417 		{
418 			CCHR('?'), CCHR('?'), fund_del, NULL
419 		},
420 #ifdef FUND_XMAPS
421 		FUND_XMAPS,
422 #endif /* FUND_XMAPS */
423 	}
424 };
425 
426 static PF fill_sp[] = {
427 	fillword		/* ' ' */
428 };
429 
430 static struct KEYMAPE (1 + IMAPEXT) fillmap = {
431 	1,
432 	1 + IMAPEXT,
433 	rescan,
434 	{
435 		{ ' ', ' ', fill_sp, NULL }
436 	}
437 };
438 
439 static PF indent_lf[] = {
440 	newline,		/* ^J */
441 	rescan,			/* ^K */
442 	rescan,			/* ^L */
443 	lfindent		/* ^M */
444 };
445 
446 static struct KEYMAPE (1 + IMAPEXT) indntmap = {
447 	1,
448 	1 + IMAPEXT,
449 	rescan,
450 	{
451 		{
452 			CCHR('J'), CCHR('M'), indent_lf, NULL
453 		}
454 	}
455 };
456 
457 #ifdef NOTAB
458 static PF notab_tab[] = {
459 	space_to_tabstop	/* ^I */
460 };
461 
462 static struct KEYMAPE (1 + IMAPEXT) notabmap = {
463 	1,
464 	1 + IMAPEXT,
465 	rescan,
466 	{
467 		{
468 			CCHR('I'), CCHR('I'), notab_tab, NULL
469 		}
470 	}
471 };
472 #endif /* NOTAB */
473 
474 static struct KEYMAPE (1 + IMAPEXT) overwmap = {
475 	0,
476 	1 + IMAPEXT,		/* 1 to avoid 0 sized array */
477 	rescan,
478 	{
479 		/* unused dummy entry for VMS C */
480 		{
481 			(KCHAR)0, (KCHAR)0, NULL, NULL
482 		}
483 	}
484 };
485 
486 
487 /*
488  * The basic (root) keyboard map
489  */
490 struct maps_s	fundamental_mode = { (KEYMAP *)&fundmap, "fundamental" };
491 
492 /*
493  * give names to the maps, for use by help etc. If the map is to be bindable,
494  * it must also be listed in the function name table below with the same
495  * name. Maps created dynamically currently don't get added here, thus are
496  * unnamed. Modes are just named keymaps with functions to add/subtract them
497  * from a buffer's list of modes.  If you change a mode name, change it in
498  * modes.c also.
499  */
500 
501 static struct maps_s map_table[] = {
502 	{(KEYMAP *) &fillmap, "fill",},
503 	{(KEYMAP *) &indntmap, "indent",},
504 #ifdef NOTAB
505 	{(KEYMAP *) &notabmap, "notab",},
506 #endif /* NOTAB */
507 	{(KEYMAP *) &overwmap, "overwrite",},
508 	{(KEYMAP *) &metamap, "esc prefix",},
509 	{(KEYMAP *) &cXmap, "c-x prefix",},
510 	{(KEYMAP *) &cX4map, "c-x 4 prefix",},
511 	{(KEYMAP *) &helpmap, "help",},
512 	{NULL, NULL}
513 };
514 
515 struct maps_s *maps;
516 
517 void
518 maps_init(void)
519 {
520 	int	 i;
521 	struct maps_s	*mp;
522 
523 	maps = &fundamental_mode;
524 	for (i = 0; map_table[i].p_name != NULL; i++) {
525 		mp = &map_table[i];
526 		mp->p_next = maps;
527 		maps = mp;
528 	}
529 }
530 
531 /*
532  * Insert a new (named) keymap at the head of the keymap list.
533  */
534 int
535 maps_add(KEYMAP *map, const char *name)
536 {
537 	struct maps_s	*mp;
538 
539 	if ((mp = malloc(sizeof(*mp))) == NULL)
540 		return (FALSE);
541 
542 	mp->p_name = name;
543 	mp->p_map = map;
544 	mp->p_next = maps;
545 	maps = mp;
546 
547 	return (TRUE);
548 }
549 
550 struct maps_s *
551 name_mode(const char *name)
552 {
553 	struct maps_s	*mp;
554 
555 	for (mp = maps; mp != NULL; mp = mp->p_next)
556 		if (strcmp(mp->p_name, name) == 0)
557 			return (mp);
558 	return (NULL);
559 }
560 
561 KEYMAP *
562 name_map(const char *name)
563 {
564 	struct maps_s	*mp;
565 
566 	return ((mp = name_mode(name)) == NULL ? NULL : mp->p_map);
567 }
568