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 *) ¬abmap, "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