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