tools/llvm: Do not build with symbols
[minix3.git] / external / bsd / nvi / dist / vi / vi.c
blob50f804e1c1ee768530f9d2cdc61e9c4a5bec0572
1 /* $NetBSD: vi.c,v 1.5 2013/12/01 02:34:54 christos Exp $ */
2 /*-
3 * Copyright (c) 1992, 1993, 1994
4 * The Regents of the University of California. All rights reserved.
5 * Copyright (c) 1992, 1993, 1994, 1995, 1996
6 * Keith Bostic. All rights reserved.
8 * See the LICENSE file for redistribution information.
9 */
11 #include "config.h"
13 #ifndef lint
14 static const char sccsid[] = "Id: vi.c,v 10.73 2002/04/11 19:49:30 skimo Exp (Berkeley) Date: 2002/04/11 19:49:30 ";
15 #endif /* not lint */
17 #include <sys/types.h>
18 #include <sys/queue.h>
19 #include <sys/time.h>
21 #include <bitstring.h>
22 #include <ctype.h>
23 #include <errno.h>
24 #include <limits.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
30 #include "../common/common.h"
31 #include "vi.h"
33 typedef enum {
34 GC_ERR, GC_ERR_NOFLUSH, GC_EVENT, GC_FATAL, GC_INTERRUPT, GC_OK
35 } gcret_t;
37 static VIKEYS const
38 *v_alias __P((SCR *, VICMD *, VIKEYS const *));
39 static gcret_t v_cmd __P((SCR *, VICMD *, VICMD *, VICMD *, int *, int *));
40 static int v_count __P((SCR *, VICMD *, ARG_CHAR_T, u_long *));
41 static void v_dtoh __P((SCR *));
42 static int v_init __P((SCR *));
43 static gcret_t v_key __P((SCR *, VICMD *, int, u_int32_t));
44 static int v_motion __P((SCR *, VICMD *, VICMD *, int *));
46 #if defined(DEBUG) && defined(COMLOG)
47 static void v_comlog __P((SCR *, VICMD *));
48 #endif
51 * Side-effect:
52 * The dot structure can be set by the underlying vi functions,
53 * see v_Put() and v_put().
55 #define DOT (&VIP(sp)->sdot)
56 #define DOTMOTION (&VIP(sp)->sdotmotion)
59 * vi --
60 * Main vi command loop.
62 * PUBLIC: int vi __P((SCR **));
64 int
65 vi(SCR **spp)
67 GS *gp;
68 WIN *wp;
69 MARK abst;
70 SCR *next, *sp;
71 VICMD cmd, *vp;
72 VI_PRIVATE *vip;
73 int comcount, mapped, rval;
75 /* Get the first screen. */
76 sp = *spp;
77 wp = sp->wp;
78 gp = sp->gp;
80 /* Initialize the command structure. */
81 vp = &cmd;
82 memset(vp, 0, sizeof(VICMD));
84 /* Reset strange attraction. */
85 F_SET(vp, VM_RCM_SET);
87 /* Initialize the vi screen. */
88 if (v_init(sp))
89 return (1);
91 /* Set the focus. */
92 (void)sp->gp->scr_rename(sp, sp->frp->name, 1);
94 for (vip = VIP(sp), rval = 0;;) {
95 /* Resolve messages. */
96 if (!MAPPED_KEYS_WAITING(sp) && vs_resolve(sp, NULL, 0))
97 goto ret;
100 * If not skipping a refresh, return to command mode and
101 * refresh the screen.
103 if (F_ISSET(vip, VIP_S_REFRESH))
104 F_CLR(vip, VIP_S_REFRESH);
105 else {
106 sp->showmode = SM_COMMAND;
107 if (vs_refresh(sp, 0))
108 goto ret;
111 /* Set the new favorite position. */
112 if (F_ISSET(vp, VM_RCM_SET | VM_RCM_SETFNB | VM_RCM_SETNNB)) {
113 F_CLR(vip, VIP_RCM_LAST);
114 (void)vs_column(sp, &sp->rcm);
118 * If not currently in a map, log the cursor position,
119 * and set a flag so that this command can become the
120 * DOT command.
122 if (MAPPED_KEYS_WAITING(sp))
123 mapped = 1;
124 else {
125 if (log_cursor(sp))
126 goto err;
127 mapped = 0;
131 * There may be an ex command waiting, and we returned here
132 * only because we exited a screen or file. In this case,
133 * we simply go back into the ex parser.
135 if (EXCMD_RUNNING(wp)) {
136 vp->kp = &vikeys[':'];
137 goto ex_continue;
140 /* Refresh the command structure. */
141 memset(vp, 0, sizeof(VICMD));
144 * We get a command, which may or may not have an associated
145 * motion. If it does, we get it too, calling its underlying
146 * function to get the resulting mark. We then call the
147 * command setting the cursor to the resulting mark.
149 * !!!
150 * Vi historically flushed mapped characters on error, but
151 * entering extra <escape> characters at the beginning of
152 * a map wasn't considered an error -- in fact, users would
153 * put leading <escape> characters in maps to clean up vi
154 * state before the map was interpreted. Beauty!
156 switch (v_cmd(sp, DOT, vp, NULL, &comcount, &mapped)) {
157 case GC_ERR:
158 goto err;
159 case GC_ERR_NOFLUSH:
160 goto gc_err_noflush;
161 case GC_FATAL:
162 goto ret;
163 case GC_INTERRUPT:
164 goto intr;
165 case GC_EVENT:
166 case GC_OK:
167 break;
170 /* Check for security setting. */
171 if (F_ISSET(vp->kp, V_SECURE) && O_ISSET(sp, O_SECURE)) {
172 ex_emsg(sp, (const char *)KEY_NAME(sp, vp->key),
173 EXM_SECURE);
174 goto err;
178 * Historical practice: if a dot command gets a new count,
179 * any motion component goes away, i.e. "d3w2." deletes a
180 * total of 5 words.
182 if (F_ISSET(vp, VC_ISDOT) && comcount)
183 DOTMOTION->count = 1;
185 /* Copy the key flags into the local structure. */
186 F_SET(vp, vp->kp->flags);
188 /* Prepare to set the previous context. */
189 if (F_ISSET(vp, V_ABS | V_ABS_C | V_ABS_L)) {
190 abst.lno = sp->lno;
191 abst.cno = sp->cno;
195 * Set the three cursor locations to the current cursor. The
196 * underlying routines don't bother if the cursor doesn't move.
197 * This also handles line commands (e.g. Y) defaulting to the
198 * current line.
200 vp->m_start.lno = vp->m_stop.lno = vp->m_final.lno = sp->lno;
201 vp->m_start.cno = vp->m_stop.cno = vp->m_final.cno = sp->cno;
204 * Do any required motion; v_motion sets the from MARK and the
205 * line mode flag, as well as the VM_RCM flags.
207 if (F_ISSET(vp, V_MOTION) &&
208 v_motion(sp, DOTMOTION, vp, &mapped)) {
209 if (INTERRUPTED(sp))
210 goto intr;
211 goto err;
215 * If a count is set and the command is line oriented, set the
216 * to MARK here relative to the cursor/from MARK. This is for
217 * commands that take both counts and motions, i.e. "4yy" and
218 * "y%". As there's no way the command can know which the user
219 * did, we have to do it here. (There are commands that are
220 * line oriented and that take counts ("#G", "#H"), for which
221 * this calculation is either completely meaningless or wrong.
222 * Each command must validate the value for itself.
224 if (F_ISSET(vp, VC_C1SET) && F_ISSET(vp, VM_LMODE))
225 vp->m_stop.lno += vp->count - 1;
227 /* Increment the command count. */
228 ++sp->ccnt;
230 #if defined(DEBUG) && defined(COMLOG)
231 v_comlog(sp, vp);
232 #endif
233 /* Call the function. */
234 ex_continue: if (vp->kp->func(sp, vp))
235 goto err;
236 #ifdef DEBUG
237 /* Make sure no function left the temporary space locked. */
238 if (F_ISSET(wp, W_TMP_INUSE)) {
239 F_CLR(wp, W_TMP_INUSE);
240 msgq(sp, M_ERR,
241 "232|vi: temporary buffer not released");
243 #endif
245 * If we're exiting this screen, move to the next one, or, if
246 * there aren't any more, return to the main editor loop. The
247 * ordering is careful, don't discard the contents of sp until
248 * the end.
250 if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE)) {
251 if (file_end(sp, NULL, F_ISSET(sp, SC_EXIT_FORCE)))
252 goto ret;
253 if (vs_discard(sp, &next))
254 goto ret;
255 if (next == NULL && vs_swap(sp, &next, NULL))
256 goto ret;
257 *spp = next;
258 if (screen_end(sp))
259 goto ret;
260 if (next == NULL)
261 break;
263 /* Switch screens, change focus. */
264 sp = next;
265 vip = VIP(sp);
266 (void)sp->gp->scr_rename(sp, sp->frp->name, 1);
268 /* Don't trust the cursor. */
269 F_SET(vip, VIP_CUR_INVALID);
271 continue;
275 * Set the dot command structure.
277 * !!!
278 * Historically, commands which used mapped keys did not
279 * set the dot command, with the exception of the text
280 * input commands.
282 if (F_ISSET(vp, V_DOT) && !mapped) {
283 *DOT = cmd;
284 F_SET(DOT, VC_ISDOT);
287 * If a count was supplied for both the command and
288 * its motion, the count was used only for the motion.
289 * Turn the count back on for the dot structure.
291 if (F_ISSET(vp, VC_C1RESET))
292 F_SET(DOT, VC_C1SET);
294 /* VM flags aren't retained. */
295 F_CLR(DOT, VM_COMMASK | VM_RCM_MASK);
299 * Some vi row movements are "attracted" to the last position
300 * set, i.e. the VM_RCM commands are moths to the VM_RCM_SET
301 * commands' candle. If the movement is to the EOL the vi
302 * command handles it. If it's to the beginning, we handle it
303 * here.
305 * Note, some commands (e.g. _, ^) don't set the VM_RCM_SETFNB
306 * flag, but do the work themselves. The reason is that they
307 * have to modify the column in case they're being used as a
308 * motion component. Other similar commands (e.g. +, -) don't
309 * have to modify the column because they are always line mode
310 * operations when used as motions, so the column number isn't
311 * of any interest.
313 * Does this totally violate the screen and editor layering?
314 * You betcha. As they say, if you think you understand it,
315 * you don't.
317 switch (F_ISSET(vp, VM_RCM_MASK)) {
318 case 0:
319 case VM_RCM_SET:
320 break;
321 case VM_RCM:
322 vp->m_final.cno = vs_rcm(sp,
323 vp->m_final.lno, F_ISSET(vip, VIP_RCM_LAST));
324 break;
325 case VM_RCM_SETLAST:
326 F_SET(vip, VIP_RCM_LAST);
327 break;
328 case VM_RCM_SETFNB:
329 vp->m_final.cno = 0;
330 /* FALLTHROUGH */
331 case VM_RCM_SETNNB:
332 if (nonblank(sp, vp->m_final.lno, &vp->m_final.cno))
333 goto err;
334 break;
335 default:
336 abort();
339 /* Update the cursor. */
340 sp->lno = vp->m_final.lno;
341 sp->cno = vp->m_final.cno;
344 * Set the absolute mark -- set even if a tags or similar
345 * command, since the tag may be moving to the same file.
347 if ((F_ISSET(vp, V_ABS) ||
348 (F_ISSET(vp, V_ABS_L) && sp->lno != abst.lno) ||
349 (F_ISSET(vp, V_ABS_C) &&
350 (sp->lno != abst.lno || sp->cno != abst.cno))) &&
351 mark_set(sp, ABSMARK1, &abst, 1))
352 goto err;
354 if (0) {
355 err: if (v_event_flush(sp, CH_MAPPED))
356 msgq(sp, M_BERR,
357 "110|Vi command failed: mapped keys discarded");
361 * Check and clear interrupts. There's an obvious race, but
362 * it's not worth fixing.
364 gc_err_noflush: if (INTERRUPTED(sp)) {
365 intr: CLR_INTERRUPT(sp);
366 if (v_event_flush(sp, CH_MAPPED))
367 msgq(sp, M_ERR,
368 "231|Interrupted: mapped keys discarded");
369 else
370 msgq(sp, M_ERR, "236|Interrupted");
373 /* If the last command switched screens, update. */
374 if (F_ISSET(sp, SC_SSWITCH)) {
375 F_CLR(sp, SC_SSWITCH);
378 * If the current screen is still displayed, it will
379 * need a new status line.
381 F_SET(sp, SC_STATUS);
383 /* Switch screens, change focus. */
384 sp = sp->nextdisp;
385 vip = VIP(sp);
386 (void)sp->gp->scr_rename(sp, sp->frp->name, 1);
388 /* Don't trust the cursor. */
389 F_SET(vip, VIP_CUR_INVALID);
391 /* Refresh so we can display messages. */
392 if (vs_refresh(sp, 1))
393 return (1);
396 /* If the last command switched files, change focus. */
397 if (F_ISSET(sp, SC_FSWITCH)) {
398 F_CLR(sp, SC_FSWITCH);
399 (void)sp->gp->scr_rename(sp, sp->frp->name, 1);
402 /* If leaving vi, return to the main editor loop. */
403 if (F_ISSET(gp, G_SRESTART) || F_ISSET(sp, SC_EX)) {
404 *spp = sp;
405 v_dtoh(sp);
406 gp->scr_discard(sp, NULL);
407 break;
410 if (0)
411 ret: rval = 1;
412 return (rval);
415 #define KEY(key, ec_flags) { \
416 if ((gcret = v_key(sp, vp, 0, ec_flags)) != GC_OK) \
417 return (gcret); \
418 if (vp->ev.e_value == K_ESCAPE) \
419 goto esc; \
420 if (FL_ISSET(vp->ev.e_flags, CH_MAPPED)) \
421 *mappedp = 1; \
422 key = vp->ev.e_c; \
426 * The O_TILDEOP option makes the ~ command take a motion instead
427 * of a straight count. This is the replacement structure we use
428 * instead of the one currently in the VIKEYS table.
430 * XXX
431 * This should probably be deleted -- it's not all that useful, and
432 * we get help messages wrong.
434 VIKEYS const tmotion = {
435 v_mulcase, V_CNT|V_DOT|V_MOTION|VM_RCM_SET,
436 "[count]~[count]motion",
437 " ~ change case to motion"
441 * v_cmd --
442 * Get a vi command.
444 static gcret_t
445 v_cmd(SCR *sp, VICMD *dp, VICMD *vp, VICMD *ismotion, int *comcountp, int *mappedp)
448 /* Previous key if getting motion component. */
451 enum { COMMANDMODE, ISPARTIAL, NOTPARTIAL } cpart;
452 ARG_CHAR_T key;
453 VIKEYS const *kp;
454 gcret_t gcret;
455 u_int flags;
456 const char *s;
459 * Get an event command or a key. Event commands are simple, and
460 * don't have any additional information.
462 cpart = ismotion == NULL ? COMMANDMODE : ISPARTIAL;
463 gcret = v_key(sp, vp, 1, EC_MAPCOMMAND);
464 if (gcret != GC_OK) {
465 if (gcret != GC_EVENT)
466 return (gcret);
467 if (v_event(sp, vp))
468 return (GC_ERR);
469 if (ismotion != NULL && !F_ISSET(vp->kp, V_MOVE))
470 v_event_err(sp, &vp->ev);
471 return (GC_EVENT);
475 * Keys are not simple. (Although vi's command structure less complex
476 * than ex (and don't think I'm not grateful!) The command syntax is:
478 * [count] [buffer] [count] key [[motion] | [buffer] [character]]
480 * and there are, of course, several special cases. The motion value
481 * is itself a vi command, with the syntax:
483 * [count] key [character]
485 * <escape> cancels partial commands, i.e. a command where at least
486 * one non-numeric character has been entered. Otherwise, it beeps
487 * the terminal.
489 * !!!
490 * POSIX 1003.2-1992 explicitly disallows cancelling commands where
491 * all that's been entered is a number, requiring that the terminal
492 * be alerted.
494 if (vp->ev.e_value == K_ESCAPE)
495 goto esc;
498 * Commands that are mapped are treated differently (e.g., they
499 * don't set the dot command. Pass that information back.
501 if (FL_ISSET(vp->ev.e_flags, CH_MAPPED))
502 *mappedp = 1;
503 key = vp->ev.e_c;
505 if (ismotion == NULL)
506 cpart = NOTPARTIAL;
508 /* Pick up an optional buffer. */
509 if (key == '"') {
510 cpart = ISPARTIAL;
511 if (ismotion != NULL) {
512 v_emsg(sp, NULL, VIM_COMBUF);
513 return (GC_ERR);
515 KEY(vp->buffer, 0);
516 F_SET(vp, VC_BUFFER);
518 KEY(key, EC_MAPCOMMAND);
522 * Pick up an optional count, where a leading 0 isn't a count, it's
523 * a command. When a count is specified, the dot command behaves
524 * differently, pass the information back.
526 if (ISDIGIT(key) && key != '0') {
527 if (v_count(sp, vp, key, &vp->count))
528 return (GC_ERR);
530 F_SET(vp, VC_C1SET);
531 *comcountp = 1;
533 KEY(key, EC_MAPCOMMAND);
534 } else
535 *comcountp = 0;
537 /* Pick up optional buffer. */
538 if (key == '"') {
539 cpart = ISPARTIAL;
540 if (F_ISSET(vp, VC_BUFFER)) {
541 msgq(sp, M_ERR, "234|Only one buffer may be specified");
542 return (GC_ERR);
544 if (ismotion != NULL) {
545 v_emsg(sp, NULL, VIM_COMBUF);
546 return (GC_ERR);
548 KEY(vp->buffer, 0);
549 F_SET(vp, VC_BUFFER);
551 KEY(key, EC_MAPCOMMAND);
554 /* Check for an OOB command key. */
555 cpart = ISPARTIAL;
556 if (key > MAXVIKEY) {
557 v_emsg(sp, (const char *)KEY_NAME(sp, key), VIM_NOCOM);
558 return (GC_ERR);
560 kp = &vikeys[vp->key = key];
563 * !!!
564 * Historically, D accepted and then ignored a count. Match it.
566 if (vp->key == 'D' && F_ISSET(vp, VC_C1SET)) {
567 *comcountp = 0;
568 vp->count = 0;
569 F_CLR(vp, VC_C1SET);
573 * There are several commands that we implement as aliases, both
574 * to match historic practice and to ensure consistency. Check
575 * for command aliases.
577 if (kp->func == NULL && (kp = v_alias(sp, vp, kp)) == NULL)
578 return (GC_ERR);
580 /* The tildeop option makes the ~ command take a motion. */
581 if (key == '~' && O_ISSET(sp, O_TILDEOP))
582 kp = &tmotion;
584 vp->kp = kp;
587 * Find the command. The only legal command with no underlying
588 * function is dot. It's historic practice that <escape> doesn't
589 * just erase the preceding number, it beeps the terminal as well.
590 * It's a common problem, so just beep the terminal unless verbose
591 * was set.
593 if (kp->func == NULL) {
594 if (key != '.') {
595 v_emsg(sp, (const char *)KEY_NAME(sp, key),
596 vp->ev.e_value == K_ESCAPE ?
597 VIM_NOCOM_B : VIM_NOCOM);
598 return (GC_ERR);
601 /* If called for a motion command, stop now. */
602 if (dp == NULL)
603 goto usage;
606 * !!!
607 * If a '.' is immediately entered after an undo command, we
608 * replay the log instead of redoing the last command. This
609 * is necessary because 'u' can't set the dot command -- see
610 * vi/v_undo.c:v_undo for details.
612 if (VIP(sp)->u_ccnt == sp->ccnt) {
613 vp->kp = &vikeys['u'];
614 F_SET(vp, VC_ISDOT);
615 return (GC_OK);
618 /* Otherwise, a repeatable command must have been executed. */
619 if (!F_ISSET(dp, VC_ISDOT)) {
620 msgq(sp, M_ERR, "208|No command to repeat");
621 return (GC_ERR);
624 /* Set new count/buffer, if any, and return. */
625 if (F_ISSET(vp, VC_C1SET)) {
626 F_SET(dp, VC_C1SET);
627 dp->count = vp->count;
629 if (F_ISSET(vp, VC_BUFFER))
630 dp->buffer = vp->buffer;
632 *vp = *dp;
633 return (GC_OK);
636 /* Set the flags based on the command flags. */
637 flags = kp->flags;
639 /* Check for illegal count. */
640 if (F_ISSET(vp, VC_C1SET) && !LF_ISSET(V_CNT))
641 goto usage;
643 /* Illegal motion command. */
644 if (ismotion == NULL) {
645 /* Illegal buffer. */
646 if (!LF_ISSET(V_OBUF) && F_ISSET(vp, VC_BUFFER))
647 goto usage;
649 /* Required buffer. */
650 if (LF_ISSET(V_RBUF)) {
651 KEY(vp->buffer, 0);
652 F_SET(vp, VC_BUFFER);
657 * Special case: '[', ']' and 'Z' commands. Doesn't the fact that
658 * the *single* characters don't mean anything but the *doubled*
659 * characters do, just frost your shorts?
661 if (vp->key == '[' || vp->key == ']' || vp->key == 'Z') {
663 * Historically, half entered [[, ]] or Z commands weren't
664 * cancelled by <escape>, the terminal was beeped instead.
665 * POSIX.2-1992 probably didn't notice, and requires that
666 * they be cancelled instead of beeping. Seems fine to me.
668 * Don't set the EC_MAPCOMMAND flag, apparently ] is a popular
669 * vi meta-character, and we don't want the user to wait while
670 * we time out a possible mapping. This *appears* to match
671 * historic vi practice, but with mapping characters, You Just
672 * Never Know.
674 KEY(key, 0);
676 if (vp->key != key) {
677 usage: if (ismotion == NULL)
678 s = kp->usage;
679 else if (ismotion->key == '~' && O_ISSET(sp, O_TILDEOP))
680 s = tmotion.usage;
681 else
682 s = vikeys[ismotion->key].usage;
683 v_emsg(sp, s, VIM_USAGE);
684 return (GC_ERR);
687 /* Special case: 'z' command. */
688 if (vp->key == 'z') {
689 KEY(vp->character, 0);
690 if (ISDIGIT(vp->character)) {
691 if (v_count(sp, vp, vp->character, &vp->count2))
692 return (GC_ERR);
693 F_SET(vp, VC_C2SET);
694 KEY(vp->character, 0);
699 * Commands that have motion components can be doubled to imply the
700 * current line.
702 if (ismotion != NULL && ismotion->key != key && !LF_ISSET(V_MOVE)) {
703 msgq(sp, M_ERR, "210|%s may not be used as a motion command",
704 KEY_NAME(sp, key));
705 return (GC_ERR);
708 /* Pick up required trailing character. */
709 if (LF_ISSET(V_CHAR))
710 KEY(vp->character, 0);
712 /* Get any associated cursor word. */
713 if (F_ISSET(kp, V_KEYW) && v_curword(sp))
714 return (GC_ERR);
716 return (GC_OK);
718 esc: switch (cpart) {
719 case COMMANDMODE:
720 msgq(sp, M_BERR, "211|Already in command mode");
721 return (GC_ERR_NOFLUSH);
722 case ISPARTIAL:
723 break;
724 case NOTPARTIAL:
725 (void)sp->gp->scr_bell(sp);
726 break;
728 return (GC_ERR);
732 * v_motion --
734 * Get resulting motion mark.
736 static int
737 v_motion(SCR *sp, VICMD *dm, VICMD *vp, int *mappedp)
739 VICMD motion;
740 gcret_t gcret;
741 size_t len;
742 u_long cnt;
743 u_int flags;
744 int tilde_reset, notused;
747 * If '.' command, use the dot motion, else get the motion command.
748 * Clear any line motion flags, the subsequent motion isn't always
749 * the same, i.e. "/aaa" may or may not be a line motion.
751 if (F_ISSET(vp, VC_ISDOT)) {
752 motion = *dm;
753 F_SET(&motion, VC_ISDOT);
754 F_CLR(&motion, VM_COMMASK);
755 gcret = GC_OK;
756 } else {
757 memset(&motion, 0, sizeof(VICMD));
758 gcret = v_cmd(sp, NULL, &motion, vp, &notused, mappedp);
759 if (gcret != GC_OK && gcret != GC_EVENT)
760 return (1);
764 * A count may be provided both to the command and to the motion, in
765 * which case the count is multiplicative. For example, "3y4y" is the
766 * same as "12yy". This count is provided to the motion command and
767 * not to the regular function.
769 cnt = motion.count = F_ISSET(&motion, VC_C1SET) ? motion.count : 1;
770 if (F_ISSET(vp, VC_C1SET)) {
771 motion.count *= vp->count;
772 F_SET(&motion, VC_C1SET);
775 * Set flags to restore the original values of the command
776 * structure so dot commands can change the count values,
777 * e.g. "2dw" "3." deletes a total of five words.
779 F_CLR(vp, VC_C1SET);
780 F_SET(vp, VC_C1RESET);
784 * Some commands can be repeated to indicate the current line. In
785 * this case, or if the command is a "line command", set the flags
786 * appropriately. If not a doubled command, run the function to get
787 * the resulting mark.
789 if (gcret != GC_EVENT && vp->key == motion.key) {
790 F_SET(vp, VM_LDOUBLE | VM_LMODE);
792 /* Set the origin of the command. */
793 vp->m_start.lno = sp->lno;
794 vp->m_start.cno = 0;
797 * Set the end of the command.
799 * If the current line is missing, i.e. the file is empty,
800 * historic vi permitted a "cc" or "!!" command to insert
801 * text.
803 vp->m_stop.lno = sp->lno + motion.count - 1;
804 if (db_get(sp, vp->m_stop.lno, 0, NULL, &len)) {
805 if (vp->m_stop.lno != 1 ||
806 (vp->key != 'c' && vp->key != '!')) {
807 v_emsg(sp, NULL, VIM_EMPTY);
808 return (1);
810 vp->m_stop.cno = 0;
811 } else
812 vp->m_stop.cno = len ? len - 1 : 0;
813 } else {
815 * Motion commands change the underlying movement (*snarl*).
816 * For example, "l" is illegal at the end of a line, but "dl"
817 * is not. Set flags so the function knows the situation.
819 motion.rkp = vp->kp;
822 * XXX
823 * Use yank instead of creating a new motion command, it's a
824 * lot easier for now.
826 if (vp->kp == &tmotion) {
827 tilde_reset = 1;
828 vp->kp = &vikeys['y'];
829 } else
830 tilde_reset = 0;
833 * Copy the key flags into the local structure, except for the
834 * RCM flags -- the motion command will set the RCM flags in
835 * the vp structure if necessary. This means that the motion
836 * command is expected to determine where the cursor ends up!
837 * However, we save off the current RCM mask and restore it if
838 * it no RCM flags are set by the motion command, with a small
839 * modification.
841 * We replace the VM_RCM_SET flag with the VM_RCM flag. This
842 * is so that cursor movement doesn't set the relative position
843 * unless the motion command explicitly specified it. This
844 * appears to match historic practice, but I've never been able
845 * to develop a hard-and-fast rule.
847 flags = F_ISSET(vp, VM_RCM_MASK);
848 if (LF_ISSET(VM_RCM_SET)) {
849 LF_SET(VM_RCM);
850 LF_CLR(VM_RCM_SET);
852 F_CLR(vp, VM_RCM_MASK);
853 F_SET(&motion, motion.kp->flags & ~VM_RCM_MASK);
856 * Set the three cursor locations to the current cursor. This
857 * permits commands like 'j' and 'k', that are line oriented
858 * motions and have special cursor suck semantics when they are
859 * used as standalone commands, to ignore column positioning.
861 motion.m_final.lno =
862 motion.m_stop.lno = motion.m_start.lno = sp->lno;
863 motion.m_final.cno =
864 motion.m_stop.cno = motion.m_start.cno = sp->cno;
866 /* Run the function. */
867 if ((motion.kp->func)(sp, &motion))
868 return (1);
871 * If the current line is missing, i.e. the file is empty,
872 * historic vi allowed "c<motion>" or "!<motion>" to insert
873 * text. Otherwise fail -- most motion commands will have
874 * already failed, but some, e.g. G, succeed in empty files.
876 if (!db_exist(sp, vp->m_stop.lno)) {
877 if (vp->m_stop.lno != 1 ||
878 (vp->key != 'c' && vp->key != '!')) {
879 v_emsg(sp, NULL, VIM_EMPTY);
880 return (1);
882 vp->m_stop.cno = 0;
886 * XXX
887 * See above.
889 if (tilde_reset)
890 vp->kp = &tmotion;
893 * Copy cut buffer, line mode and cursor position information
894 * from the motion command structure, i.e. anything that the
895 * motion command can set for us. The commands can flag the
896 * movement as a line motion (see v_sentence) as well as set
897 * the VM_RCM_* flags explicitly.
899 F_SET(vp, F_ISSET(&motion, VM_COMMASK | VM_RCM_MASK));
902 * If the motion command set no relative motion flags, use
903 * the (slightly) modified previous values.
905 if (!F_ISSET(vp, VM_RCM_MASK))
906 F_SET(vp, flags);
909 * Commands can change behaviors based on the motion command
910 * used, for example, the ! command repeated the last bang
911 * command if N or n was used as the motion.
913 vp->rkp = motion.kp;
916 * Motion commands can reset all of the cursor information.
917 * If the motion is in the reverse direction, switch the
918 * from and to MARK's so that it's in a forward direction.
919 * Motions are from the from MARK to the to MARK (inclusive).
921 if (motion.m_start.lno > motion.m_stop.lno ||
922 (motion.m_start.lno == motion.m_stop.lno &&
923 motion.m_start.cno > motion.m_stop.cno)) {
924 vp->m_start = motion.m_stop;
925 vp->m_stop = motion.m_start;
926 } else {
927 vp->m_start = motion.m_start;
928 vp->m_stop = motion.m_stop;
930 vp->m_final = motion.m_final;
934 * If the command sets dot, save the motion structure. The motion
935 * count was changed above and needs to be reset, that's why this
936 * is done here, and not in the calling routine.
938 if (F_ISSET(vp->kp, V_DOT)) {
939 *dm = motion;
940 dm->count = cnt;
942 return (0);
946 * v_init --
947 * Initialize the vi screen.
949 static int
950 v_init(SCR *sp)
952 GS *gp;
953 VI_PRIVATE *vip;
955 gp = sp->gp;
956 vip = VIP(sp);
958 /* Switch into vi. */
959 if (gp->scr_screen(sp, SC_VI))
960 return (1);
961 (void)gp->scr_attr(sp, SA_ALTERNATE, 1);
963 F_CLR(sp, SC_EX | SC_SCR_EX);
964 F_SET(sp, SC_VI);
967 * Initialize screen values.
969 * Small windows: see vs_refresh(), section 6a.
971 * Setup:
972 * t_minrows is the minimum rows to display
973 * t_maxrows is the maximum rows to display (rows - 1)
974 * t_rows is the rows currently being displayed
976 sp->rows = vip->srows = O_VAL(sp, O_LINES);
977 sp->cols = O_VAL(sp, O_COLUMNS);
978 sp->t_rows = sp->t_minrows = O_VAL(sp, O_WINDOW);
979 if (sp->rows != 1) {
980 if (sp->t_rows > sp->rows - 1) {
981 sp->t_minrows = sp->t_rows = sp->rows - 1;
982 msgq(sp, M_INFO,
983 "214|Windows option value is too large, max is %zu",
984 sp->t_rows);
986 sp->t_maxrows = sp->rows - 1;
987 } else
988 sp->t_maxrows = 1;
989 sp->roff = sp->coff = 0;
991 /* Create a screen map. */
992 CALLOC_RET(sp, HMAP, SMAP *, SIZE_HMAP(sp), sizeof(SMAP));
993 TMAP = HMAP + (sp->t_rows - 1);
994 HMAP->lno = sp->lno;
995 HMAP->coff = 0;
996 HMAP->soff = 1;
999 * Fill the screen map from scratch -- try and center the line. That
1000 * way if we're starting with a file we've seen before, we'll put the
1001 * line in the middle, otherwise, it won't work and we'll end up with
1002 * the line at the top.
1004 F_CLR(sp, SC_SCR_TOP);
1005 F_SET(sp, SC_SCR_REFORMAT | SC_SCR_CENTER);
1007 /* Invalidate the cursor. */
1008 F_SET(vip, VIP_CUR_INVALID);
1010 /* Paint the screen image from scratch. */
1011 F_SET(vip, VIP_N_EX_PAINT);
1013 return (0);
1017 * v_dtoh --
1018 * Move all but the current screen to the hidden queue.
1020 static void
1021 v_dtoh(SCR *sp)
1023 GS *gp;
1024 SCR *tsp;
1025 WIN *wp;
1026 int hidden;
1028 /* Move all screens to the hidden queue, tossing screen maps. */
1029 for (hidden = 0, gp = sp->gp, wp = sp->wp;
1030 (tsp = TAILQ_FIRST(&wp->scrq)) != NULL; ++hidden) {
1031 if (_HMAP(tsp) != NULL) {
1032 free(_HMAP(tsp));
1033 _HMAP(tsp) = NULL;
1035 TAILQ_REMOVE(&wp->scrq, tsp, q);
1036 TAILQ_INSERT_TAIL(&gp->hq, tsp, q);
1037 /* XXXX Change if hidden screens per window */
1038 tsp->wp = 0;
1039 gp->scr_discard(tsp, NULL);
1042 /* Move current screen back to the display queue. */
1043 TAILQ_REMOVE(&gp->hq, sp, q);
1044 TAILQ_INSERT_TAIL(&wp->scrq, sp, q);
1045 sp->wp = wp;
1047 if (hidden > 1)
1048 msgq(sp, M_INFO,
1049 "319|%d screens backgrounded; use :display to list them",
1050 hidden - 1);
1054 * v_curword --
1055 * Get the word (tagstring, actually) the cursor is on.
1057 * PUBLIC: int v_curword __P((SCR *));
1060 v_curword(SCR *sp)
1062 VI_PRIVATE *vip;
1063 size_t beg, end, len;
1064 int moved;
1065 CHAR_T *p;
1067 if (db_get(sp, sp->lno, DBG_FATAL, &p, &len))
1068 return (1);
1071 * !!!
1072 * Historically, tag commands skipped over any leading whitespace
1073 * characters. Make this true in general when using cursor words.
1074 * If movement, getting a cursor word implies moving the cursor to
1075 * its beginning. Refresh now.
1077 * !!!
1078 * Find the beginning/end of the keyword. Keywords are currently
1079 * used for cursor-word searching and for tags. Historical vi
1080 * only used the word in a tag search from the cursor to the end
1081 * of the word, i.e. if the cursor was on the 'b' in " abc ", the
1082 * tag was "bc". For consistency, we make cursor word searches
1083 * follow the same rule.
1085 for (moved = 0,
1086 beg = sp->cno; beg < len && ISSPACE((UCHAR_T)p[beg]); moved = 1, ++beg);
1087 if (beg >= len) {
1088 msgq(sp, M_BERR, "212|Cursor not in a word");
1089 return (1);
1091 if (moved) {
1092 sp->cno = beg;
1093 (void)vs_refresh(sp, 0);
1097 * Find the end of the word.
1099 * !!!
1100 * Historically, vi accepted any non-blank as initial character
1101 * when building up a tagstring. Required by IEEE 1003.1-2001.
1103 for (end = beg; ++end < len && inword(p[end]););
1105 vip = VIP(sp);
1106 vip->klen = len = end - beg;
1107 BINC_RETW(sp, vip->keyw, vip->keywlen, len+1);
1108 MEMMOVEW(vip->keyw, p + beg, len);
1109 vip->keyw[len] = L('\0'); /* XXX */
1110 return (0);
1114 * v_alias --
1115 * Check for a command alias.
1117 static VIKEYS const *
1118 v_alias(SCR *sp, VICMD *vp, const VIKEYS *kp)
1120 CHAR_T push;
1122 switch (vp->key) {
1123 case 'C': /* C -> c$ */
1124 push = '$';
1125 vp->key = 'c';
1126 break;
1127 case 'D': /* D -> d$ */
1128 push = '$';
1129 vp->key = 'd';
1130 break;
1131 case 'S': /* S -> c_ */
1132 push = '_';
1133 vp->key = 'c';
1134 break;
1135 case 'Y': /* Y -> y_ */
1136 push = '_';
1137 vp->key = 'y';
1138 break;
1139 default:
1140 return (kp);
1142 return (v_event_push(sp,
1143 NULL, &push, 1, CH_NOMAP | CH_QUOTED) ? NULL : &vikeys[vp->key]);
1147 * v_count --
1148 * Return the next count.
1150 static int
1151 v_count(SCR *sp, VICMD *vp, ARG_CHAR_T fkey, u_long *countp)
1153 u_long count, tc;
1155 vp->ev.e_c = fkey;
1156 count = tc = 0;
1157 do {
1159 * XXX
1160 * Assume that overflow results in a smaller number.
1162 tc = count * 10 + vp->ev.e_c - '0';
1163 if (count > tc) {
1164 /* Toss to the next non-digit. */
1165 do {
1166 if (v_key(sp, vp, 0,
1167 EC_MAPCOMMAND | EC_MAPNODIGIT) != GC_OK)
1168 return (1);
1169 } while (ISDIGIT(vp->ev.e_c));
1170 msgq(sp, M_ERR,
1171 "235|Number larger than %lu", ULONG_MAX);
1172 return (1);
1174 count = tc;
1175 if (v_key(sp, vp, 0, EC_MAPCOMMAND | EC_MAPNODIGIT) != GC_OK)
1176 return (1);
1177 } while (ISDIGIT(vp->ev.e_c));
1178 *countp = count;
1179 return (0);
1183 * v_key --
1184 * Return the next event.
1186 static gcret_t
1187 v_key(SCR *sp, VICMD *vp, int events_ok, u_int32_t ec_flags)
1189 EVENT *evp;
1190 u_int32_t quote;
1192 for (evp = &vp->ev, quote = 0;;) {
1193 if (v_event_get(sp, evp, 0, ec_flags | quote))
1194 return (GC_FATAL);
1195 quote = 0;
1197 switch (evp->e_event) {
1198 case E_CHARACTER:
1200 * !!!
1201 * Historically, ^V was ignored in the command stream,
1202 * although it had a useful side-effect of interrupting
1203 * mappings. Adding a quoting bit to the call probably
1204 * extends historic practice, but it feels right.
1206 if (evp->e_value == K_VLNEXT) {
1207 quote = EC_QUOTED;
1208 break;
1210 return (GC_OK);
1211 case E_ERR:
1212 case E_EOF:
1213 return (GC_FATAL);
1214 case E_INTERRUPT:
1216 * !!!
1217 * Historically, vi beeped on command level interrupts.
1219 * Historically, vi exited to ex mode if no file was
1220 * named on the command line, and two interrupts were
1221 * generated in a row. (I figured you might want to
1222 * know that, just in case there's a quiz later.)
1224 (void)sp->gp->scr_bell(sp);
1225 return (GC_INTERRUPT);
1226 case E_REPAINT:
1227 if (v_erepaint(sp, evp))
1228 return (GC_FATAL);
1229 break;
1230 case E_WRESIZE:
1232 * !!!
1233 * We don't do anything here, just return an error.
1234 * The vi loop will return because of this, and then
1235 * the main loop will realize that we had to restart
1236 * the world and will call the vi loop again.
1238 return (GC_ERR);
1239 case E_IPCOMMAND:
1240 if (events_ok)
1241 return (GC_EVENT);
1242 /* FALLTHROUGH */
1243 default:
1244 v_event_err(sp, evp);
1245 return (GC_ERR);
1248 /* NOTREACHED */
1251 #if defined(DEBUG) && defined(COMLOG)
1253 * v_comlog --
1254 * Log the contents of the command structure.
1256 static void
1257 v_comlog(sp, vp)
1258 SCR *sp;
1259 VICMD *vp;
1261 vtrace(sp, "vcmd: "WC, vp->key);
1262 if (F_ISSET(vp, VC_BUFFER))
1263 vtrace(sp, " buffer: "WC, vp->buffer);
1264 if (F_ISSET(vp, VC_C1SET))
1265 vtrace(sp, " c1: %lu", vp->count);
1266 if (F_ISSET(vp, VC_C2SET))
1267 vtrace(sp, " c2: %lu", vp->count2);
1268 vtrace(sp, " flags: 0x%x\n", vp->flags);
1270 #endif