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 <ctype.h> 18 #include <errno.h> 19 #include <limits.h> 20 #include <stdio.h> 21 #include <stdlib.h> 22 #include <string.h> 23 #include <unistd.h> 24 25 #include "../common/common.h" 26 #include "vi.h" 27 28 typedef enum { 29 GC_ERR, GC_ERR_NOFLUSH, GC_EVENT, GC_FATAL, GC_INTERRUPT, GC_OK 30 } gcret_t; 31 32 static VIKEYS const 33 *v_alias(SCR *, VICMD *, VIKEYS const *); 34 static gcret_t v_cmd(SCR *, VICMD *, VICMD *, VICMD *, int *, int *); 35 static int v_count(SCR *, ARG_CHAR_T, u_long *); 36 static void v_dtoh(SCR *); 37 static int v_init(SCR *); 38 static gcret_t v_key(SCR *, int, EVENT *, u_int32_t); 39 static int v_motion(SCR *, VICMD *, VICMD *, int *); 40 41 #if defined(DEBUG) && defined(COMLOG) 42 static void v_comlog(SCR *, VICMD *); 43 #endif 44 45 /* 46 * Side-effect: 47 * The dot structure can be set by the underlying vi functions, 48 * see v_Put() and v_put(). 49 */ 50 #define DOT (&VIP(sp)->sdot) 51 #define DOTMOTION (&VIP(sp)->sdotmotion) 52 53 /* 54 * vi -- 55 * Main vi command loop. 56 * 57 * PUBLIC: int vi(SCR **); 58 */ 59 int 60 vi(SCR **spp) 61 { 62 GS *gp; 63 MARK abs; 64 SCR *next, *sp; 65 VICMD cmd = { 0 }, *vp; 66 VI_PRIVATE *vip; 67 int comcount, mapped, rval; 68 69 /* Get the first screen. */ 70 sp = *spp; 71 gp = sp->gp; 72 73 /* Point to the command structure. */ 74 vp = &cmd; 75 76 /* Reset strange attraction. */ 77 F_SET(vp, VM_RCM_SET); 78 79 /* Initialize the vi screen. */ 80 if (v_init(sp)) 81 return (1); 82 83 /* Set the focus. */ 84 (void)sp->gp->scr_rename(sp, sp->frp->name, 1); 85 86 for (vip = VIP(sp), rval = 0;;) { 87 /* Resolve messages. */ 88 if (!MAPPED_KEYS_WAITING(sp) && vs_resolve(sp, NULL, 0)) 89 goto ret; 90 91 /* 92 * If not skipping a refresh, return to command mode and 93 * refresh the screen. 94 */ 95 if (F_ISSET(vip, VIP_S_REFRESH)) 96 F_CLR(vip, VIP_S_REFRESH); 97 else { 98 sp->showmode = SM_COMMAND; 99 if (vs_refresh(sp, 0)) 100 goto ret; 101 } 102 103 /* Set the new favorite position. */ 104 if (F_ISSET(vp, VM_RCM_SET | VM_RCM_SETFNB | VM_RCM_SETNNB)) { 105 F_CLR(vip, VIP_RCM_LAST); 106 (void)vs_column(sp, &sp->rcm); 107 } 108 109 /* 110 * If not currently in a map, log the cursor position, 111 * and set a flag so that this command can become the 112 * DOT command. 113 */ 114 if (MAPPED_KEYS_WAITING(sp)) 115 mapped = 1; 116 else { 117 if (log_cursor(sp)) 118 goto err; 119 mapped = 0; 120 } 121 122 /* 123 * There may be an ex command waiting, and we returned here 124 * only because we exited a screen or file. In this case, 125 * we simply go back into the ex parser. 126 */ 127 if (EXCMD_RUNNING(gp)) { 128 vp->kp = &vikeys[':']; 129 goto ex_continue; 130 } 131 132 /* Refresh the command structure. */ 133 memset(vp, 0, sizeof(VICMD)); 134 135 /* 136 * We get a command, which may or may not have an associated 137 * motion. If it does, we get it too, calling its underlying 138 * function to get the resulting mark. We then call the 139 * command setting the cursor to the resulting mark. 140 * 141 * !!! 142 * Vi historically flushed mapped characters on error, but 143 * entering extra <escape> characters at the beginning of 144 * a map wasn't considered an error -- in fact, users would 145 * put leading <escape> characters in maps to clean up vi 146 * state before the map was interpreted. Beauty! 147 */ 148 switch (v_cmd(sp, DOT, vp, NULL, &comcount, &mapped)) { 149 case GC_ERR: 150 goto err; 151 case GC_ERR_NOFLUSH: 152 goto gc_err_noflush; 153 case GC_EVENT: 154 goto gc_event; 155 case GC_FATAL: 156 goto ret; 157 case GC_INTERRUPT: 158 goto intr; 159 case GC_OK: 160 break; 161 } 162 163 /* Check for security setting. */ 164 if (F_ISSET(vp->kp, V_SECURE) && O_ISSET(sp, O_SECURE)) { 165 ex_emsg(sp, KEY_NAME(sp, vp->key), EXM_SECURE); 166 goto err; 167 } 168 169 /* 170 * Historical practice: if a dot command gets a new count, 171 * any motion component goes away, i.e. "d3w2." deletes a 172 * total of 5 words. 173 */ 174 if (F_ISSET(vp, VC_ISDOT) && comcount) 175 DOTMOTION->count = 1; 176 177 /* Copy the key flags into the local structure. */ 178 F_SET(vp, vp->kp->flags); 179 180 /* Prepare to set the previous context. */ 181 if (F_ISSET(vp, V_ABS | V_ABS_C | V_ABS_L)) { 182 abs.lno = sp->lno; 183 abs.cno = sp->cno; 184 } 185 186 /* 187 * Set the three cursor locations to the current cursor. The 188 * underlying routines don't bother if the cursor doesn't move. 189 * This also handles line commands (e.g. Y) defaulting to the 190 * current line. 191 */ 192 vp->m_start.lno = vp->m_stop.lno = vp->m_final.lno = sp->lno; 193 vp->m_start.cno = vp->m_stop.cno = vp->m_final.cno = sp->cno; 194 195 /* 196 * Do any required motion; v_motion sets the from MARK and the 197 * line mode flag, as well as the VM_RCM flags. 198 */ 199 if (F_ISSET(vp, V_MOTION) && 200 v_motion(sp, DOTMOTION, vp, &mapped)) { 201 if (INTERRUPTED(sp)) 202 goto intr; 203 goto err; 204 } 205 206 /* 207 * If a count is set and the command is line oriented, set the 208 * to MARK here relative to the cursor/from MARK. This is for 209 * commands that take both counts and motions, i.e. "4yy" and 210 * "y%". As there's no way the command can know which the user 211 * did, we have to do it here. (There are commands that are 212 * line oriented and that take counts ("#G", "#H"), for which 213 * this calculation is either completely meaningless or wrong. 214 * Each command must validate the value for itself. 215 */ 216 if (F_ISSET(vp, VC_C1SET) && F_ISSET(vp, VM_LMODE)) 217 vp->m_stop.lno += vp->count - 1; 218 219 /* Increment the command count. */ 220 ++sp->ccnt; 221 222 #if defined(DEBUG) && defined(COMLOG) 223 v_comlog(sp, vp); 224 #endif 225 /* Call the function. */ 226 ex_continue: if (vp->kp->func(sp, vp)) 227 goto err; 228 gc_event: 229 #ifdef DEBUG 230 /* Make sure no function left the temporary space locked. */ 231 if (F_ISSET(gp, G_TMP_INUSE)) { 232 F_CLR(gp, G_TMP_INUSE); 233 msgq(sp, M_ERR, 234 "232|vi: temporary buffer not released"); 235 } 236 #endif 237 /* 238 * If we're exiting this screen, move to the next one, or, if 239 * there aren't any more, return to the main editor loop. The 240 * ordering is careful, don't discard the contents of sp until 241 * the end. 242 */ 243 if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE)) { 244 if (file_end(sp, NULL, F_ISSET(sp, SC_EXIT_FORCE))) 245 goto ret; 246 if (vs_discard(sp, &next)) 247 goto ret; 248 if (next == NULL && vs_swap(sp, &next, NULL)) 249 goto ret; 250 *spp = next; 251 if (screen_end(sp)) 252 goto ret; 253 if (next == NULL) 254 break; 255 256 /* Switch screens, change focus. */ 257 sp = next; 258 vip = VIP(sp); 259 (void)sp->gp->scr_rename(sp, sp->frp->name, 1); 260 261 /* Don't trust the cursor. */ 262 F_SET(vip, VIP_CUR_INVALID); 263 264 continue; 265 } 266 267 /* 268 * Set the dot command structure. 269 * 270 * !!! 271 * Historically, commands which used mapped keys did not 272 * set the dot command, with the exception of the text 273 * input commands. 274 */ 275 if (F_ISSET(vp, V_DOT) && !mapped) { 276 *DOT = cmd; 277 F_SET(DOT, VC_ISDOT); 278 279 /* 280 * If a count was supplied for both the command and 281 * its motion, the count was used only for the motion. 282 * Turn the count back on for the dot structure. 283 */ 284 if (F_ISSET(vp, VC_C1RESET)) 285 F_SET(DOT, VC_C1SET); 286 287 /* VM flags aren't retained. */ 288 F_CLR(DOT, VM_COMMASK | VM_RCM_MASK); 289 } 290 291 /* 292 * Some vi row movements are "attracted" to the last position 293 * set, i.e. the VM_RCM commands are moths to the VM_RCM_SET 294 * commands' candle. If the movement is to the EOL the vi 295 * command handles it. If it's to the beginning, we handle it 296 * here. 297 * 298 * Note, some commands (e.g. _, ^) don't set the VM_RCM_SETFNB 299 * flag, but do the work themselves. The reason is that they 300 * have to modify the column in case they're being used as a 301 * motion component. Other similar commands (e.g. +, -) don't 302 * have to modify the column because they are always line mode 303 * operations when used as motions, so the column number isn't 304 * of any interest. 305 * 306 * Does this totally violate the screen and editor layering? 307 * You betcha. As they say, if you think you understand it, 308 * you don't. 309 */ 310 switch (F_ISSET(vp, VM_RCM_MASK)) { 311 case 0: 312 case VM_RCM_SET: 313 break; 314 case VM_RCM: 315 vp->m_final.cno = vs_rcm(sp, 316 vp->m_final.lno, F_ISSET(vip, VIP_RCM_LAST)); 317 break; 318 case VM_RCM_SETLAST: 319 F_SET(vip, VIP_RCM_LAST); 320 break; 321 case VM_RCM_SETFNB: 322 vp->m_final.cno = 0; 323 /* FALLTHROUGH */ 324 case VM_RCM_SETNNB: 325 if (nonblank(sp, vp->m_final.lno, &vp->m_final.cno)) 326 goto err; 327 break; 328 default: 329 abort(); 330 } 331 332 /* Update the cursor. */ 333 sp->lno = vp->m_final.lno; 334 sp->cno = vp->m_final.cno; 335 336 /* 337 * Set the absolute mark -- set even if a tags or similar 338 * command, since the tag may be moving to the same file. 339 */ 340 if ((F_ISSET(vp, V_ABS) || 341 (F_ISSET(vp, V_ABS_L) && sp->lno != abs.lno) || 342 (F_ISSET(vp, V_ABS_C) && 343 (sp->lno != abs.lno || sp->cno != abs.cno))) && 344 mark_set(sp, ABSMARK1, &abs, 1)) 345 goto err; 346 347 if (0) { 348 err: if (v_event_flush(sp, CH_MAPPED)) 349 msgq(sp, M_BERR, 350 "110|Vi command failed: mapped keys discarded"); 351 } 352 353 /* 354 * Check and clear interrupts. There's an obvious race, but 355 * it's not worth fixing. 356 */ 357 gc_err_noflush: if (INTERRUPTED(sp)) { 358 intr: CLR_INTERRUPT(sp); 359 if (v_event_flush(sp, CH_MAPPED)) 360 msgq(sp, M_ERR, 361 "231|Interrupted: mapped keys discarded"); 362 else 363 msgq(sp, M_ERR, "236|Interrupted"); 364 } 365 366 /* If the last command switched screens, update. */ 367 if (F_ISSET(sp, SC_SSWITCH)) { 368 F_CLR(sp, SC_SSWITCH); 369 370 /* 371 * If the current screen is still displayed, it will 372 * need a new status line. 373 */ 374 F_SET(sp, SC_STATUS); 375 376 /* Switch screens, change focus. */ 377 sp = sp->nextdisp; 378 vip = VIP(sp); 379 (void)sp->gp->scr_rename(sp, sp->frp->name, 1); 380 381 /* Don't trust the cursor. */ 382 F_SET(vip, VIP_CUR_INVALID); 383 384 /* Refresh so we can display messages. */ 385 if (vs_refresh(sp, 1)) 386 return (1); 387 } 388 389 /* If the last command switched files, change focus. */ 390 if (F_ISSET(sp, SC_FSWITCH)) { 391 F_CLR(sp, SC_FSWITCH); 392 (void)sp->gp->scr_rename(sp, sp->frp->name, 1); 393 } 394 395 /* If leaving vi, return to the main editor loop. */ 396 if (F_ISSET(gp, G_SRESTART) || F_ISSET(sp, SC_EX)) { 397 *spp = sp; 398 v_dtoh(sp); 399 gp->scr_discard(sp, NULL); 400 break; 401 } 402 } 403 if (0) 404 ret: rval = 1; 405 return (rval); 406 } 407 408 #define KEY(key, ec_flags) do { \ 409 if ((gcret = v_key(sp, 0, &ev, ec_flags)) != GC_OK) \ 410 return (gcret); \ 411 if (ev.e_value == K_ESCAPE) \ 412 goto esc; \ 413 if (F_ISSET(&ev.e_ch, CH_MAPPED)) \ 414 *mappedp = 1; \ 415 key = ev.e_c; \ 416 } while (0) 417 418 /* 419 * The O_TILDEOP option makes the ~ command take a motion instead 420 * of a straight count. This is the replacement structure we use 421 * instead of the one currently in the VIKEYS table. 422 * 423 * XXX 424 * This should probably be deleted -- it's not all that useful, and 425 * we get help messages wrong. 426 */ 427 VIKEYS const tmotion = { 428 v_mulcase, V_CNT|V_DOT|V_MOTION|VM_RCM_SET, 429 "[count]~[count]motion", 430 " ~ change case to motion" 431 }; 432 433 /* 434 * v_cmd -- 435 * 436 * The command structure for vi is less complex than ex (and don't think 437 * I'm not grateful!) The command syntax is: 438 * 439 * [count] [buffer] [count] key [[motion] | [buffer] [character]] 440 * 441 * and there are several special cases. The motion value is itself a vi 442 * command, with the syntax: 443 * 444 * [count] key [character] 445 */ 446 static gcret_t 447 v_cmd( 448 SCR *sp, 449 VICMD *dp, 450 VICMD *vp, 451 VICMD *ismotion, /* Previous key if getting motion component. */ 452 int *comcountp, 453 int *mappedp) 454 { 455 enum { COMMANDMODE, ISPARTIAL, NOTPARTIAL } cpart; 456 EVENT ev; 457 VIKEYS const *kp; 458 gcret_t gcret; 459 u_int flags; 460 CHAR_T key; 461 char *s; 462 463 /* 464 * Get a key. 465 * 466 * <escape> cancels partial commands, i.e. a command where at least 467 * one non-numeric character has been entered. Otherwise, it beeps 468 * the terminal. 469 * 470 * !!! 471 * POSIX 1003.2-1992 explicitly disallows cancelling commands where 472 * all that's been entered is a number, requiring that the terminal 473 * be alerted. 474 */ 475 cpart = ismotion == NULL ? COMMANDMODE : ISPARTIAL; 476 if ((gcret = 477 v_key(sp, ismotion == NULL, &ev, EC_MAPCOMMAND)) != GC_OK) { 478 if (gcret == GC_EVENT) 479 vp->ev = ev; 480 return (gcret); 481 } 482 if (ev.e_value == K_ESCAPE) 483 goto esc; 484 if (F_ISSET(&ev.e_ch, CH_MAPPED)) 485 *mappedp = 1; 486 key = ev.e_c; 487 488 if (ismotion == NULL) 489 cpart = NOTPARTIAL; 490 491 /* Pick up an optional buffer. */ 492 if (key == '"') { 493 cpart = ISPARTIAL; 494 if (ismotion != NULL) { 495 v_emsg(sp, NULL, VIM_COMBUF); 496 return (GC_ERR); 497 } 498 KEY(vp->buffer, 0); 499 F_SET(vp, VC_BUFFER); 500 501 KEY(key, EC_MAPCOMMAND); 502 } 503 504 /* 505 * Pick up an optional count, where a leading 0 is not a count, 506 * it's a command. 507 */ 508 if (ISDIGIT(key) && key != '0') { 509 if (v_count(sp, key, &vp->count)) 510 return (GC_ERR); 511 F_SET(vp, VC_C1SET); 512 *comcountp = 1; 513 514 KEY(key, EC_MAPCOMMAND); 515 } else 516 *comcountp = 0; 517 518 /* Pick up optional buffer. */ 519 if (key == '"') { 520 cpart = ISPARTIAL; 521 if (F_ISSET(vp, VC_BUFFER)) { 522 msgq(sp, M_ERR, "234|Only one buffer may be specified"); 523 return (GC_ERR); 524 } 525 if (ismotion != NULL) { 526 v_emsg(sp, NULL, VIM_COMBUF); 527 return (GC_ERR); 528 } 529 KEY(vp->buffer, 0); 530 F_SET(vp, VC_BUFFER); 531 532 KEY(key, EC_MAPCOMMAND); 533 } 534 535 /* Check for an OOB command key. */ 536 cpart = ISPARTIAL; 537 if (key > MAXVIKEY) { 538 v_emsg(sp, KEY_NAME(sp, key), VIM_NOCOM); 539 return (GC_ERR); 540 } 541 kp = &vikeys[vp->key = key]; 542 543 /* 544 * !!! 545 * Historically, D accepted and then ignored a count. Match it. 546 */ 547 if (vp->key == 'D' && F_ISSET(vp, VC_C1SET)) { 548 *comcountp = 0; 549 vp->count = 0; 550 F_CLR(vp, VC_C1SET); 551 } 552 553 /* Check for command aliases. */ 554 if (kp->func == NULL && (kp = v_alias(sp, vp, kp)) == NULL) 555 return (GC_ERR); 556 557 /* The tildeop option makes the ~ command take a motion. */ 558 if (key == '~' && O_ISSET(sp, O_TILDEOP)) 559 kp = &tmotion; 560 561 vp->kp = kp; 562 563 /* 564 * Find the command. The only legal command with no underlying 565 * function is dot. It's historic practice that <escape> doesn't 566 * just erase the preceding number, it beeps the terminal as well. 567 * It's a common problem, so just beep the terminal unless verbose 568 * was set. 569 */ 570 if (kp->func == NULL) { 571 if (key != '.') { 572 v_emsg(sp, KEY_NAME(sp, key), 573 ev.e_value == K_ESCAPE ? VIM_NOCOM_B : VIM_NOCOM); 574 return (GC_ERR); 575 } 576 577 /* If called for a motion command, stop now. */ 578 if (dp == NULL) 579 goto usage; 580 581 /* 582 * !!! 583 * If a '.' is immediately entered after an undo command, we 584 * replay the log instead of redoing the last command. This 585 * is necessary because 'u' can't set the dot command -- see 586 * vi/v_undo.c:v_undo for details. 587 */ 588 if (VIP(sp)->u_ccnt == sp->ccnt) { 589 vp->kp = &vikeys['u']; 590 F_SET(vp, VC_ISDOT); 591 return (GC_OK); 592 } 593 594 /* Otherwise, a repeatable command must have been executed. */ 595 if (!F_ISSET(dp, VC_ISDOT)) { 596 msgq(sp, M_ERR, "208|No command to repeat"); 597 return (GC_ERR); 598 } 599 600 /* Set new count/buffer, if any, and return. */ 601 if (F_ISSET(vp, VC_C1SET)) { 602 F_SET(dp, VC_C1SET); 603 dp->count = vp->count; 604 } 605 if (F_ISSET(vp, VC_BUFFER)) 606 dp->buffer = vp->buffer; 607 608 *vp = *dp; 609 return (GC_OK); 610 } 611 612 /* Set the flags based on the command flags. */ 613 flags = kp->flags; 614 615 /* Check for illegal count. */ 616 if (F_ISSET(vp, VC_C1SET) && !LF_ISSET(V_CNT)) 617 goto usage; 618 619 /* Illegal motion command. */ 620 if (ismotion == NULL) { 621 /* Illegal buffer. */ 622 if (!LF_ISSET(V_OBUF) && F_ISSET(vp, VC_BUFFER)) 623 goto usage; 624 625 /* Required buffer. */ 626 if (LF_ISSET(V_RBUF)) { 627 KEY(vp->buffer, 0); 628 F_SET(vp, VC_BUFFER); 629 } 630 } 631 632 /* 633 * Special case: '[', ']' and 'Z' commands. Doesn't the fact that 634 * the *single* characters don't mean anything but the *doubled* 635 * characters do, just frost your shorts? 636 */ 637 if (vp->key == '[' || vp->key == ']' || vp->key == 'Z') { 638 /* 639 * Historically, half entered [[, ]] or Z commands weren't 640 * cancelled by <escape>, the terminal was beeped instead. 641 * POSIX.2-1992 probably didn't notice, and requires that 642 * they be cancelled instead of beeping. Seems fine to me. 643 * 644 * Don't set the EC_MAPCOMMAND flag, apparently ] is a popular 645 * vi meta-character, and we don't want the user to wait while 646 * we time out a possible mapping. This *appears* to match 647 * historic vi practice, but with mapping characters, You Just 648 * Never Know. 649 */ 650 KEY(key, 0); 651 652 if (vp->key != key) { 653 usage: if (ismotion == NULL) 654 s = kp->usage; 655 else if (ismotion->key == '~' && O_ISSET(sp, O_TILDEOP)) 656 s = tmotion.usage; 657 else 658 s = vikeys[ismotion->key].usage; 659 v_emsg(sp, s, VIM_USAGE); 660 return (GC_ERR); 661 } 662 } 663 /* Special case: 'z' command. */ 664 if (vp->key == 'z') { 665 KEY(vp->character, 0); 666 if (ISDIGIT(vp->character)) { 667 if (v_count(sp, vp->character, &vp->count2)) 668 return (GC_ERR); 669 F_SET(vp, VC_C2SET); 670 KEY(vp->character, 0); 671 } 672 } 673 674 /* 675 * Commands that have motion components can be doubled to imply the 676 * current line. 677 */ 678 if (ismotion != NULL && ismotion->key != key && !LF_ISSET(V_MOVE)) { 679 msgq(sp, M_ERR, "210|%s may not be used as a motion command", 680 KEY_NAME(sp, key)); 681 return (GC_ERR); 682 } 683 684 /* Pick up required trailing character. */ 685 if (LF_ISSET(V_CHAR)) 686 KEY(vp->character, 0); 687 688 /* Get any associated cursor word. */ 689 if (F_ISSET(kp, V_KEYW) && v_curword(sp)) 690 return (GC_ERR); 691 692 return (GC_OK); 693 694 esc: switch (cpart) { 695 case COMMANDMODE: 696 msgq(sp, M_BERR, "211|Already in command mode"); 697 return (GC_ERR_NOFLUSH); 698 case ISPARTIAL: 699 break; 700 case NOTPARTIAL: 701 (void)sp->gp->scr_bell(sp); 702 break; 703 } 704 return (GC_ERR); 705 } 706 707 /* 708 * v_motion -- 709 * 710 * Get resulting motion mark. 711 */ 712 static int 713 v_motion( 714 SCR *sp, 715 VICMD *dm, 716 VICMD *vp, 717 int *mappedp) 718 { 719 VICMD motion; 720 size_t len; 721 u_long cnt; 722 u_int flags; 723 int tilde_reset, notused; 724 725 /* 726 * If '.' command, use the dot motion, else get the motion command. 727 * Clear any line motion flags, the subsequent motion isn't always 728 * the same, i.e. "/aaa" may or may not be a line motion. 729 */ 730 if (F_ISSET(vp, VC_ISDOT)) { 731 motion = *dm; 732 F_SET(&motion, VC_ISDOT); 733 F_CLR(&motion, VM_COMMASK); 734 } else { 735 memset(&motion, 0, sizeof(VICMD)); 736 if (v_cmd(sp, NULL, &motion, vp, ¬used, mappedp) != GC_OK) 737 return (1); 738 } 739 740 /* 741 * A count may be provided both to the command and to the motion, in 742 * which case the count is multiplicative. For example, "3y4y" is the 743 * same as "12yy". This count is provided to the motion command and 744 * not to the regular function. 745 */ 746 cnt = motion.count = F_ISSET(&motion, VC_C1SET) ? motion.count : 1; 747 if (F_ISSET(vp, VC_C1SET)) { 748 motion.count *= vp->count; 749 F_SET(&motion, VC_C1SET); 750 751 /* 752 * Set flags to restore the original values of the command 753 * structure so dot commands can change the count values, 754 * e.g. "2dw" "3." deletes a total of five words. 755 */ 756 F_CLR(vp, VC_C1SET); 757 F_SET(vp, VC_C1RESET); 758 } 759 760 /* 761 * Some commands can be repeated to indicate the current line. In 762 * this case, or if the command is a "line command", set the flags 763 * appropriately. If not a doubled command, run the function to get 764 * the resulting mark. 765 */ 766 if (vp->key == motion.key) { 767 F_SET(vp, VM_LDOUBLE | VM_LMODE); 768 769 /* Set the origin of the command. */ 770 vp->m_start.lno = sp->lno; 771 vp->m_start.cno = 0; 772 773 /* 774 * Set the end of the command. 775 * 776 * If the current line is missing, i.e. the file is empty, 777 * historic vi permitted a "cc" or "!!" command to insert 778 * text. 779 */ 780 vp->m_stop.lno = sp->lno + motion.count - 1; 781 if (db_get(sp, vp->m_stop.lno, 0, NULL, &len)) { 782 if (vp->m_stop.lno != 1 || 783 (vp->key != 'c' && vp->key != '!')) { 784 v_emsg(sp, NULL, VIM_EMPTY); 785 return (1); 786 } 787 vp->m_stop.cno = 0; 788 } else 789 vp->m_stop.cno = len ? len - 1 : 0; 790 } else { 791 /* 792 * Motion commands change the underlying movement (*snarl*). 793 * For example, "l" is illegal at the end of a line, but "dl" 794 * is not. Set flags so the function knows the situation. 795 */ 796 motion.rkp = vp->kp; 797 798 /* 799 * XXX 800 * Use yank instead of creating a new motion command, it's a 801 * lot easier for now. 802 */ 803 if (vp->kp == &tmotion) { 804 tilde_reset = 1; 805 vp->kp = &vikeys['y']; 806 } else 807 tilde_reset = 0; 808 809 /* 810 * Copy the key flags into the local structure, except for the 811 * RCM flags -- the motion command will set the RCM flags in 812 * the vp structure if necessary. This means that the motion 813 * command is expected to determine where the cursor ends up! 814 * However, we save off the current RCM mask and restore it if 815 * it no RCM flags are set by the motion command, with a small 816 * modification. 817 * 818 * We replace the VM_RCM_SET flag with the VM_RCM flag. This 819 * is so that cursor movement doesn't set the relative position 820 * unless the motion command explicitly specified it. This 821 * appears to match historic practice, but I've never been able 822 * to develop a hard-and-fast rule. 823 */ 824 flags = F_ISSET(vp, VM_RCM_MASK); 825 if (LF_ISSET(VM_RCM_SET)) { 826 LF_SET(VM_RCM); 827 LF_CLR(VM_RCM_SET); 828 } 829 F_CLR(vp, VM_RCM_MASK); 830 F_SET(&motion, motion.kp->flags & ~VM_RCM_MASK); 831 832 /* 833 * Set the three cursor locations to the current cursor. This 834 * permits commands like 'j' and 'k', that are line oriented 835 * motions and have special cursor suck semantics when they are 836 * used as standalone commands, to ignore column positioning. 837 */ 838 motion.m_final.lno = 839 motion.m_stop.lno = motion.m_start.lno = sp->lno; 840 motion.m_final.cno = 841 motion.m_stop.cno = motion.m_start.cno = sp->cno; 842 843 /* Run the function. */ 844 if ((motion.kp->func)(sp, &motion)) 845 return (1); 846 847 /* 848 * If the current line is missing, i.e. the file is empty, 849 * historic vi allowed "c<motion>" or "!<motion>" to insert 850 * text. Otherwise fail -- most motion commands will have 851 * already failed, but some, e.g. G, succeed in empty files. 852 */ 853 if (!db_exist(sp, vp->m_stop.lno)) { 854 if (vp->m_stop.lno != 1 || 855 (vp->key != 'c' && vp->key != '!')) { 856 v_emsg(sp, NULL, VIM_EMPTY); 857 return (1); 858 } 859 vp->m_stop.cno = 0; 860 } 861 862 /* 863 * XXX 864 * See above. 865 */ 866 if (tilde_reset) 867 vp->kp = &tmotion; 868 869 /* 870 * Copy cut buffer, line mode and cursor position information 871 * from the motion command structure, i.e. anything that the 872 * motion command can set for us. The commands can flag the 873 * movement as a line motion (see v_sentence) as well as set 874 * the VM_RCM_* flags explicitly. 875 */ 876 F_SET(vp, F_ISSET(&motion, VM_COMMASK | VM_RCM_MASK)); 877 878 /* 879 * If the motion command set no relative motion flags, use 880 * the (slightly) modified previous values. 881 */ 882 if (!F_ISSET(vp, VM_RCM_MASK)) 883 F_SET(vp, flags); 884 885 /* 886 * Commands can change behaviors based on the motion command 887 * used, for example, the ! command repeated the last bang 888 * command if N or n was used as the motion. 889 */ 890 vp->rkp = motion.kp; 891 892 /* 893 * Motion commands can reset all of the cursor information. 894 * If the motion is in the reverse direction, switch the 895 * from and to MARK's so that it's in a forward direction. 896 * Motions are from the from MARK to the to MARK (inclusive). 897 */ 898 if (motion.m_start.lno > motion.m_stop.lno || 899 (motion.m_start.lno == motion.m_stop.lno && 900 motion.m_start.cno > motion.m_stop.cno)) { 901 vp->m_start = motion.m_stop; 902 vp->m_stop = motion.m_start; 903 } else { 904 vp->m_start = motion.m_start; 905 vp->m_stop = motion.m_stop; 906 } 907 vp->m_final = motion.m_final; 908 } 909 910 /* 911 * If the command sets dot, save the motion structure. The motion 912 * count was changed above and needs to be reset, that's why this 913 * is done here, and not in the calling routine. 914 */ 915 if (F_ISSET(vp->kp, V_DOT)) { 916 *dm = motion; 917 dm->count = cnt; 918 } 919 return (0); 920 } 921 922 /* 923 * v_init -- 924 * Initialize the vi screen. 925 */ 926 static int 927 v_init(SCR *sp) 928 { 929 GS *gp; 930 VI_PRIVATE *vip; 931 932 gp = sp->gp; 933 vip = VIP(sp); 934 935 /* Switch into vi. */ 936 if (gp->scr_screen(sp, SC_VI)) 937 return (1); 938 (void)gp->scr_attr(sp, SA_ALTERNATE, 1); 939 940 F_CLR(sp, SC_EX | SC_SCR_EX); 941 F_SET(sp, SC_VI); 942 943 /* 944 * Initialize screen values. 945 * 946 * Small windows: see vs_refresh(), section 6a. 947 * 948 * Setup: 949 * t_minrows is the minimum rows to display 950 * t_maxrows is the maximum rows to display (rows - 1) 951 * t_rows is the rows currently being displayed 952 */ 953 sp->rows = vip->srows = O_VAL(sp, O_LINES); 954 sp->cols = O_VAL(sp, O_COLUMNS); 955 sp->t_rows = sp->t_minrows = O_VAL(sp, O_WINDOW); 956 if (sp->rows != 1) { 957 if (sp->t_rows > sp->rows - 1) { 958 sp->t_minrows = sp->t_rows = sp->rows - 1; 959 msgq(sp, M_INFO, 960 "214|Windows option value is too large, max is %u", 961 (u_int)sp->t_rows); 962 } 963 sp->t_maxrows = sp->rows - 1; 964 } else 965 sp->t_maxrows = 1; 966 sp->roff = sp->coff = 0; 967 968 /* Create a screen map. */ 969 CALLOC_RET(sp, HMAP, SIZE_HMAP(sp), sizeof(SMAP)); 970 TMAP = HMAP + (sp->t_rows - 1); 971 HMAP->lno = sp->lno; 972 HMAP->coff = 0; 973 HMAP->soff = 1; 974 975 /* 976 * Fill the screen map from scratch -- try and center the line. That 977 * way if we're starting with a file we've seen before, we'll put the 978 * line in the middle, otherwise, it won't work and we'll end up with 979 * the line at the top. 980 */ 981 F_SET(sp, SC_SCR_REFORMAT | SC_SCR_CENTER); 982 983 /* Invalidate the cursor. */ 984 F_SET(vip, VIP_CUR_INVALID); 985 986 /* Paint the screen image from scratch. */ 987 F_SET(vip, VIP_N_EX_PAINT); 988 989 return (0); 990 } 991 992 /* 993 * v_dtoh -- 994 * Move all but the current screen to the hidden queue. 995 */ 996 static void 997 v_dtoh(SCR *sp) 998 { 999 GS *gp; 1000 SCR *tsp; 1001 int hidden; 1002 1003 /* Move all screens to the hidden queue, tossing screen maps. */ 1004 for (hidden = 0, gp = sp->gp; 1005 (tsp = TAILQ_FIRST(gp->dq)) != NULL; ++hidden) { 1006 free(_HMAP(tsp)); 1007 _HMAP(tsp) = NULL; 1008 TAILQ_REMOVE(gp->dq, tsp, q); 1009 TAILQ_INSERT_TAIL(gp->hq, tsp, q); 1010 /* XXXX Change if hidden screens per window */ 1011 gp->scr_discard(tsp, NULL); 1012 } 1013 1014 /* Move current screen back to the display queue. */ 1015 TAILQ_REMOVE(gp->hq, sp, q); 1016 TAILQ_INSERT_TAIL(gp->dq, sp, q); 1017 1018 if (hidden > 1) 1019 msgq(sp, M_INFO, 1020 "319|%d screens backgrounded; use :display to list them", 1021 hidden - 1); 1022 } 1023 1024 /* 1025 * v_curword -- 1026 * Get the word (tagstring, actually) the cursor is on. 1027 * 1028 * PUBLIC: int v_curword(SCR *); 1029 */ 1030 int 1031 v_curword(SCR *sp) 1032 { 1033 VI_PRIVATE *vip; 1034 size_t beg, end, len; 1035 int moved; 1036 CHAR_T *p; 1037 1038 if (db_get(sp, sp->lno, DBG_FATAL, &p, &len)) 1039 return (1); 1040 1041 /* 1042 * !!! 1043 * Historically, tag commands skipped over any leading whitespace 1044 * characters. Make this true in general when using cursor words. 1045 * If movement, getting a cursor word implies moving the cursor to 1046 * its beginning. Refresh now. 1047 * 1048 * !!! 1049 * Find the beginning/end of the keyword. Keywords are currently 1050 * used for cursor-word searching and for tags. Historical vi 1051 * only used the word in a tag search from the cursor to the end 1052 * of the word, i.e. if the cursor was on the 'b' in " abc ", the 1053 * tag was "bc". For consistency, we make cursor word searches 1054 * follow the same rule. 1055 */ 1056 for (moved = 0, 1057 beg = sp->cno; beg < len && ISSPACE(p[beg]); moved = 1, ++beg); 1058 if (beg >= len) { 1059 msgq(sp, M_BERR, "212|Cursor not in a word"); 1060 return (1); 1061 } 1062 if (moved) { 1063 sp->cno = beg; 1064 (void)vs_refresh(sp, 0); 1065 } 1066 1067 /* 1068 * Find the end of the word. 1069 * 1070 * !!! 1071 * Historically, vi accepted any non-blank as initial character 1072 * when building up a tagstring. Required by IEEE 1003.1-2001. 1073 */ 1074 for (end = beg; ++end < len && inword(p[end]);); 1075 1076 vip = VIP(sp); 1077 vip->klen = len = (end - beg); 1078 BINC_RETW(sp, vip->keyw, vip->keywlen, len+1); 1079 MEMMOVE(vip->keyw, p + beg, len); 1080 vip->keyw[len] = '\0'; /* XXX */ 1081 return (0); 1082 } 1083 1084 /* 1085 * v_alias -- 1086 * Check for a command alias. 1087 */ 1088 static VIKEYS const * 1089 v_alias( 1090 SCR *sp, 1091 VICMD *vp, 1092 VIKEYS const *kp) 1093 { 1094 CHAR_T push; 1095 1096 switch (vp->key) { 1097 case 'C': /* C -> c$ */ 1098 push = '$'; 1099 vp->key = 'c'; 1100 break; 1101 case 'D': /* D -> d$ */ 1102 push = '$'; 1103 vp->key = 'd'; 1104 break; 1105 case 'S': /* S -> c_ */ 1106 push = '_'; 1107 vp->key = 'c'; 1108 break; 1109 case 'Y': /* Y -> y_ */ 1110 push = '_'; 1111 vp->key = 'y'; 1112 break; 1113 default: 1114 return (kp); 1115 } 1116 return (v_event_push(sp, 1117 NULL, &push, 1, CH_NOMAP | CH_QUOTED) ? NULL : &vikeys[vp->key]); 1118 } 1119 1120 /* 1121 * v_count -- 1122 * Return the next count. 1123 */ 1124 static int 1125 v_count( 1126 SCR *sp, 1127 ARG_CHAR_T fkey, 1128 u_long *countp) 1129 { 1130 EVENT ev; 1131 u_long count, tc; 1132 1133 ev.e_c = fkey; 1134 count = tc = 0; 1135 do { 1136 /* 1137 * XXX 1138 * Assume that overflow results in a smaller number. 1139 */ 1140 tc = count * 10 + ev.e_c - '0'; 1141 if (count > tc) { 1142 /* Toss to the next non-digit. */ 1143 do { 1144 if (v_key(sp, 0, &ev, 1145 EC_MAPCOMMAND | EC_MAPNODIGIT) != GC_OK) 1146 return (1); 1147 } while (ISDIGIT(ev.e_c)); 1148 msgq(sp, M_ERR, 1149 "235|Number larger than %lu", ULONG_MAX); 1150 return (1); 1151 } 1152 count = tc; 1153 if (v_key(sp, 0, &ev, EC_MAPCOMMAND | EC_MAPNODIGIT) != GC_OK) 1154 return (1); 1155 } while (ISDIGIT(ev.e_c)); 1156 *countp = count; 1157 return (0); 1158 } 1159 1160 /* 1161 * v_key -- 1162 * Return the next event. 1163 */ 1164 static gcret_t 1165 v_key( 1166 SCR *sp, 1167 int command_events, 1168 EVENT *evp, 1169 u_int32_t ec_flags) 1170 { 1171 u_int32_t quote; 1172 1173 for (quote = 0;;) { 1174 if (v_event_get(sp, evp, 0, ec_flags | quote)) 1175 return (GC_FATAL); 1176 quote = 0; 1177 1178 switch (evp->e_event) { 1179 case E_CHARACTER: 1180 /* 1181 * !!! 1182 * Historically, ^V was ignored in the command stream, 1183 * although it had a useful side-effect of interrupting 1184 * mappings. Adding a quoting bit to the call probably 1185 * extends historic practice, but it feels right. 1186 */ 1187 if (evp->e_value == K_VLNEXT) { 1188 quote = EC_QUOTED; 1189 break; 1190 } 1191 return (GC_OK); 1192 case E_ERR: 1193 case E_EOF: 1194 return (GC_FATAL); 1195 case E_INTERRUPT: 1196 /* 1197 * !!! 1198 * Historically, vi beeped on command level interrupts. 1199 * 1200 * Historically, vi exited to ex mode if no file was 1201 * named on the command line, and two interrupts were 1202 * generated in a row. (Just figured you might want 1203 * to know that.) 1204 */ 1205 (void)sp->gp->scr_bell(sp); 1206 return (GC_INTERRUPT); 1207 case E_REPAINT: 1208 if (vs_repaint(sp, evp)) 1209 return (GC_FATAL); 1210 break; 1211 case E_WRESIZE: 1212 return (GC_ERR); 1213 default: 1214 v_event_err(sp, evp); 1215 return (GC_ERR); 1216 } 1217 } 1218 /* NOTREACHED */ 1219 } 1220 1221 #if defined(DEBUG) && defined(COMLOG) 1222 /* 1223 * v_comlog -- 1224 * Log the contents of the command structure. 1225 */ 1226 static void 1227 v_comlog( 1228 SCR *sp, 1229 VICMD *vp) 1230 { 1231 TRACE(sp, "vcmd: "WC, vp->key); 1232 if (F_ISSET(vp, VC_BUFFER)) 1233 TRACE(sp, " buffer: "WC, vp->buffer); 1234 if (F_ISSET(vp, VC_C1SET)) 1235 TRACE(sp, " c1: %lu", vp->count); 1236 if (F_ISSET(vp, VC_C2SET)) 1237 TRACE(sp, " c2: %lu", vp->count2); 1238 TRACE(sp, " flags: 0x%x\n", vp->flags); 1239 } 1240 #endif 1241