Merge from vendor branch CVS:
[dragonfly.git] / contrib / nvi / 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[] = "@(#)vi.c  10.57 (Berkeley) 10/13/96";
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 __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 *));
45
46 #if defined(DEBUG) && defined(COMLOG)
47 static void     v_comlog __P((SCR *, VICMD *));
48 #endif
49
50 /*
51  * Side-effect:
52  *      The dot structure can be set by the underlying vi functions,
53  *      see v_Put() and v_put().
54  */
55 #define DOT             (&VIP(sp)->sdot)
56 #define DOTMOTION       (&VIP(sp)->sdotmotion)
57
58 /*
59  * vi --
60  *      Main vi command loop.
61  *
62  * PUBLIC: int vi __P((SCR **));
63  */
64 int
65 vi(spp)
66         SCR **spp;
67 {
68         GS *gp;
69         MARK abs;
70         SCR *next, *sp;
71         VICMD cmd, *vp;
72         VI_PRIVATE *vip;
73         int comcount, mapped, rval;
74
75         /* Get the first screen. */
76         sp = *spp;
77         gp = sp->gp;
78
79         /* Initialize the command structure. */
80         vp = &cmd;
81         memset(vp, 0, sizeof(VICMD));
82
83         /* Reset strange attraction. */
84         F_SET(vp, VM_RCM_SET);
85
86         /* Initialize the vi screen. */
87         if (v_init(sp))
88                 return (1);
89
90         /* Set the focus. */
91         (void)sp->gp->scr_rename(sp, sp->frp->name, 1);
92
93         for (vip = VIP(sp), rval = 0;;) {
94                 /* Resolve messages. */
95                 if (!MAPPED_KEYS_WAITING(sp) && vs_resolve(sp, NULL, 0))
96                         goto ret;
97
98                 /*
99                  * If not skipping a refresh, return to command mode and
100                  * refresh the screen.
101                  */
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;
108                 }
109
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);
114                 }
115
116                 /*
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.
120                  */
121                 if (MAPPED_KEYS_WAITING(sp))
122                         mapped = 1;
123                 else {
124                         if (log_cursor(sp))
125                                 goto err;
126                         mapped = 0;
127                 }
128
129                 /*
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.
133                  */
134                 if (EXCMD_RUNNING(gp)) {
135                         vp->kp = &vikeys[':'];
136                         goto ex_continue;
137                 }
138
139                 /* Refresh the command structure. */
140                 memset(vp, 0, sizeof(VICMD));
141
142                 /*
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.
147                  *
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!
154                  */
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;
170                 }
171
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;
176                 }
177
178                 /*
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.
182                  */
183                 if (F_ISSET(vp, VC_ISDOT) && comcount)
184                         DOTMOTION->count = 1;
185
186                 /* Copy the key flags into the local structure. */
187                 F_SET(vp, vp->kp->flags);
188
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;
193                 }
194
195                 /*
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.
200                  */
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;
203
204                 /*
205                  * Do any required motion; v_motion sets the from MARK and the
206                  * line mode flag, as well as the VM_RCM flags.
207                  */
208                 if (F_ISSET(vp, V_MOTION) &&
209                     v_motion(sp, DOTMOTION, vp, &mapped)) {
210                         if (INTERRUPTED(sp))
211                                 goto intr;
212                         goto err;
213                 }
214
215                 /*
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.
224                  */
225                 if (F_ISSET(vp, VC_C1SET) && F_ISSET(vp, VM_LMODE))
226                         vp->m_stop.lno += vp->count - 1;
227
228                 /* Increment the command count. */
229                 ++sp->ccnt;
230
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");
244                 }
245 #endif
246                 /*
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.
251                  */
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;
264
265                         /* Switch screens, change focus. */
266                         sp = next;
267                         vip = VIP(sp);
268                         (void)sp->gp->scr_rename(sp, sp->frp->name, 1);
269
270                         /* Don't trust the cursor. */
271                         F_SET(vip, VIP_CUR_INVALID);
272
273                         continue;
274                 }
275
276                 /*
277                  * Set the dot command structure.
278                  *
279                  * !!!
280                  * Historically, commands which used mapped keys did not
281                  * set the dot command, with the exception of the text
282                  * input commands.
283                  */
284                 if (F_ISSET(vp, V_DOT) && !mapped) {
285                         *DOT = cmd;
286                         F_SET(DOT, VC_ISDOT);
287
288                         /*
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.
292                          */
293                         if (F_ISSET(vp, VC_C1RESET))
294                                 F_SET(DOT, VC_C1SET);
295
296                         /* VM flags aren't retained. */
297                         F_CLR(DOT, VM_COMMASK | VM_RCM_MASK);
298                 }
299
300                 /*
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.
306                  *
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.
314                  *
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.
318                  */
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();
339                 }
340
341                 /* Update the cursor. */
342                 sp->lno = vp->m_final.lno;
343                 sp->cno = vp->m_final.cno;
344
345                 /*
346                  * Set the absolute mark -- set even if a tags or similar
347                  * command, since the tag may be moving to the same file.
348                  */
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;
355
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");
360                 }
361
362                 /*
363                  * Check and clear interrupts.  There's an obvious race, but
364                  * it's not worth fixing.
365                  */
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");
373                 }
374
375                 /* If the last command switched screens, update. */
376                 if (F_ISSET(sp, SC_SSWITCH)) {
377                         F_CLR(sp, SC_SSWITCH);
378
379                         /*
380                          * If the current screen is still displayed, it will
381                          * need a new status line.
382                          */
383                         F_SET(sp, SC_STATUS);
384
385                         /* Switch screens, change focus. */
386                         sp = sp->nextdisp;
387                         vip = VIP(sp);
388                         (void)sp->gp->scr_rename(sp, sp->frp->name, 1);
389
390                         /* Don't trust the cursor. */
391                         F_SET(vip, VIP_CUR_INVALID);
392
393                         /* Refresh so we can display messages. */
394                         if (vs_refresh(sp, 1))
395                                 return (1);
396                 }
397
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);
402                 }
403
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;
409                 }
410         }
411         if (0)
412 ret:            rval = 1;
413         return (rval);
414 }
415
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;                                                   \
424 }
425
426 /*
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.
430  *
431  * XXX
432  * This should probably be deleted -- it's not all that useful, and
433  * we get help messages wrong.
434  */
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"
439 };
440
441 /*
442  * v_cmd --
443  *
444  * The command structure for vi is less complex than ex (and don't think
445  * I'm not grateful!)  The command syntax is:
446  *
447  *      [count] [buffer] [count] key [[motion] | [buffer] [character]]
448  *
449  * and there are several special cases.  The motion value is itself a vi
450  * command, with the syntax:
451  *
452  *      [count] key [character]
453  */
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;
460 {
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;
468
469         /*
470          * Get a key.
471          *
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.
475          *
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.
480          */
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);
487         }
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;
493
494         if (ismotion == NULL)
495                 cpart = NOTPARTIAL;
496
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);
503                 }
504                 KEY(vp->buffer, 0);
505                 F_SET(vp, VC_BUFFER);
506
507                 KEY(key, EC_MAPCOMMAND);
508         }
509
510         /*
511          * Pick up optional count, where a leading 0 is not a count,
512          * it's a command.
513          */
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;
519
520                 KEY(key, EC_MAPCOMMAND);
521         } else
522                 *comcountp = 0;
523
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);
530                 }
531                 if (ismotion != NULL) {
532                         v_emsg(sp, NULL, VIM_COMBUF);
533                         return (GC_ERR);
534                 }
535                 KEY(vp->buffer, 0);
536                 F_SET(vp, VC_BUFFER);
537
538                 KEY(key, EC_MAPCOMMAND);
539         }
540
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);
546         }
547         kp = &vikeys[vp->key = key];
548
549         /*
550          * !!!
551          * Historically, D accepted and then ignored a count.  Match it.
552          */
553         if (vp->key == 'D' && F_ISSET(vp, VC_C1SET)) {
554                 *comcountp = 0;
555                 vp->count = 0;
556                 F_CLR(vp, VC_C1SET);
557         }
558
559         /* Check for command aliases. */
560         if (kp->func == NULL && (kp = v_alias(sp, vp, kp)) == NULL)
561                 return (GC_ERR);
562
563         /* The tildeop option makes the ~ command take a motion. */
564         if (key == '~' && O_ISSET(sp, O_TILDEOP))
565                 kp = &tmotion;
566
567         vp->kp = kp;
568
569         /*
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.
575          */
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);
581                 }
582
583                 /* If called for a motion command, stop now. */
584                 if (dp == NULL)
585                         goto usage;
586
587                 /*
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.
593                  */
594                 if (VIP(sp)->u_ccnt == sp->ccnt) {
595                         vp->kp = &vikeys['u'];
596                         F_SET(vp, VC_ISDOT);
597                         return (GC_OK);
598                 }
599
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);
604                 }
605
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;
610                 }
611                 if (F_ISSET(vp, VC_BUFFER))
612                         dp->buffer = vp->buffer;
613
614                 *vp = *dp;
615                 return (GC_OK);
616         }
617
618         /* Set the flags based on the command flags. */
619         flags = kp->flags;
620
621         /* Check for illegal count. */
622         if (F_ISSET(vp, VC_C1SET) && !LF_ISSET(V_CNT))
623                 goto usage;
624
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;
630
631                 /* Required buffer. */
632                 if (LF_ISSET(V_RBUF)) {
633                         KEY(vp->buffer, 0);
634                         F_SET(vp, VC_BUFFER);
635                 }
636         }
637
638         /*
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?
642          */
643         if (vp->key == '[' || vp->key == ']' || vp->key == 'Z') {
644                 /*
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.
649                  *
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.
655                  */
656                 KEY(key, 0);
657
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);
667                 }
668         }
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);
677                 }
678         }
679
680         /*
681          * Commands that have motion components can be doubled to
682          * imply the current line.
683          */
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);
688         }
689
690         /* Required character. */
691         if (LF_ISSET(V_CHAR))
692                 KEY(vp->character, 0);
693
694         /* Get any associated cursor word. */
695         if (F_ISSET(kp, V_KEYW) && v_keyword(sp))
696                 return (GC_ERR);
697
698         return (GC_OK);
699
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;
709         }
710         return (GC_ERR);
711 }
712
713 /*
714  * v_motion --
715  *
716  * Get resulting motion mark.
717  */
718 static int
719 v_motion(sp, dm, vp, mappedp)
720         SCR *sp;
721         VICMD *dm, *vp;
722         int *mappedp;
723 {
724         VICMD motion;
725         size_t len;
726         u_long cnt;
727         u_int flags;
728         int tilde_reset, notused;
729
730         /*
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.
734          */
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);
743         }
744
745         /*
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.
750          */
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);
755
756                 /*
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.
760                  */
761                 F_CLR(vp, VC_C1SET);
762                 F_SET(vp, VC_C1RESET);
763         }
764
765         /*
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.
770          */
771         if (vp->key == motion.key) {
772                 F_SET(vp, VM_LDOUBLE | VM_LMODE);
773
774                 /* Set the origin of the command. */
775                 vp->m_start.lno = sp->lno;
776                 vp->m_start.cno = 0;
777
778                 /*
779                  * Set the end of the command.
780                  *
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.
784                  */
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);
791                         }
792                         vp->m_stop.cno = 0;
793                 } else
794                         vp->m_stop.cno = len ? len - 1 : 0;
795         } else {
796                 /*
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.
800                  */
801                 motion.rkp = vp->kp;
802
803                 /*
804                  * XXX
805                  * Use yank instead of creating a new motion command, it's a
806                  * lot easier for now.
807                  */
808                 if (vp->kp == &tmotion) {
809                         tilde_reset = 1;
810                         vp->kp = &vikeys['y'];
811                 } else
812                         tilde_reset = 0;
813
814                 /*
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.
822                  *
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.
828                  */
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);
833                 }
834                 F_CLR(vp, VM_RCM_MASK);
835                 F_SET(&motion, motion.kp->flags & ~VM_RCM_MASK);
836
837                 /*
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.
842                  */
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;
847
848                 /* Run the function. */
849                 if ((motion.kp->func)(sp, &motion))
850                         return (1);
851
852                 /*
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.
857                  */
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);
863                         }
864                         vp->m_stop.cno = 0;
865                 }
866
867                 /*
868                  * XXX
869                  * See above.
870                  */
871                 if (tilde_reset)
872                         vp->kp = &tmotion;
873
874                 /*
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.
880                  */
881                 F_SET(vp, F_ISSET(&motion, VM_COMMASK | VM_RCM_MASK));
882
883                 /*
884                  * If the motion command set no relative motion flags, use
885                  * the (slightly) modified previous values.
886                  */
887                 if (!F_ISSET(vp, VM_RCM_MASK))
888                         F_SET(vp, flags);
889
890                 /*
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.
894                  */
895                 vp->rkp = motion.kp;
896
897                 /*
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).
902                  */
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;
911                 }
912                 vp->m_final = motion.m_final;
913         }
914
915         /*
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.
919          */
920         if (F_ISSET(vp->kp, V_DOT)) {
921                 *dm = motion;
922                 dm->count = cnt;
923         }
924         return (0);
925 }
926
927 /*
928  * v_init --
929  *      Initialize the vi screen.
930  */
931 static int
932 v_init(sp)
933         SCR *sp;
934 {
935         GS *gp;
936         VI_PRIVATE *vip;
937
938         gp = sp->gp;
939         vip = VIP(sp);
940
941         /* Switch into vi. */
942         if (gp->scr_screen(sp, SC_VI))
943                 return (1);
944         (void)gp->scr_attr(sp, SA_ALTERNATE, 1);
945
946         F_CLR(sp, SC_EX | SC_SCR_EX);
947         F_SET(sp, SC_VI);
948
949         /*
950          * Initialize screen values.
951          *
952          * Small windows: see vs_refresh(), section 6a.
953          *
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
958          */
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);
968                 }
969                 sp->t_maxrows = sp->rows - 1;
970         } else
971                 sp->t_maxrows = 1;
972         sp->woff = 0;
973
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;
980
981         /*
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.
986          */
987         F_SET(sp, SC_SCR_REFORMAT | SC_SCR_CENTER);
988
989         /* Invalidate the cursor. */
990         F_SET(vip, VIP_CUR_INVALID);
991
992         /* Paint the screen image from scratch. */
993         F_SET(vip, VIP_N_EX_PAINT);
994
995         return (0);
996 }
997
998 /*
999  * v_dtoh --
1000  *      Move all but the current screen to the hidden queue.
1001  */
1002 static void
1003 v_dtoh(sp)
1004         SCR *sp;
1005 {
1006         GS *gp;
1007         SCR *tsp;
1008         int hidden;
1009
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;
1016                 }
1017                 CIRCLEQ_REMOVE(&gp->dq, tsp, q);
1018                 CIRCLEQ_INSERT_TAIL(&gp->hq, tsp, q);
1019         }
1020
1021         /* Move current screen back to the display queue. */
1022         CIRCLEQ_REMOVE(&gp->hq, sp, q);
1023         CIRCLEQ_INSERT_TAIL(&gp->dq, sp, q);
1024
1025         /*
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
1029          */
1030         if (hidden > 1)
1031                 msgq(sp, M_INFO,
1032                     "%d screens backgrounded; use :display to list them",
1033                     hidden - 1);
1034 }
1035
1036 /*
1037  * v_keyword --
1038  *      Get the word (or non-word) the cursor is on.
1039  */
1040 static int
1041 v_keyword(sp)
1042         SCR *sp;
1043 {
1044         VI_PRIVATE *vip;
1045         size_t beg, end, len;
1046         int moved, state;
1047         char *p;
1048
1049         if (db_get(sp, sp->lno, DBG_FATAL, &p, &len))
1050                 return (1);
1051
1052         /*
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.
1058          *
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.
1066          */
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);
1072         }
1073         if (moved) {
1074                 sp->cno = beg;
1075                 (void)vs_refresh(sp, 0);
1076         }
1077
1078         /* Find the end of the word. */
1079         for (state = inword(p[beg]),
1080             end = beg; ++end < len && state == inword(p[end]););
1081
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);
1088 }
1089
1090 /*
1091  * v_alias --
1092  *      Check for a command alias.
1093  */
1094 static VIKEYS const *
1095 v_alias(sp, vp, kp)
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(sp, fkey, countp)
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(sp, command_events, evp, ec_flags)
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                 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);
1227                 }
1228         }
1229         /* NOTREACHED */
1230 }
1231
1232 #if defined(DEBUG) && defined(COMLOG)
1233 /*
1234  * v_comlog --
1235  *      Log the contents of the command structure.
1236  */
1237 static void
1238 v_comlog(sp, vp)
1239         SCR *sp;
1240         VICMD *vp;
1241 {
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);
1250 }
1251 #endif