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