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