vi.c revision 302408
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
13static 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
32typedef enum {
33	GC_ERR, GC_ERR_NOFLUSH, GC_EVENT, GC_FATAL, GC_INTERRUPT, GC_OK
34} gcret_t;
35
36static VIKEYS const
37	       *v_alias(SCR *, VICMD *, VIKEYS const *);
38static gcret_t	v_cmd(SCR *, VICMD *, VICMD *, VICMD *, int *, int *);
39static int	v_count(SCR *, ARG_CHAR_T, u_long *);
40static void	v_dtoh(SCR *);
41static int	v_init(SCR *);
42static gcret_t	v_key(SCR *, int, EVENT *, u_int32_t);
43static int	v_motion(SCR *, VICMD *, VICMD *, int *);
44
45#if defined(DEBUG) && defined(COMLOG)
46static 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 */
63int
64vi(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. */
230ex_continue:	if (vp->kp->func(sp, vp))
231			goto err;
232gc_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) {
352err:			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		 */
361gc_err_noflush:	if (INTERRUPTED(sp)) {
362intr:			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)
408ret:		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 */
431VIKEYS 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 */
450static gcret_t
451v_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) {
657usage:			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
698esc:	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 */
716static int
717v_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 */
930static int
931v_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 */
1000static void
1001v_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 */
1036int
1037v_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 */
1094static VIKEYS const *
1095v_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 */
1130static int
1131v_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 */
1170static gcret_t
1171v_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 */
1232static void
1233v_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
1247