1/*- 2 * Copyright (c) 1992, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * Copyright (c) 1992, 1993, 1994, 1995, 1996 5 * Keith Bostic. All rights reserved. 6 * 7 * See the LICENSE file for redistribution information. 8 */ 9 10#include "config.h" 11 12#include <sys/types.h> 13#include <sys/queue.h> 14#include <sys/time.h> 15 16#include <bitstring.h> 17#include <limits.h> 18#include <stdio.h> 19 20#include "../common/common.h" 21#include "vi.h" 22 23/* 24 * This array maps keystrokes to vi command functions. It is known 25 * in ex/ex_usage.c that it takes four columns to name a vi character. 26 */ 27VIKEYS const vikeys [MAXVIKEY + 1] = { 28/* 000 NUL -- The code in vi.c expects key 0 to be undefined. */ 29 {NULL}, 30/* 001 ^A */ 31 {v_searchw, V_ABS|V_CNT|V_MOVE|V_KEYW|VM_CUTREQ|VM_RCM_SET, 32 "[count]^A", 33 "^A search forward for cursor word"}, 34/* 002 ^B */ 35 {v_pageup, V_CNT|VM_RCM_SET, 36 "[count]^B", 37 "^B scroll up by screens"}, 38/* 003 ^C */ 39 {NULL, 0, 40 "^C", 41 "^C interrupt an operation (e.g. read, write, search)"}, 42/* 004 ^D */ 43 {v_hpagedown, V_CNT|VM_RCM_SET, 44 "[count]^D", 45 "^D scroll down by half screens (setting count)"}, 46/* 005 ^E */ 47 {v_linedown, V_CNT, 48 "[count]^E", 49 "^E scroll down by lines"}, 50/* 006 ^F */ 51 {v_pagedown, V_CNT|VM_RCM_SET, 52 "[count]^F", 53 "^F scroll down by screens"}, 54/* 007 ^G */ 55 {v_status, 0, 56 "^G", 57 "^G file status"}, 58/* 010 ^H */ 59 {v_left, V_CNT|V_MOVE|VM_RCM_SET, 60 "[count]^H", 61 "^H move left by characters"}, 62/* 011 ^I */ 63 {NULL}, 64/* 012 ^J */ 65 {v_down, V_CNT|V_MOVE|VM_LMODE|VM_RCM, 66 "[count]^J", 67 "^J move down by lines"}, 68/* 013 ^K */ 69 {NULL}, 70/* 014 ^L */ 71 {v_redraw, 0, 72 "^L", 73 "^L redraw screen"}, 74/* 015 ^M */ 75 {v_cr, V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETFNB, 76 "[count]^M", 77 "^M move down by lines (to first non-blank)"}, 78/* 016 ^N */ 79 {v_down, V_CNT|V_MOVE|VM_LMODE|VM_RCM, 80 "[count]^N", 81 "^N move down by lines"}, 82/* 017 ^O */ 83 {NULL}, 84/* 020 ^P */ 85 {v_up, V_CNT|V_MOVE|VM_LMODE|VM_RCM, 86 "[count]^P", 87 "^P move up by lines"}, 88/* 021 ^Q -- same as ^V if not used for hardware flow control. */ 89 {NULL}, 90/* 022 ^R */ 91 {v_redraw, 0, 92 "^R", 93 "^R redraw screen"}, 94/* 023 ^S -- not available, used for hardware flow control. */ 95 {NULL}, 96/* 024 ^T */ 97 {v_tagpop, V_ABS|VM_RCM_SET, 98 "^T", 99 "^T tag pop"}, 100/* 025 ^U */ 101 {v_hpageup, V_CNT|VM_RCM_SET, 102 "[count]^U", 103 "^U half page up (set count)"}, 104/* 026 ^V */ 105 {NULL, 0, 106 "^V", 107 "^V input a literal character"}, 108/* 027 ^W */ 109 {v_screen, 0, 110 "^W", 111 "^W move to next screen"}, 112/* 030 ^X */ 113 {NULL}, 114/* 031 ^Y */ 115 {v_lineup, V_CNT, 116 "[count]^Y", 117 "^Y page up by lines"}, 118/* 032 ^Z */ 119 {v_suspend, V_SECURE, 120 "^Z", 121 "^Z suspend editor"}, 122/* 033 ^[ */ 123 {NULL, 0, 124 "^[ <escape>", 125 "^[ <escape> exit input mode, cancel partial commands"}, 126/* 034 ^\ */ 127 {v_exmode, 0, 128 "^\\", 129 "^\\ switch to ex mode"}, 130/* 035 ^] */ 131 {v_tagpush, V_ABS|V_KEYW|VM_RCM_SET, 132 "^]", 133 "^] tag push cursor word"}, 134/* 036 ^^ */ 135 {v_switch, 0, 136 "^^", 137 "^^ switch to previous file"}, 138/* 037 ^_ */ 139 {NULL}, 140/* 040 ' ' */ 141 {v_right, V_CNT|V_MOVE|VM_RCM_SET, 142 "[count]' '", 143 " <space> move right by columns"}, 144/* 041 ! */ 145 {v_filter, V_CNT|V_DOT|V_MOTION|V_SECURE|VM_RCM_SET, 146 "[count]![count]motion command(s)", 147 " ! filter through command(s) to motion"}, 148/* 042 " */ 149 {NULL}, 150/* 043 # */ 151 {v_increment, V_CHAR|V_CNT|V_DOT|VM_RCM_SET, 152 "[count]# +|-|#", 153 " # number increment/decrement"}, 154/* 044 $ */ 155 {v_dollar, V_CNT|V_MOVE|VM_RCM_SETLAST, 156 " [count]$", 157 " $ move to last column"}, 158/* 045 % */ 159 {v_match, V_ABS|V_CNT|V_MOVE|VM_CUTREQ|VM_RCM_SET, 160 "%", 161 " % move to match"}, 162/* 046 & */ 163 {v_again, 0, 164 "&", 165 " & repeat substitution"}, 166/* 047 ' */ 167 {v_fmark, V_ABS_L|V_CHAR|V_MOVE|VM_LMODE|VM_RCM_SET, 168 "'['a-z]", 169 " ' move to mark (to first non-blank)"}, 170/* 050 ( */ 171 {v_sentenceb, V_ABS|V_CNT|V_MOVE|VM_CUTREQ|VM_RCM_SET, 172 "[count](", 173 " ( move back sentence"}, 174/* 051 ) */ 175 {v_sentencef, V_ABS|V_CNT|V_MOVE|VM_CUTREQ|VM_RCM_SET, 176 "[count])", 177 " ) move forward sentence"}, 178/* 052 * */ 179 {NULL}, 180/* 053 + */ 181 {v_down, V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETFNB, 182 "[count]+", 183 " + move down by lines (to first non-blank)"}, 184/* 054 , */ 185 {v_chrrepeat, V_CNT|V_MOVE|VM_RCM_SET, 186 "[count],", 187 " , reverse last F, f, T or t search"}, 188/* 055 - */ 189 {v_up, V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETFNB, 190 "[count]-", 191 " - move up by lines (to first non-blank)"}, 192/* 056 . */ 193 {NULL, 0, 194 ".", 195 " . repeat the last command"}, 196/* 057 / */ 197 {v_searchf, V_ABS_C|V_MOVE|VM_CUTREQ|VM_RCM_SET, 198 "/RE[/ offset]", 199 " / search forward"}, 200/* 060 0 */ 201 {v_zero, V_MOVE|VM_RCM_SET, 202 "0", 203 " 0 move to first character"}, 204/* 061 1 */ 205 {NULL}, 206/* 062 2 */ 207 {NULL}, 208/* 063 3 */ 209 {NULL}, 210/* 064 4 */ 211 {NULL}, 212/* 065 5 */ 213 {NULL}, 214/* 066 6 */ 215 {NULL}, 216/* 067 7 */ 217 {NULL}, 218/* 070 8 */ 219 {NULL}, 220/* 071 9 */ 221 {NULL}, 222/* 072 : */ 223 {v_ex, 0, 224 ":command [| command] ...", 225 " : ex command"}, 226/* 073 ; */ 227 {v_chrepeat, V_CNT|V_MOVE|VM_RCM_SET, 228 "[count];", 229 " ; repeat last F, f, T or t search"}, 230/* 074 < */ 231 {v_shiftl, V_CNT|V_DOT|V_MOTION|VM_RCM_SET, 232 "[count]<[count]motion", 233 " < shift lines left to motion"}, 234/* 075 = */ 235 {NULL}, 236/* 076 > */ 237 {v_shiftr, V_CNT|V_DOT|V_MOTION|VM_RCM_SET, 238 "[count]>[count]motion", 239 " > shift lines right to motion"}, 240/* 077 ? */ 241 {v_searchb, V_ABS_C|V_MOVE|VM_CUTREQ|VM_RCM_SET, 242 "?RE[? offset]", 243 " ? search backward"}, 244/* 100 @ */ 245 {v_at, V_CNT|V_RBUF|VM_RCM_SET, 246 "@buffer", 247 " @ execute buffer"}, 248/* 101 A */ 249 {v_iA, V_CNT|V_DOT|VM_RCM_SET, 250 "[count]A", 251 " A append to the line"}, 252/* 102 B */ 253 {v_wordB, V_CNT|V_MOVE|VM_RCM_SET, 254 "[count]B", 255 " B move back bigword"}, 256/* 103 C */ 257 {NULL, 0, 258 "[buffer][count]C", 259 " C change to end-of-line"}, 260/* 104 D */ 261 {NULL, 0, 262 "[buffer]D", 263 " D delete to end-of-line"}, 264/* 105 E */ 265 {v_wordE, V_CNT|V_MOVE|VM_RCM_SET, 266 "[count]E", 267 " E move to end of bigword"}, 268/* 106 F */ 269 {v_chF, V_CHAR|V_CNT|V_MOVE|VM_RCM_SET, 270 "[count]F character", 271 " F character in line backward search"}, 272/* 107 G */ 273 {v_lgoto, V_ABS_L|V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETFNB, 274 "[count]G", 275 " G move to line"}, 276/* 110 H */ 277 {v_home, V_ABS_L|V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETNNB, 278 "[count]H", 279 " H move to count lines from screen top"}, 280/* 111 I */ 281 {v_iI, V_CNT|V_DOT|VM_RCM_SET, 282 "[count]I", 283 " I insert before first nonblank"}, 284/* 112 J */ 285 {v_join, V_CNT|V_DOT|VM_RCM_SET, 286 "[count]J", 287 " J join lines"}, 288/* 113 K */ 289 {NULL}, 290/* 114 L */ 291 {v_bottom, V_ABS_L|V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETNNB, 292 "[count]L", 293 " L move to screen bottom"}, 294/* 115 M */ 295 {v_middle, V_ABS_L|V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETNNB, 296 "M", 297 " M move to screen middle"}, 298/* 116 N */ 299 {v_searchN, V_ABS_C|V_MOVE|VM_CUTREQ|VM_RCM_SET, 300 "n", 301 " N reverse last search"}, 302/* 117 O */ 303 {v_iO, V_CNT|V_DOT|VM_RCM_SET, 304 "[count]O", 305 " O insert above line"}, 306/* 120 P */ 307 {v_Put, V_CNT|V_DOT|V_OBUF|VM_RCM_SET, 308 "[buffer]P", 309 " P insert before cursor from buffer"}, 310/* 121 Q */ 311 {v_exmode, 0, 312 "Q", 313 " Q switch to ex mode"}, 314/* 122 R */ 315 {v_Replace, V_CNT|V_DOT|VM_RCM_SET, 316 "[count]R", 317 " R replace characters"}, 318/* 123 S */ 319 {NULL, 0, 320 "[buffer][count]S", 321 " S substitute for the line(s)"}, 322/* 124 T */ 323 {v_chT, V_CHAR|V_CNT|V_MOVE|VM_RCM_SET, 324 "[count]T character", 325 " T before character in line backward search"}, 326/* 125 U */ 327 {v_Undo, VM_RCM_SET, 328 "U", 329 " U Restore the current line"}, 330/* 126 V */ 331 {NULL}, 332/* 127 W */ 333 {v_wordW, V_CNT|V_MOVE|VM_RCM_SET, 334 "[count]W", 335 " W move to next bigword"}, 336/* 130 X */ 337 {v_Xchar, V_CNT|V_DOT|V_OBUF|VM_RCM_SET, 338 "[buffer][count]X", 339 " X delete character before cursor"}, 340/* 131 Y */ 341 {NULL, 0, 342 "[buffer][count]Y", 343 " Y copy line"}, 344/* 132 Z */ 345 {v_zexit, 0, 346 "ZZ", 347 "ZZ save file and exit"}, 348/* 133 [ */ 349 {v_sectionb, V_ABS|V_CNT|V_MOVE|VM_RCM_SET, 350 "[[", 351 "[[ move back section"}, 352/* 134 \ */ 353 {NULL}, 354/* 135 ] */ 355 {v_sectionf, V_ABS|V_CNT|V_MOVE|VM_RCM_SET, 356 "]]", 357 "]] move forward section"}, 358/* 136 ^ */ 359 /* 360 * DON'T set the VM_RCM_SETFNB flag, the function has to do the work 361 * anyway, in case it's a motion component. DO set VM_RCM_SET, so 362 * that any motion that's part of a command is preserved. 363 */ 364 {v_first, V_CNT|V_MOVE|VM_RCM_SET, 365 "^", 366 " ^ move to first non-blank"}, 367/* 137 _ */ 368 /* 369 * Needs both to set the VM_RCM_SETFNB flag, and to do the work 370 * in the function, in case it's a delete. 371 */ 372 {v_cfirst, V_CNT|V_MOVE|VM_RCM_SETFNB, 373 "_", 374 " _ move to first non-blank"}, 375/* 140 ` */ 376 {v_bmark, V_ABS_C|V_CHAR|V_MOVE|VM_CUTREQ|VM_RCM_SET, 377 "`[`a-z]", 378 " ` move to mark"}, 379/* 141 a */ 380 {v_ia, V_CNT|V_DOT|VM_RCM_SET, 381 "[count]a", 382 " a append after cursor"}, 383/* 142 b */ 384 {v_wordb, V_CNT|V_MOVE|VM_RCM_SET, 385 "[count]b", 386 " b move back word"}, 387/* 143 c */ 388 {v_change, V_CNT|V_DOT|V_MOTION|V_OBUF|VM_RCM_SET, 389 "[buffer][count]c[count]motion", 390 " c change to motion"}, 391/* 144 d */ 392 {v_delete, V_CNT|V_DOT|V_MOTION|V_OBUF|VM_RCM_SET, 393 "[buffer][count]d[count]motion", 394 " d delete to motion"}, 395/* 145 e */ 396 {v_worde, V_CNT|V_MOVE|VM_RCM_SET, 397 "[count]e", 398 " e move to end of word"}, 399/* 146 f */ 400 {v_chf, V_CHAR|V_CNT|V_MOVE|VM_RCM_SET, 401 "[count]f character", 402 " f character in line forward search"}, 403/* 147 g */ 404 {NULL}, 405/* 150 h */ 406 {v_left, V_CNT|V_MOVE|VM_RCM_SET, 407 "[count]h", 408 " h move left by columns"}, 409/* 151 i */ 410 {v_ii, V_CNT|V_DOT|VM_RCM_SET, 411 "[count]i", 412 " i insert before cursor"}, 413/* 152 j */ 414 {v_down, V_CNT|V_MOVE|VM_LMODE|VM_RCM, 415 "[count]j", 416 " j move down by lines"}, 417/* 153 k */ 418 {v_up, V_CNT|V_MOVE|VM_LMODE|VM_RCM, 419 "[count]k", 420 " k move up by lines"}, 421/* 154 l */ 422 {v_right, V_CNT|V_MOVE|VM_RCM_SET, 423 "[count]l", 424 " l move right by columns"}, 425/* 155 m */ 426 {v_mark, V_CHAR, 427 "m[a-z]", 428 " m set mark"}, 429/* 156 n */ 430 {v_searchn, V_ABS_C|V_MOVE|VM_CUTREQ|VM_RCM_SET, 431 "n", 432 " n repeat last search"}, 433/* 157 o */ 434 {v_io, V_CNT|V_DOT|VM_RCM_SET, 435 "[count]o", 436 " o append after line"}, 437/* 160 p */ 438 {v_put, V_CNT|V_DOT|V_OBUF|VM_RCM_SET, 439 "[buffer]p", 440 " p insert after cursor from buffer"}, 441/* 161 q */ 442 {NULL}, 443/* 162 r */ 444 {v_replace, V_CNT|V_DOT|VM_RCM_SET, 445 "[count]r character", 446 " r replace character"}, 447/* 163 s */ 448 {v_subst, V_CNT|V_DOT|V_OBUF|VM_RCM_SET, 449 "[buffer][count]s", 450 " s substitute character"}, 451/* 164 t */ 452 {v_cht, V_CHAR|V_CNT|V_MOVE|VM_RCM_SET, 453 "[count]t character", 454 " t before character in line forward search"}, 455/* 165 u */ 456 /* 457 * DON'T set the V_DOT flag, it' more complicated than that. 458 * See vi/vi.c for details. 459 */ 460 {v_undo, VM_RCM_SET, 461 "u", 462 " u undo last change"}, 463/* 166 v */ 464 {NULL}, 465/* 167 w */ 466 {v_wordw, V_CNT|V_MOVE|VM_RCM_SET, 467 "[count]w", 468 " w move to next word"}, 469/* 170 x */ 470 {v_xchar, V_CNT|V_DOT|V_OBUF|VM_RCM_SET, 471 "[buffer][count]x", 472 " x delete character"}, 473/* 171 y */ 474 {v_yank, V_CNT|V_DOT|V_MOTION|V_OBUF|VM_RCM_SET, 475 "[buffer][count]y[count]motion", 476 " y copy text to motion into a cut buffer"}, 477/* 172 z */ 478 /* 479 * DON'T set the V_CHAR flag, the char isn't required, 480 * so it's handled specially in getcmd(). 481 */ 482 {v_z, V_ABS_L|V_CNT|VM_RCM_SETFNB, 483 "[line]z[window_size][-|.|+|^|<CR>]", 484 " z reposition the screen"}, 485/* 173 { */ 486 {v_paragraphb, V_ABS|V_CNT|V_MOVE|VM_CUTREQ|VM_RCM_SET, 487 "[count]{", 488 " { move back paragraph"}, 489/* 174 | */ 490 {v_ncol, V_CNT|V_MOVE|VM_RCM_SET, 491 "[count]|", 492 " | move to column"}, 493/* 175 } */ 494 {v_paragraphf, V_ABS|V_CNT|V_MOVE|VM_CUTREQ|VM_RCM_SET, 495 "[count]}", 496 " } move forward paragraph"}, 497/* 176 ~ */ 498 {v_ulcase, V_CNT|V_DOT|VM_RCM_SET, 499 "[count]~", 500 " ~ reverse case"}, 501}; 502