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