Remove some more dead initialization.
[dragonfly.git] / contrib / nvi / vi / vi.c
blobd20f7f284e39b68d0024a81824a1b119ef3d7b5a
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[] = "@(#)vi.c 10.57 (Berkeley) 10/13/96";
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 *, 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 *, int, EVENT *, u_int32_t));
43 static int v_keyword __P((SCR *));
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(spp)
66 SCR **spp;
68 GS *gp;
69 MARK abs;
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 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(gp)) {
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_EVENT:
161 if (v_event_exec(sp, vp))
162 goto err;
163 goto gc_event;
164 case GC_FATAL:
165 goto ret;
166 case GC_INTERRUPT:
167 goto intr;
168 case GC_OK:
169 break;
172 /* Check for security setting. */
173 if (F_ISSET(vp->kp, V_SECURE) && O_ISSET(sp, O_SECURE)) {
174 ex_emsg(sp, KEY_NAME(sp, vp->key), EXM_SECURE);
175 goto err;
179 * Historical practice: if a dot command gets a new count,
180 * any motion component goes away, i.e. "d3w2." deletes a
181 * total of 5 words.
183 if (F_ISSET(vp, VC_ISDOT) && comcount)
184 DOTMOTION->count = 1;
186 /* Copy the key flags into the local structure. */
187 F_SET(vp, vp->kp->flags);
189 /* Prepare to set the previous context. */
190 if (F_ISSET(vp, V_ABS | V_ABS_C | V_ABS_L)) {
191 abs.lno = sp->lno;
192 abs.cno = sp->cno;
196 * Set the three cursor locations to the current cursor. The
197 * underlying routines don't bother if the cursor doesn't move.
198 * This also handles line commands (e.g. Y) defaulting to the
199 * current line.
201 vp->m_start.lno = vp->m_stop.lno = vp->m_final.lno = sp->lno;
202 vp->m_start.cno = vp->m_stop.cno = vp->m_final.cno = sp->cno;
205 * Do any required motion; v_motion sets the from MARK and the
206 * line mode flag, as well as the VM_RCM flags.
208 if (F_ISSET(vp, V_MOTION) &&
209 v_motion(sp, DOTMOTION, vp, &mapped)) {
210 if (INTERRUPTED(sp))
211 goto intr;
212 goto err;
216 * If a count is set and the command is line oriented, set the
217 * to MARK here relative to the cursor/from MARK. This is for
218 * commands that take both counts and motions, i.e. "4yy" and
219 * "y%". As there's no way the command can know which the user
220 * did, we have to do it here. (There are commands that are
221 * line oriented and that take counts ("#G", "#H"), for which
222 * this calculation is either completely meaningless or wrong.
223 * Each command must validate the value for itself.
225 if (F_ISSET(vp, VC_C1SET) && F_ISSET(vp, VM_LMODE))
226 vp->m_stop.lno += vp->count - 1;
228 /* Increment the command count. */
229 ++sp->ccnt;
231 #if defined(DEBUG) && defined(COMLOG)
232 v_comlog(sp, vp);
233 #endif
234 /* Call the function. */
235 ex_continue: if (vp->kp->func(sp, vp))
236 goto err;
237 gc_event:
238 #ifdef DEBUG
239 /* Make sure no function left the temporary space locked. */
240 if (F_ISSET(gp, G_TMP_INUSE)) {
241 F_CLR(gp, G_TMP_INUSE);
242 msgq(sp, M_ERR,
243 "232|vi: temporary buffer not released");
245 #endif
247 * If we're exiting this screen, move to the next one, or, if
248 * there aren't any more, return to the main editor loop. The
249 * ordering is careful, don't discard the contents of sp until
250 * the end.
252 if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE)) {
253 if (file_end(sp, NULL, F_ISSET(sp, SC_EXIT_FORCE)))
254 goto ret;
255 if (vs_discard(sp, &next))
256 goto ret;
257 if (next == NULL && vs_swap(sp, &next, NULL))
258 goto ret;
259 *spp = next;
260 if (screen_end(sp))
261 goto ret;
262 if (next == NULL)
263 break;
265 /* Switch screens, change focus. */
266 sp = next;
267 vip = VIP(sp);
268 (void)sp->gp->scr_rename(sp, sp->frp->name, 1);
270 /* Don't trust the cursor. */
271 F_SET(vip, VIP_CUR_INVALID);
273 continue;
277 * Set the dot command structure.
279 * !!!
280 * Historically, commands which used mapped keys did not
281 * set the dot command, with the exception of the text
282 * input commands.
284 if (F_ISSET(vp, V_DOT) && !mapped) {
285 *DOT = cmd;
286 F_SET(DOT, VC_ISDOT);
289 * If a count was supplied for both the command and
290 * its motion, the count was used only for the motion.
291 * Turn the count back on for the dot structure.
293 if (F_ISSET(vp, VC_C1RESET))
294 F_SET(DOT, VC_C1SET);
296 /* VM flags aren't retained. */
297 F_CLR(DOT, VM_COMMASK | VM_RCM_MASK);
301 * Some vi row movements are "attracted" to the last position
302 * set, i.e. the VM_RCM commands are moths to the VM_RCM_SET
303 * commands' candle. If the movement is to the EOL the vi
304 * command handles it. If it's to the beginning, we handle it
305 * here.
307 * Note, some commands (e.g. _, ^) don't set the VM_RCM_SETFNB
308 * flag, but do the work themselves. The reason is that they
309 * have to modify the column in case they're being used as a
310 * motion component. Other similar commands (e.g. +, -) don't
311 * have to modify the column because they are always line mode
312 * operations when used as motions, so the column number isn't
313 * of any interest.
315 * Does this totally violate the screen and editor layering?
316 * You betcha. As they say, if you think you understand it,
317 * you don't.
319 switch (F_ISSET(vp, VM_RCM_MASK)) {
320 case 0:
321 case VM_RCM_SET:
322 break;
323 case VM_RCM:
324 vp->m_final.cno = vs_rcm(sp,
325 vp->m_final.lno, F_ISSET(vip, VIP_RCM_LAST));
326 break;
327 case VM_RCM_SETLAST:
328 F_SET(vip, VIP_RCM_LAST);
329 break;
330 case VM_RCM_SETFNB:
331 vp->m_final.cno = 0;
332 /* FALLTHROUGH */
333 case VM_RCM_SETNNB:
334 if (nonblank(sp, vp->m_final.lno, &vp->m_final.cno))
335 goto err;
336 break;
337 default:
338 abort();
341 /* Update the cursor. */
342 sp->lno = vp->m_final.lno;
343 sp->cno = vp->m_final.cno;
346 * Set the absolute mark -- set even if a tags or similar
347 * command, since the tag may be moving to the same file.
349 if ((F_ISSET(vp, V_ABS) ||
350 F_ISSET(vp, V_ABS_L) && sp->lno != abs.lno ||
351 F_ISSET(vp, V_ABS_C) &&
352 (sp->lno != abs.lno || sp->cno != abs.cno)) &&
353 mark_set(sp, ABSMARK1, &abs, 1))
354 goto err;
356 if (0) {
357 err: if (v_event_flush(sp, CH_MAPPED))
358 msgq(sp, M_BERR,
359 "110|Vi command failed: mapped keys discarded");
363 * Check and clear interrupts. There's an obvious race, but
364 * it's not worth fixing.
366 gc_err_noflush: if (INTERRUPTED(sp)) {
367 intr: CLR_INTERRUPT(sp);
368 if (v_event_flush(sp, CH_MAPPED))
369 msgq(sp, M_ERR,
370 "231|Interrupted: mapped keys discarded");
371 else
372 msgq(sp, M_ERR, "236|Interrupted");
375 /* If the last command switched screens, update. */
376 if (F_ISSET(sp, SC_SSWITCH)) {
377 F_CLR(sp, SC_SSWITCH);
380 * If the current screen is still displayed, it will
381 * need a new status line.
383 F_SET(sp, SC_STATUS);
385 /* Switch screens, change focus. */
386 sp = sp->nextdisp;
387 vip = VIP(sp);
388 (void)sp->gp->scr_rename(sp, sp->frp->name, 1);
390 /* Don't trust the cursor. */
391 F_SET(vip, VIP_CUR_INVALID);
393 /* Refresh so we can display messages. */
394 if (vs_refresh(sp, 1))
395 return (1);
398 /* If the last command switched files, change focus. */
399 if (F_ISSET(sp, SC_FSWITCH)) {
400 F_CLR(sp, SC_FSWITCH);
401 (void)sp->gp->scr_rename(sp, sp->frp->name, 1);
404 /* If leaving vi, return to the main editor loop. */
405 if (F_ISSET(gp, G_SRESTART) || F_ISSET(sp, SC_EX)) {
406 *spp = sp;
407 v_dtoh(sp);
408 break;
411 if (0)
412 ret: rval = 1;
413 return (rval);
416 #define KEY(key, ec_flags) { \
417 if ((gcret = v_key(sp, 0, &ev, ec_flags)) != GC_OK) \
418 return (gcret); \
419 if (ev.e_value == K_ESCAPE) \
420 goto esc; \
421 if (F_ISSET(&ev.e_ch, CH_MAPPED)) \
422 *mappedp = 1; \
423 key = ev.e_c; \
427 * The O_TILDEOP option makes the ~ command take a motion instead
428 * of a straight count. This is the replacement structure we use
429 * instead of the one currently in the VIKEYS table.
431 * XXX
432 * This should probably be deleted -- it's not all that useful, and
433 * we get help messages wrong.
435 VIKEYS const tmotion = {
436 v_mulcase, V_CNT|V_DOT|V_MOTION|VM_RCM_SET,
437 "[count]~[count]motion",
438 " ~ change case to motion"
442 * v_cmd --
444 * The command structure for vi is less complex than ex (and don't think
445 * I'm not grateful!) The command syntax is:
447 * [count] [buffer] [count] key [[motion] | [buffer] [character]]
449 * and there are several special cases. The motion value is itself a vi
450 * command, with the syntax:
452 * [count] key [character]
454 static gcret_t
455 v_cmd(sp, dp, vp, ismotion, comcountp, mappedp)
456 SCR *sp;
457 VICMD *dp, *vp;
458 VICMD *ismotion; /* Previous key if getting motion component. */
459 int *comcountp, *mappedp;
461 enum { COMMANDMODE, ISPARTIAL, NOTPARTIAL } cpart;
462 EVENT ev;
463 VIKEYS const *kp;
464 gcret_t gcret;
465 u_int flags;
466 CHAR_T key;
467 char *s;
470 * Get a key.
472 * <escape> cancels partial commands, i.e. a command where at least
473 * one non-numeric character has been entered. Otherwise, it beeps
474 * the terminal.
476 * !!!
477 * POSIX 1003.2-1992 explicitly disallows cancelling commands where
478 * all that's been entered is a number, requiring that the terminal
479 * be alerted.
481 cpart = ismotion == NULL ? COMMANDMODE : ISPARTIAL;
482 if ((gcret =
483 v_key(sp, ismotion == NULL, &ev, EC_MAPCOMMAND)) != GC_OK) {
484 if (gcret == GC_EVENT)
485 vp->ev = ev;
486 return (gcret);
488 if (ev.e_value == K_ESCAPE)
489 goto esc;
490 if (F_ISSET(&ev.e_ch, CH_MAPPED))
491 *mappedp = 1;
492 key = ev.e_c;
494 if (ismotion == NULL)
495 cpart = NOTPARTIAL;
497 /* Pick up optional buffer. */
498 if (key == '"') {
499 cpart = ISPARTIAL;
500 if (ismotion != NULL) {
501 v_emsg(sp, NULL, VIM_COMBUF);
502 return (GC_ERR);
504 KEY(vp->buffer, 0);
505 F_SET(vp, VC_BUFFER);
507 KEY(key, EC_MAPCOMMAND);
511 * Pick up optional count, where a leading 0 is not a count,
512 * it's a command.
514 if (isdigit(key) && key != '0') {
515 if (v_count(sp, key, &vp->count))
516 return (GC_ERR);
517 F_SET(vp, VC_C1SET);
518 *comcountp = 1;
520 KEY(key, EC_MAPCOMMAND);
521 } else
522 *comcountp = 0;
524 /* Pick up optional buffer. */
525 if (key == '"') {
526 cpart = ISPARTIAL;
527 if (F_ISSET(vp, VC_BUFFER)) {
528 msgq(sp, M_ERR, "234|Only one buffer may be specified");
529 return (GC_ERR);
531 if (ismotion != NULL) {
532 v_emsg(sp, NULL, VIM_COMBUF);
533 return (GC_ERR);
535 KEY(vp->buffer, 0);
536 F_SET(vp, VC_BUFFER);
538 KEY(key, EC_MAPCOMMAND);
541 /* Check for an OOB command key. */
542 cpart = ISPARTIAL;
543 if (key > MAXVIKEY) {
544 v_emsg(sp, KEY_NAME(sp, key), VIM_NOCOM);
545 return (GC_ERR);
547 kp = &vikeys[vp->key = key];
550 * !!!
551 * Historically, D accepted and then ignored a count. Match it.
553 if (vp->key == 'D' && F_ISSET(vp, VC_C1SET)) {
554 *comcountp = 0;
555 vp->count = 0;
556 F_CLR(vp, VC_C1SET);
559 /* Check for command aliases. */
560 if (kp->func == NULL && (kp = v_alias(sp, vp, kp)) == NULL)
561 return (GC_ERR);
563 /* The tildeop option makes the ~ command take a motion. */
564 if (key == '~' && O_ISSET(sp, O_TILDEOP))
565 kp = &tmotion;
567 vp->kp = kp;
570 * Find the command. The only legal command with no underlying
571 * function is dot. It's historic practice that <escape> doesn't
572 * just erase the preceding number, it beeps the terminal as well.
573 * It's a common problem, so just beep the terminal unless verbose
574 * was set.
576 if (kp->func == NULL) {
577 if (key != '.') {
578 v_emsg(sp, KEY_NAME(sp, key),
579 ev.e_value == K_ESCAPE ? VIM_NOCOM_B : VIM_NOCOM);
580 return (GC_ERR);
583 /* If called for a motion command, stop now. */
584 if (dp == NULL)
585 goto usage;
588 * !!!
589 * If a '.' is immediately entered after an undo command, we
590 * replay the log instead of redoing the last command. This
591 * is necessary because 'u' can't set the dot command -- see
592 * vi/v_undo.c:v_undo for details.
594 if (VIP(sp)->u_ccnt == sp->ccnt) {
595 vp->kp = &vikeys['u'];
596 F_SET(vp, VC_ISDOT);
597 return (GC_OK);
600 /* Otherwise, a repeatable command must have been executed. */
601 if (!F_ISSET(dp, VC_ISDOT)) {
602 msgq(sp, M_ERR, "208|No command to repeat");
603 return (GC_ERR);
606 /* Set new count/buffer, if any, and return. */
607 if (F_ISSET(vp, VC_C1SET)) {
608 F_SET(dp, VC_C1SET);
609 dp->count = vp->count;
611 if (F_ISSET(vp, VC_BUFFER))
612 dp->buffer = vp->buffer;
614 *vp = *dp;
615 return (GC_OK);
618 /* Set the flags based on the command flags. */
619 flags = kp->flags;
621 /* Check for illegal count. */
622 if (F_ISSET(vp, VC_C1SET) && !LF_ISSET(V_CNT))
623 goto usage;
625 /* Illegal motion command. */
626 if (ismotion == NULL) {
627 /* Illegal buffer. */
628 if (!LF_ISSET(V_OBUF) && F_ISSET(vp, VC_BUFFER))
629 goto usage;
631 /* Required buffer. */
632 if (LF_ISSET(V_RBUF)) {
633 KEY(vp->buffer, 0);
634 F_SET(vp, VC_BUFFER);
639 * Special case: '[', ']' and 'Z' commands. Doesn't the fact that
640 * the *single* characters don't mean anything but the *doubled*
641 * characters do, just frost your shorts?
643 if (vp->key == '[' || vp->key == ']' || vp->key == 'Z') {
645 * Historically, half entered [[, ]] or Z commands weren't
646 * cancelled by <escape>, the terminal was beeped instead.
647 * POSIX.2-1992 probably didn't notice, and requires that
648 * they be cancelled instead of beeping. Seems fine to me.
650 * Don't set the EC_MAPCOMMAND flag, apparently ] is a popular
651 * vi meta-character, and we don't want the user to wait while
652 * we time out a possible mapping. This *appears* to match
653 * historic vi practice, but with mapping characters, you Just
654 * Never Know.
656 KEY(key, 0);
658 if (vp->key != key) {
659 usage: if (ismotion == NULL)
660 s = kp->usage;
661 else if (ismotion->key == '~' && O_ISSET(sp, O_TILDEOP))
662 s = tmotion.usage;
663 else
664 s = vikeys[ismotion->key].usage;
665 v_emsg(sp, s, VIM_USAGE);
666 return (GC_ERR);
669 /* Special case: 'z' command. */
670 if (vp->key == 'z') {
671 KEY(vp->character, 0);
672 if (isdigit(vp->character)) {
673 if (v_count(sp, vp->character, &vp->count2))
674 return (GC_ERR);
675 F_SET(vp, VC_C2SET);
676 KEY(vp->character, 0);
681 * Commands that have motion components can be doubled to
682 * imply the current line.
684 if (ismotion != NULL && ismotion->key != key && !LF_ISSET(V_MOVE)) {
685 msgq(sp, M_ERR, "210|%s may not be used as a motion command",
686 KEY_NAME(sp, key));
687 return (GC_ERR);
690 /* Required character. */
691 if (LF_ISSET(V_CHAR))
692 KEY(vp->character, 0);
694 /* Get any associated cursor word. */
695 if (F_ISSET(kp, V_KEYW) && v_keyword(sp))
696 return (GC_ERR);
698 return (GC_OK);
700 esc: switch (cpart) {
701 case COMMANDMODE:
702 msgq(sp, M_BERR, "211|Already in command mode");
703 return (GC_ERR_NOFLUSH);
704 case ISPARTIAL:
705 break;
706 case NOTPARTIAL:
707 (void)sp->gp->scr_bell(sp);
708 break;
710 return (GC_ERR);
714 * v_motion --
716 * Get resulting motion mark.
718 static int
719 v_motion(sp, dm, vp, mappedp)
720 SCR *sp;
721 VICMD *dm, *vp;
722 int *mappedp;
724 VICMD motion;
725 size_t len;
726 u_long cnt;
727 u_int flags;
728 int tilde_reset, notused;
731 * If '.' command, use the dot motion, else get the motion command.
732 * Clear any line motion flags, the subsequent motion isn't always
733 * the same, i.e. "/aaa" may or may not be a line motion.
735 if (F_ISSET(vp, VC_ISDOT)) {
736 motion = *dm;
737 F_SET(&motion, VC_ISDOT);
738 F_CLR(&motion, VM_COMMASK);
739 } else {
740 memset(&motion, 0, sizeof(VICMD));
741 if (v_cmd(sp, NULL, &motion, vp, &notused, mappedp) != GC_OK)
742 return (1);
746 * A count may be provided both to the command and to the motion, in
747 * which case the count is multiplicative. For example, "3y4y" is the
748 * same as "12yy". This count is provided to the motion command and
749 * not to the regular function.
751 cnt = motion.count = F_ISSET(&motion, VC_C1SET) ? motion.count : 1;
752 if (F_ISSET(vp, VC_C1SET)) {
753 motion.count *= vp->count;
754 F_SET(&motion, VC_C1SET);
757 * Set flags to restore the original values of the command
758 * structure so dot commands can change the count values,
759 * e.g. "2dw" "3." deletes a total of five words.
761 F_CLR(vp, VC_C1SET);
762 F_SET(vp, VC_C1RESET);
766 * Some commands can be repeated to indicate the current line. In
767 * this case, or if the command is a "line command", set the flags
768 * appropriately. If not a doubled command, run the function to get
769 * the resulting mark.
771 if (vp->key == motion.key) {
772 F_SET(vp, VM_LDOUBLE | VM_LMODE);
774 /* Set the origin of the command. */
775 vp->m_start.lno = sp->lno;
776 vp->m_start.cno = 0;
779 * Set the end of the command.
781 * If the current line is missing, i.e. the file is empty,
782 * historic vi permitted a "cc" or "!!" command to insert
783 * text.
785 vp->m_stop.lno = sp->lno + motion.count - 1;
786 if (db_get(sp, vp->m_stop.lno, 0, NULL, &len)) {
787 if (vp->m_stop.lno != 1 ||
788 vp->key != 'c' && vp->key != '!') {
789 v_emsg(sp, NULL, VIM_EMPTY);
790 return (1);
792 vp->m_stop.cno = 0;
793 } else
794 vp->m_stop.cno = len ? len - 1 : 0;
795 } else {
797 * Motion commands change the underlying movement (*snarl*).
798 * For example, "l" is illegal at the end of a line, but "dl"
799 * is not. Set flags so the function knows the situation.
801 motion.rkp = vp->kp;
804 * XXX
805 * Use yank instead of creating a new motion command, it's a
806 * lot easier for now.
808 if (vp->kp == &tmotion) {
809 tilde_reset = 1;
810 vp->kp = &vikeys['y'];
811 } else
812 tilde_reset = 0;
815 * Copy the key flags into the local structure, except for the
816 * RCM flags -- the motion command will set the RCM flags in
817 * the vp structure if necessary. This means that the motion
818 * command is expected to determine where the cursor ends up!
819 * However, we save off the current RCM mask and restore it if
820 * it no RCM flags are set by the motion command, with a small
821 * modification.
823 * We replace the VM_RCM_SET flag with the VM_RCM flag. This
824 * is so that cursor movement doesn't set the relative position
825 * unless the motion command explicitly specified it. This
826 * appears to match historic practice, but I've never been able
827 * to develop a hard-and-fast rule.
829 flags = F_ISSET(vp, VM_RCM_MASK);
830 if (LF_ISSET(VM_RCM_SET)) {
831 LF_SET(VM_RCM);
832 LF_CLR(VM_RCM_SET);
834 F_CLR(vp, VM_RCM_MASK);
835 F_SET(&motion, motion.kp->flags & ~VM_RCM_MASK);
838 * Set the three cursor locations to the current cursor. This
839 * permits commands like 'j' and 'k', that are line oriented
840 * motions and have special cursor suck semantics when they are
841 * used as standalone commands, to ignore column positioning.
843 motion.m_final.lno =
844 motion.m_stop.lno = motion.m_start.lno = sp->lno;
845 motion.m_final.cno =
846 motion.m_stop.cno = motion.m_start.cno = sp->cno;
848 /* Run the function. */
849 if ((motion.kp->func)(sp, &motion))
850 return (1);
853 * If the current line is missing, i.e. the file is empty,
854 * historic vi allowed "c<motion>" or "!<motion>" to insert
855 * text. Otherwise fail -- most motion commands will have
856 * already failed, but some, e.g. G, succeed in empty files.
858 if (!db_exist(sp, vp->m_stop.lno)) {
859 if (vp->m_stop.lno != 1 ||
860 vp->key != 'c' && vp->key != '!') {
861 v_emsg(sp, NULL, VIM_EMPTY);
862 return (1);
864 vp->m_stop.cno = 0;
868 * XXX
869 * See above.
871 if (tilde_reset)
872 vp->kp = &tmotion;
875 * Copy cut buffer, line mode and cursor position information
876 * from the motion command structure, i.e. anything that the
877 * motion command can set for us. The commands can flag the
878 * movement as a line motion (see v_sentence) as well as set
879 * the VM_RCM_* flags explicitly.
881 F_SET(vp, F_ISSET(&motion, VM_COMMASK | VM_RCM_MASK));
884 * If the motion command set no relative motion flags, use
885 * the (slightly) modified previous values.
887 if (!F_ISSET(vp, VM_RCM_MASK))
888 F_SET(vp, flags);
891 * Commands can change behaviors based on the motion command
892 * used, for example, the ! command repeated the last bang
893 * command if N or n was used as the motion.
895 vp->rkp = motion.kp;
898 * Motion commands can reset all of the cursor information.
899 * If the motion is in the reverse direction, switch the
900 * from and to MARK's so that it's in a forward direction.
901 * Motions are from the from MARK to the to MARK (inclusive).
903 if (motion.m_start.lno > motion.m_stop.lno ||
904 motion.m_start.lno == motion.m_stop.lno &&
905 motion.m_start.cno > motion.m_stop.cno) {
906 vp->m_start = motion.m_stop;
907 vp->m_stop = motion.m_start;
908 } else {
909 vp->m_start = motion.m_start;
910 vp->m_stop = motion.m_stop;
912 vp->m_final = motion.m_final;
916 * If the command sets dot, save the motion structure. The motion
917 * count was changed above and needs to be reset, that's why this
918 * is done here, and not in the calling routine.
920 if (F_ISSET(vp->kp, V_DOT)) {
921 *dm = motion;
922 dm->count = cnt;
924 return (0);
928 * v_init --
929 * Initialize the vi screen.
931 static int
932 v_init(sp)
933 SCR *sp;
935 GS *gp;
936 VI_PRIVATE *vip;
938 gp = sp->gp;
939 vip = VIP(sp);
941 /* Switch into vi. */
942 if (gp->scr_screen(sp, SC_VI))
943 return (1);
944 (void)gp->scr_attr(sp, SA_ALTERNATE, 1);
946 F_CLR(sp, SC_EX | SC_SCR_EX);
947 F_SET(sp, SC_VI);
950 * Initialize screen values.
952 * Small windows: see vs_refresh(), section 6a.
954 * Setup:
955 * t_minrows is the minimum rows to display
956 * t_maxrows is the maximum rows to display (rows - 1)
957 * t_rows is the rows currently being displayed
959 sp->rows = vip->srows = O_VAL(sp, O_LINES);
960 sp->cols = O_VAL(sp, O_COLUMNS);
961 sp->t_rows = sp->t_minrows = O_VAL(sp, O_WINDOW);
962 if (sp->rows != 1) {
963 if (sp->t_rows > sp->rows - 1) {
964 sp->t_minrows = sp->t_rows = sp->rows - 1;
965 msgq(sp, M_INFO,
966 "214|Windows option value is too large, max is %u",
967 sp->t_rows);
969 sp->t_maxrows = sp->rows - 1;
970 } else
971 sp->t_maxrows = 1;
972 sp->woff = 0;
974 /* Create a screen map. */
975 CALLOC_RET(sp, HMAP, SMAP *, SIZE_HMAP(sp), sizeof(SMAP));
976 TMAP = HMAP + (sp->t_rows - 1);
977 HMAP->lno = sp->lno;
978 HMAP->coff = 0;
979 HMAP->soff = 1;
982 * Fill the screen map from scratch -- try and center the line. That
983 * way if we're starting with a file we've seen before, we'll put the
984 * line in the middle, otherwise, it won't work and we'll end up with
985 * the line at the top.
987 F_SET(sp, SC_SCR_REFORMAT | SC_SCR_CENTER);
989 /* Invalidate the cursor. */
990 F_SET(vip, VIP_CUR_INVALID);
992 /* Paint the screen image from scratch. */
993 F_SET(vip, VIP_N_EX_PAINT);
995 return (0);
999 * v_dtoh --
1000 * Move all but the current screen to the hidden queue.
1002 static void
1003 v_dtoh(sp)
1004 SCR *sp;
1006 GS *gp;
1007 SCR *tsp;
1008 int hidden;
1010 /* Move all screens to the hidden queue, tossing screen maps. */
1011 for (hidden = 0, gp = sp->gp;
1012 (tsp = gp->dq.cqh_first) != (void *)&gp->dq; ++hidden) {
1013 if (_HMAP(tsp) != NULL) {
1014 free(_HMAP(tsp));
1015 _HMAP(tsp) = NULL;
1017 CIRCLEQ_REMOVE(&gp->dq, tsp, q);
1018 CIRCLEQ_INSERT_TAIL(&gp->hq, tsp, q);
1021 /* Move current screen back to the display queue. */
1022 CIRCLEQ_REMOVE(&gp->hq, sp, q);
1023 CIRCLEQ_INSERT_TAIL(&gp->dq, sp, q);
1026 * XXX
1027 * Don't bother internationalizing this message, it's going to
1028 * go away as soon as we have one-line screens. --TK
1030 if (hidden > 1)
1031 msgq(sp, M_INFO,
1032 "%d screens backgrounded; use :display to list them",
1033 hidden - 1);
1037 * v_keyword --
1038 * Get the word (or non-word) the cursor is on.
1040 static int
1041 v_keyword(sp)
1042 SCR *sp;
1044 VI_PRIVATE *vip;
1045 size_t beg, end, len;
1046 int moved, state;
1047 char *p;
1049 if (db_get(sp, sp->lno, DBG_FATAL, &p, &len))
1050 return (1);
1053 * !!!
1054 * Historically, tag commands skipped over any leading whitespace
1055 * characters. Make this true in general when using cursor words.
1056 * If movement, getting a cursor word implies moving the cursor to
1057 * its beginning. Refresh now.
1059 * !!!
1060 * Find the beginning/end of the keyword. Keywords are currently
1061 * used for cursor-word searching and for tags. Historical vi
1062 * only used the word in a tag search from the cursor to the end
1063 * of the word, i.e. if the cursor was on the 'b' in " abc ", the
1064 * tag was "bc". For consistency, we make cursor word searches
1065 * follow the same rule.
1067 for (moved = 0,
1068 beg = sp->cno; beg < len && isspace(p[beg]); moved = 1, ++beg);
1069 if (beg >= len) {
1070 msgq(sp, M_BERR, "212|Cursor not in a word");
1071 return (1);
1073 if (moved) {
1074 sp->cno = beg;
1075 (void)vs_refresh(sp, 0);
1078 /* Find the end of the word. */
1079 for (state = inword(p[beg]),
1080 end = beg; ++end < len && state == inword(p[end]););
1082 vip = VIP(sp);
1083 len = (end - beg);
1084 BINC_RET(sp, vip->keyw, vip->klen, len);
1085 memmove(vip->keyw, p + beg, len);
1086 vip->keyw[len] = '\0'; /* XXX */
1087 return (0);
1091 * v_alias --
1092 * Check for a command alias.
1094 static VIKEYS const *
1095 v_alias(sp, vp, kp)
1096 SCR *sp;
1097 VICMD *vp;
1098 VIKEYS const *kp;
1100 CHAR_T push;
1102 switch (vp->key) {
1103 case 'C': /* C -> c$ */
1104 push = '$';
1105 vp->key = 'c';
1106 break;
1107 case 'D': /* D -> d$ */
1108 push = '$';
1109 vp->key = 'd';
1110 break;
1111 case 'S': /* S -> c_ */
1112 push = '_';
1113 vp->key = 'c';
1114 break;
1115 case 'Y': /* Y -> y_ */
1116 push = '_';
1117 vp->key = 'y';
1118 break;
1119 default:
1120 return (kp);
1122 return (v_event_push(sp,
1123 NULL, &push, 1, CH_NOMAP | CH_QUOTED) ? NULL : &vikeys[vp->key]);
1127 * v_count --
1128 * Return the next count.
1130 static int
1131 v_count(sp, fkey, countp)
1132 SCR *sp;
1133 ARG_CHAR_T fkey;
1134 u_long *countp;
1136 EVENT ev;
1137 u_long count, tc;
1139 ev.e_c = fkey;
1140 count = tc = 0;
1141 do {
1143 * XXX
1144 * Assume that overflow results in a smaller number.
1146 tc = count * 10 + ev.e_c - '0';
1147 if (count > tc) {
1148 /* Toss to the next non-digit. */
1149 do {
1150 if (v_key(sp, 0, &ev,
1151 EC_MAPCOMMAND | EC_MAPNODIGIT) != GC_OK)
1152 return (1);
1153 } while (isdigit(ev.e_c));
1154 msgq(sp, M_ERR,
1155 "235|Number larger than %lu", ULONG_MAX);
1156 return (1);
1158 count = tc;
1159 if (v_key(sp, 0, &ev, EC_MAPCOMMAND | EC_MAPNODIGIT) != GC_OK)
1160 return (1);
1161 } while (isdigit(ev.e_c));
1162 *countp = count;
1163 return (0);
1167 * v_key --
1168 * Return the next event.
1170 static gcret_t
1171 v_key(sp, command_events, evp, ec_flags)
1172 SCR *sp;
1173 int command_events;
1174 EVENT *evp;
1175 u_int32_t ec_flags;
1177 u_int32_t quote;
1179 for (quote = 0;;) {
1180 if (v_event_get(sp, evp, 0, ec_flags | quote))
1181 return (GC_FATAL);
1182 quote = 0;
1184 switch (evp->e_event) {
1185 case E_CHARACTER:
1187 * !!!
1188 * Historically, ^V was ignored in the command stream,
1189 * although it had a useful side-effect of interrupting
1190 * mappings. Adding a quoting bit to the call probably
1191 * extends historic practice, but it feels right.
1193 if (evp->e_value == K_VLNEXT) {
1194 quote = EC_QUOTED;
1195 break;
1197 return (GC_OK);
1198 case E_ERR:
1199 case E_EOF:
1200 return (GC_FATAL);
1201 case E_INTERRUPT:
1203 * !!!
1204 * Historically, vi beeped on command level interrupts.
1206 * Historically, vi exited to ex mode if no file was
1207 * named on the command line, and two interrupts were
1208 * generated in a row. (Just figured you might want
1209 * to know that.)
1211 (void)sp->gp->scr_bell(sp);
1212 return (GC_INTERRUPT);
1213 case E_REPAINT:
1214 if (vs_repaint(sp, evp))
1215 return (GC_FATAL);
1216 break;
1217 case E_WRESIZE:
1218 return (GC_ERR);
1219 case E_QUIT:
1220 case E_WRITE:
1221 if (command_events)
1222 return (GC_EVENT);
1223 /* FALLTHROUGH */
1224 default:
1225 v_event_err(sp, evp);
1226 return (GC_ERR);
1229 /* NOTREACHED */
1232 #if defined(DEBUG) && defined(COMLOG)
1234 * v_comlog --
1235 * Log the contents of the command structure.
1237 static void
1238 v_comlog(sp, vp)
1239 SCR *sp;
1240 VICMD *vp;
1242 TRACE(sp, "vcmd: %c", vp->key);
1243 if (F_ISSET(vp, VC_BUFFER))
1244 TRACE(sp, " buffer: %c", vp->buffer);
1245 if (F_ISSET(vp, VC_C1SET))
1246 TRACE(sp, " c1: %lu", vp->count);
1247 if (F_ISSET(vp, VC_C2SET))
1248 TRACE(sp, " c2: %lu", vp->count2);
1249 TRACE(sp, " flags: 0x%x\n", vp->flags);
1251 #endif