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