119304Speter/*-
219304Speter * Copyright (c) 1992, 1993, 1994
319304Speter *	The Regents of the University of California.  All rights reserved.
419304Speter * Copyright (c) 1992, 1993, 1994, 1995, 1996
519304Speter *	Keith Bostic.  All rights reserved.
619304Speter *
719304Speter * See the LICENSE file for redistribution information.
819304Speter *
9254225Speter *	$Id: vi.h,v 10.29 2012/02/11 00:33:46 zy Exp $
1019304Speter */
1119304Speter
1219304Speter/* Definition of a vi "word". */
13254225Speter#define	inword(ch)	((ch) == '_' || (ISGRAPH(ch) && !ISPUNCT(ch)))
1419304Speter
1519304Spetertypedef struct _vikeys VIKEYS;
1619304Speter
1719304Speter/* Structure passed around to functions implementing vi commands. */
1819304Spetertypedef struct _vicmd {
1919304Speter	CHAR_T	key;			/* Command key. */
2019304Speter	CHAR_T	buffer;			/* Buffer. */
2119304Speter	CHAR_T	character;		/* Character. */
2219304Speter	u_long	count;			/* Count. */
2319304Speter	u_long	count2;			/* Second count (only used by z). */
2419304Speter	EVENT	ev;			/* Associated event. */
2519304Speter
2619304Speter#define	ISCMD(p, key)	((p) == &vikeys[key])
2719304Speter	VIKEYS const *kp;		/* Command/Motion VIKEYS entry. */
2819304Speter#define	ISMOTION(vp)	(vp->rkp != NULL && F_ISSET(vp->rkp, V_MOTION))
2919304Speter	VIKEYS const *rkp;		/* Related C/M VIKEYS entry. */
3019304Speter
3119304Speter	/*
3219304Speter	 * Historic vi allowed "dl" when the cursor was on the last column,
3319304Speter	 * deleting the last character, and similarly allowed "dw" when
3419304Speter	 * the cursor was on the last column of the file.  It didn't allow
3519304Speter	 * "dh" when the cursor was on column 1, although these cases are
3619304Speter	 * not strictly analogous.  The point is that some movements would
3719304Speter	 * succeed if they were associated with a motion command, and fail
3819304Speter	 * otherwise.  This is part of the off-by-1 schizophrenia that
3919304Speter	 * plagued vi.  Other examples are that "dfb" deleted everything
4019304Speter	 * up to and including the next 'b' character, while "d/b" deleted
4119304Speter	 * everything up to the next 'b' character.  While this implementation
4219304Speter	 * regularizes the interface to the extent possible, there are many
4319304Speter	 * special cases that can't be fixed.  The special cases are handled
4419304Speter	 * by setting flags per command so that the underlying command and
4519304Speter	 * motion routines know what's really going on.
4619304Speter	 *
4719304Speter	 * The VM_* flags are set in the vikeys array and by the underlying
4819304Speter	 * functions (motion component or command) as well.  For this reason,
4919304Speter	 * the flags in the VICMD and VIKEYS structures live in the same name
5019304Speter	 * space.
5119304Speter	 */
5219304Speter#define	VM_CMDFAILED	0x00000001	/* Command failed. */
5319304Speter#define	VM_CUTREQ	0x00000002	/* Always cut into numeric buffers. */
5419304Speter#define	VM_LDOUBLE	0x00000004	/* Doubled command for line mode. */
5519304Speter#define	VM_LMODE	0x00000008	/* Motion is line oriented. */
5619304Speter#define	VM_COMMASK	0x0000000f	/* Mask for VM flags. */
5719304Speter
5819304Speter	/*
5919304Speter	 * The VM_RCM_* flags are single usage, i.e. if you set one, you have
6019304Speter	 * to clear the others.
6119304Speter	 */
6219304Speter#define	VM_RCM		0x00000010	/* Use relative cursor movment (RCM). */
6319304Speter#define	VM_RCM_SET	0x00000020	/* RCM: set to current position. */
6419304Speter#define	VM_RCM_SETFNB	0x00000040	/* RCM: set to first non-blank (FNB). */
6519304Speter#define	VM_RCM_SETLAST	0x00000080	/* RCM: set to last character. */
6619304Speter#define	VM_RCM_SETNNB	0x00000100	/* RCM: set to next non-blank. */
6719304Speter#define	VM_RCM_MASK	0x000001f0	/* Mask for RCM flags. */
6819304Speter
6919304Speter	/* Flags for the underlying function. */
7019304Speter#define	VC_BUFFER	0x00000200	/* The buffer was set. */
7119304Speter#define	VC_C1RESET	0x00000400	/* Reset C1SET flag for dot commands. */
7219304Speter#define	VC_C1SET	0x00000800	/* Count 1 was set. */
7319304Speter#define	VC_C2SET	0x00001000	/* Count 2 was set. */
7419304Speter#define	VC_ISDOT	0x00002000	/* Command was the dot command. */
7519304Speter	u_int32_t flags;
7619304Speter
7719304Speter	/*
7819304Speter	 * There are four cursor locations that we worry about: the initial
7919304Speter	 * cursor position, the start of the range, the end of the range,
8019304Speter	 * and the final cursor position.  The initial cursor position and
8119304Speter	 * the start of the range are both m_start, and are always the same.
8219304Speter	 * All locations are initialized to the starting cursor position by
8319304Speter	 * the main vi routines, and the underlying functions depend on this.
8419304Speter	 *
8519304Speter	 * Commands that can be motion components set the end of the range
8619304Speter	 * cursor position, m_stop.  All commands must set the ending cursor
8719304Speter	 * position, m_final.  The reason that m_stop isn't the same as m_final
8819304Speter	 * is that there are situations where the final position of the cursor
8919304Speter	 * is outside of the cut/delete range (e.g. 'd[[' from the first column
9019304Speter	 * of a line).  The final cursor position often varies based on the
9119304Speter	 * direction of the movement, as well as the command.  The only special
9219304Speter	 * case that the delete code handles is that it will make adjustments
9319304Speter	 * if the final cursor position is deleted.
9419304Speter	 *
9519304Speter	 * The reason for all of this is that the historic vi semantics were
9619304Speter	 * defined command-by-command.  Every function has to roll its own
9719304Speter	 * starting and stopping positions, and adjust them if it's being used
9819304Speter	 * as a motion component.  The general rules are as follows:
9919304Speter	 *
10019304Speter	 *	1: If not a motion component, the final cursor is at the end
10119304Speter	 *	   of the range.
10219304Speter	 *	2: If moving backward in the file, delete and yank move the
10319304Speter	 *	   final cursor to the end of the range.
10419304Speter	 *	3: If moving forward in the file, delete and yank leave the
10519304Speter	 *	   final cursor at the start of the range.
10619304Speter	 *
10719304Speter	 * Usually, if moving backward in the file and it's a motion component,
10819304Speter	 * the starting cursor is decremented by a single character (or, in a
10919304Speter	 * few cases, to the end of the previous line) so that the starting
11019304Speter	 * cursor character isn't cut or deleted.  No cursor adjustment is
11119304Speter	 * needed for moving forward, because the cut/delete routines handle
11219304Speter	 * m_stop inclusively, i.e. the last character in the range is cut or
11319304Speter	 * deleted.  This makes cutting to the EOF/EOL reasonable.
11419304Speter	 *
11519304Speter	 * The 'c', '<', '>', and '!' commands are special cases.  We ignore
11619304Speter	 * the final cursor position for all of them: for 'c', the text input
11719304Speter	 * routines set the cursor to the last character inserted; for '<',
11819304Speter	 * '>' and '!', the underlying ex commands that do the operation will
11919304Speter	 * set the cursor for us, usually to something related to the first
12019304Speter	 * <nonblank>.
12119304Speter	 */
12219304Speter	MARK	 m_start;		/* mark: initial cursor, range start. */
12319304Speter	MARK	 m_stop;		/* mark: range end. */
12419304Speter	MARK	 m_final;		/* mark: final cursor position. */
12519304Speter} VICMD;
12619304Speter
12719304Speter/* Vi command table structure. */
12819304Speterstruct _vikeys {			/* Underlying function. */
129281373Sbapt	int	 (*func)(SCR *, VICMD *);
13019304Speter#define	V_ABS		0x00004000	/* Absolute movement, set '' mark. */
13119304Speter#define	V_ABS_C		0x00008000	/* V_ABS: if the line/column changed. */
13219304Speter#define	V_ABS_L		0x00010000	/* V_ABS: if the line changed. */
13319304Speter#define	V_CHAR		0x00020000	/* Character (required, trailing). */
13419304Speter#define	V_CNT		0x00040000	/* Count (optional, leading). */
13519304Speter#define	V_DOT		0x00080000	/* On success, sets dot command. */
13619304Speter#define	V_KEYW		0x00100000	/* Cursor referenced word. */
13719304Speter#define	V_MOTION	0x00200000	/* Motion (required, trailing). */
13819304Speter#define	V_MOVE		0x00400000	/* Command defines movement. */
13919304Speter#define	V_OBUF		0x00800000	/* Buffer (optional, leading). */
14019304Speter#define	V_RBUF		0x01000000	/* Buffer (required, trailing). */
14119304Speter#define	V_SECURE	0x02000000	/* Permission denied if O_SECURE set. */
14219304Speter	u_int32_t flags;
14319304Speter	char	*usage;			/* Usage line. */
14419304Speter	char	*help;			/* Help line. */
14519304Speter};
14619304Speter#define	MAXVIKEY	126		/* List of vi commands. */
14719304Speterextern VIKEYS const vikeys[MAXVIKEY + 1];
14819304Speterextern VIKEYS const tmotion;		/* XXX Hacked ~ command. */
14919304Speter
15019304Speter/* Character stream structure, prototypes. */
15119304Spetertypedef struct _vcs {
15219304Speter	recno_t	 cs_lno;		/* Line. */
15319304Speter	size_t	 cs_cno;		/* Column. */
15419304Speter	CHAR_T	*cs_bp;			/* Buffer. */
15519304Speter	size_t	 cs_len;		/* Length. */
15619304Speter	CHAR_T	 cs_ch;			/* Character. */
15719304Speter#define	CS_EMP	1			/* Empty line. */
15819304Speter#define	CS_EOF	2			/* End-of-file. */
15919304Speter#define	CS_EOL	3			/* End-of-line. */
16019304Speter#define	CS_SOF	4			/* Start-of-file. */
16119304Speter	int	 cs_flags;		/* Return flags. */
16219304Speter} VCS;
16319304Speter
164281373Sbaptint	cs_bblank(SCR *, VCS *);
165281373Sbaptint	cs_fblank(SCR *, VCS *);
166281373Sbaptint	cs_fspace(SCR *, VCS *);
167281373Sbaptint	cs_init(SCR *, VCS *);
168281373Sbaptint	cs_next(SCR *, VCS *);
169281373Sbaptint	cs_prev(SCR *, VCS *);
17019304Speter
17119304Speter/*
17219304Speter * We use a single "window" for each set of vi screens.  The model would be
17319304Speter * simpler with two windows (one for the text, and one for the modeline)
17419304Speter * because scrolling the text window down would work correctly then, not
17519304Speter * affecting the mode line.  As it is we have to play games to make it look
17619304Speter * right.  The reason for this choice is that it would be difficult for
17719304Speter * curses to optimize the movement, i.e. detect that the downward scroll
17819304Speter * isn't going to change the modeline, set the scrolling region on the
17919304Speter * terminal and only scroll the first part of the text window.
18019304Speter *
18119304Speter * Structure for mapping lines to the screen.  An SMAP is an array, with one
18219304Speter * structure element per screen line, which holds information describing the
18319304Speter * physical line which is displayed in the screen line.  The first two fields
18419304Speter * (lno and off) are all that are necessary to describe a line.  The rest of
18519304Speter * the information is useful to keep information from being re-calculated.
18619304Speter *
18719304Speter * The SMAP always has an entry for each line of the physical screen, plus a
18819304Speter * slot for the colon command line, so there is room to add any screen into
18919304Speter * another one at screen exit.
19019304Speter *
191254225Speter * Lno is the line number.  If doing the historic vi long line folding, soff
19219304Speter * is the screen offset into the line.  For example, the pair 2:1 would be
19319304Speter * the first screen of line 2, and 2:2 would be the second.  In the case of
19419304Speter * long lines, the screen map will tend to be staggered, e.g., 1:1, 1:2, 1:3,
195254225Speter * 2:1, 3:1, etc.  If doing left-right scrolling, the coff field is the screen
19619304Speter * column offset into the lines, and can take on any value, as it's adjusted
19719304Speter * by the user set value O_SIDESCROLL.
19819304Speter */
19919304Spetertypedef struct _smap {
200254225Speter	recno_t  lno;	/* 1-N: Physical file line number. */
20119304Speter	size_t	 coff;		/* 0-N: Column offset in the line. */
20219304Speter	size_t	 soff;		/* 1-N: Screen offset in the line. */
20319304Speter
20419304Speter				/* vs_line() cache information. */
205254225Speter	size_t	 c_sboff;	/* 0-N: offset of first character on screen. */
206254225Speter	size_t	 c_eboff;	/* 0-N: offset of  last character on screen. */
20719304Speter	u_int8_t c_scoff;	/* 0-N: offset into the first character. */
208254225Speter				/* 255: no character of line visible. */
20919304Speter	u_int8_t c_eclen;	/* 1-N: columns from the last character. */
21019304Speter	u_int8_t c_ecsize;	/* 1-N: size of the last character. */
21119304Speter} SMAP;
21219304Speter				/* Macros to flush/test cached information. */
21319304Speter#define	SMAP_CACHE(smp)		((smp)->c_ecsize != 0)
21419304Speter#define	SMAP_FLUSH(smp)		((smp)->c_ecsize = 0)
21519304Speter
21619304Speter				/* Character search information. */
21719304Spetertypedef enum { CNOTSET, FSEARCH, fSEARCH, TSEARCH, tSEARCH } cdir_t;
21819304Speter
21919304Spetertypedef enum { AB_NOTSET, AB_NOTWORD, AB_INWORD } abb_t;
22019304Spetertypedef enum { Q_NOTSET, Q_BNEXT, Q_BTHIS, Q_VNEXT, Q_VTHIS } quote_t;
22119304Speter
22219304Speter/* Vi private, per-screen memory. */
22319304Spetertypedef struct _vi_private {
22419304Speter	VICMD	cmd;		/* Current command, motion. */
22519304Speter	VICMD	motion;
22619304Speter
22719304Speter	/*
22819304Speter	 * !!!
22919304Speter	 * The saved command structure can be modified by the underlying
23019304Speter	 * vi functions, see v_Put() and v_put().
23119304Speter	 */
23219304Speter	VICMD	sdot;		/* Saved dot, motion command. */
23319304Speter	VICMD	sdotmotion;
23419304Speter
23519304Speter	CHAR_T *keyw;		/* Keyword buffer. */
23619304Speter	size_t	klen;		/* Keyword length. */
23719304Speter	size_t	keywlen;	/* Keyword buffer length. */
23819304Speter
23919304Speter	CHAR_T	rlast;		/* Last 'r' replacement character. */
24019304Speter	e_key_t	rvalue;		/* Value of last replacement character. */
24119304Speter
24219304Speter	EVENT  *rep;		/* Input replay buffer. */
24319304Speter	size_t	rep_len;	/* Input replay buffer length. */
24419304Speter	size_t	rep_cnt;	/* Input replay buffer characters. */
24519304Speter
24619304Speter	mtype_t	mtype;		/* Last displayed message type. */
24719304Speter	size_t	linecount;	/* 1-N: Output overwrite count. */
24819304Speter	size_t	lcontinue;	/* 1-N: Output line continue value. */
24919304Speter	size_t	totalcount;	/* 1-N: Output overwrite count. */
25019304Speter
25119304Speter				/* Busy state. */
25219304Speter	int	busy_ref;	/* Busy reference count. */
25319304Speter	int	busy_ch;	/* Busy character. */
25419304Speter	size_t	busy_fx;	/* Busy character x coordinate. */
25519304Speter	size_t	busy_oldy;	/* Saved y coordinate. */
25619304Speter	size_t	busy_oldx;	/* Saved x coordinate. */
257254225Speter	struct timespec busy_ts;/* Busy timer. */
25819304Speter
259254225Speter	MARK	sel;		/* Select start position. */
260254225Speter
261254225Speter	CHAR_T *mcs;		/* Match character list. */
26219304Speter	char   *ps;		/* Paragraph plus section list. */
26319304Speter
26419304Speter	u_long	u_ccnt;		/* Undo command count. */
26519304Speter
26619304Speter	CHAR_T	lastckey;	/* Last search character. */
26719304Speter	cdir_t	csearchdir;	/* Character search direction. */
26819304Speter
26919304Speter	SMAP   *h_smap;		/* First slot of the line map. */
27019304Speter	SMAP   *t_smap;		/* Last slot of the line map. */
27119304Speter
27219304Speter	/*
27319304Speter	 * One extra slot is always allocated for the map so that we can use
27419304Speter	 * it to do vi :colon command input; see v_tcmd().
27519304Speter	 */
27619304Speter	recno_t	sv_tm_lno;	/* tcmd: saved TMAP lno field. */
27719304Speter	size_t	sv_tm_coff;	/* tcmd: saved TMAP coff field. */
27819304Speter	size_t	sv_tm_soff;	/* tcmd: saved TMAP soff field. */
27919304Speter	size_t	sv_t_maxrows;	/* tcmd: saved t_maxrows. */
28019304Speter	size_t	sv_t_minrows;	/* tcmd: saved t_minrows. */
28119304Speter	size_t	sv_t_rows;	/* tcmd: saved t_rows. */
28219304Speter#define	SIZE_HMAP(sp)	(VIP(sp)->srows + 1)
28319304Speter
28419304Speter	/*
28519304Speter	 * Macros to get to the head/tail of the smap.  If the screen only has
28619304Speter	 * one line, HMAP can be equal to TMAP, so the code has to understand
28719304Speter	 * the off-by-one errors that can result.  If stepping through an SMAP
28819304Speter	 * and operating on each entry, use sp->t_rows as the count of slots,
28919304Speter	 * don't use a loop that compares <= TMAP.
29019304Speter	 */
29119304Speter#define	_HMAP(sp)	(VIP(sp)->h_smap)
29219304Speter#define	HMAP		_HMAP(sp)
29319304Speter#define	_TMAP(sp)	(VIP(sp)->t_smap)
29419304Speter#define	TMAP		_TMAP(sp)
29519304Speter
29619304Speter	recno_t	ss_lno;	/* 1-N: vi_opt_screens cached line number. */
29719304Speter	size_t	ss_screens;	/* vi_opt_screens cached return value. */
29819304Speter#define	VI_SCR_CFLUSH(vip)	vip->ss_lno = OOBLNO
29919304Speter
30019304Speter	size_t	srows;		/* 1-N: rows in the terminal/window. */
30119304Speter	recno_t	olno;		/* 1-N: old cursor file line. */
30219304Speter	size_t	ocno;		/* 0-N: old file cursor column. */
30319304Speter	size_t	sc_col;		/* 0-N: LOGICAL screen column. */
30419304Speter	SMAP   *sc_smap;	/* SMAP entry where sc_col occurs. */
30519304Speter
30619304Speter#define	VIP_CUR_INVALID	0x0001	/* Cursor position is unknown. */
30719304Speter#define	VIP_DIVIDER	0x0002	/* Divider line was displayed. */
30819304Speter#define	VIP_N_EX_PAINT	0x0004	/* Clear and repaint when ex finishes. */
30919304Speter#define	VIP_N_EX_REDRAW	0x0008	/* Schedule SC_SCR_REDRAW when ex finishes. */
31019304Speter#define	VIP_N_REFRESH	0x0010	/* Repaint (from SMAP) on the next refresh. */
31119304Speter#define	VIP_N_RENUMBER	0x0020	/* Renumber screen on the next refresh. */
31219304Speter#define	VIP_RCM_LAST	0x0040	/* Cursor drawn to the last column. */
31319304Speter#define	VIP_S_MODELINE	0x0080	/* Skip next modeline refresh. */
31419304Speter#define	VIP_S_REFRESH	0x0100	/* Skip next refresh. */
31519304Speter	u_int16_t flags;
31619304Speter} VI_PRIVATE;
31719304Speter
31819304Speter/* Vi private area. */
31919304Speter#define	VIP(sp)	((VI_PRIVATE *)((sp)->vi_private))
32019304Speter
32119304Speter#define	O_NUMBER_FMT	"%7lu "			/* O_NUMBER format, length. */
32219304Speter#define	O_NUMBER_LENGTH	8
32319304Speter#define	SCREEN_COLS(sp)				/* Screen columns. */	\
32419304Speter	((O_ISSET(sp, O_NUMBER) ? (sp)->cols - O_NUMBER_LENGTH : (sp)->cols))
32519304Speter
32619304Speter/*
32719304Speter * LASTLINE is the zero-based, last line in the screen.  Note that it is correct
32819304Speter * regardless of the changes in the screen to permit text input on the last line
32919304Speter * of the screen, or the existence of small screens.
33019304Speter */
33119304Speter#define LASTLINE(sp) \
33219304Speter	((sp)->t_maxrows < (sp)->rows ? (sp)->t_maxrows : (sp)->rows - 1)
33319304Speter
33419304Speter/*
33519304Speter * Small screen (see vs_refresh.c, section 6a) and one-line screen test.
33619304Speter * Note, both cannot be true for the same screen.
33719304Speter */
33819304Speter#define	IS_SMALL(sp)	((sp)->t_minrows != (sp)->t_maxrows)
33919304Speter#define	IS_ONELINE(sp)	((sp)->rows == 1)
34019304Speter
34119304Speter#define	HALFTEXT(sp)				/* Half text. */	\
34219304Speter	((sp)->t_rows == 1 ? 1 : (sp)->t_rows / 2)
34319304Speter#define	HALFSCREEN(sp)				/* Half text screen. */	\
34419304Speter	((sp)->t_maxrows == 1 ? 1 : (sp)->t_maxrows / 2)
34519304Speter
34619304Speter/*
34719304Speter * Next tab offset.
34819304Speter *
34919304Speter * !!!
35019304Speter * There are problems with how the historical vi handled tabs.  For example,
35119304Speter * by doing "set ts=3" and building lines that fold, you can get it to step
35219304Speter * through tabs as if they were spaces and move inserted characters to new
35319304Speter * positions when <esc> is entered.  I believe that nvi does tabs correctly,
35419304Speter * but there are some historical incompatibilities.
35519304Speter */
35619304Speter#define	TAB_OFF(c)	COL_OFF((c), O_VAL(sp, O_TABSTOP))
35719304Speter
358254225Speter/* If more than one horizontal screen being shown. */
359254225Speter#define	IS_HSPLIT(sp)							\
360254225Speter	((sp)->rows != O_VAL(sp, O_LINES))
361254225Speter/* If more than one vertical screen being shown. */
362254225Speter#define	IS_VSPLIT(sp)							\
363254225Speter	((sp)->cols != O_VAL(sp, O_COLUMNS))
36419304Speter/* If more than one screen being shown. */
36519304Speter#define	IS_SPLIT(sp)							\
366254225Speter	(IS_HSPLIT(sp) || IS_VSPLIT(sp))
36719304Speter
36819304Speter/* Screen adjustment operations. */
36919304Spetertypedef enum { A_DECREASE, A_INCREASE, A_SET } adj_t;
37019304Speter
37119304Speter/* Screen position operations. */
37219304Spetertypedef enum { P_BOTTOM, P_FILL, P_MIDDLE, P_TOP } pos_t;
37319304Speter
37419304Speter/* Scrolling operations. */
37519304Spetertypedef enum {
37619304Speter	CNTRL_B, CNTRL_D, CNTRL_E, CNTRL_F,
37719304Speter	CNTRL_U, CNTRL_Y, Z_CARAT, Z_PLUS
37819304Speter} scroll_t;
37919304Speter
38019304Speter/* Vi common error messages. */
38119304Spetertypedef enum {
38219304Speter	VIM_COMBUF, VIM_EMPTY, VIM_EOF, VIM_EOL,
38319304Speter	VIM_NOCOM, VIM_NOCOM_B, VIM_USAGE, VIM_WRESIZE
38419304Speter} vim_t;
38519304Speter
386254225Speter#include "extern.h"
387