vi.h revision 1.1 1 1.1 christos /*-
2 1.1 christos * Copyright (c) 1992, 1993, 1994
3 1.1 christos * The Regents of the University of California. All rights reserved.
4 1.1 christos * Copyright (c) 1992, 1993, 1994, 1995, 1996
5 1.1 christos * Keith Bostic. All rights reserved.
6 1.1 christos *
7 1.1 christos * See the LICENSE file for redistribution information.
8 1.1 christos *
9 1.1 christos * Id: vi.h,v 10.27 2002/01/19 21:59:07 skimo Exp (Berkeley) Date: 2002/01/19 21:59:07
10 1.1 christos */
11 1.1 christos
12 1.1 christos /* Definition of a vi "word". */
13 1.1 christos #define inword(ch) ((UCHAR_T)ch <= 255 && (isalnum(ch) || (ch) == '_'))
14 1.1 christos
15 1.1 christos typedef struct _vikeys VIKEYS;
16 1.1 christos
17 1.1 christos /* Structure passed around to functions implementing vi commands. */
18 1.1 christos typedef struct _vicmd {
19 1.1 christos CHAR_T key; /* Command key. */
20 1.1 christos CHAR_T buffer; /* Buffer. */
21 1.1 christos CHAR_T character; /* Character. */
22 1.1 christos u_long count; /* Count. */
23 1.1 christos u_long count2; /* Second count (only used by z). */
24 1.1 christos EVENT ev; /* Associated event. */
25 1.1 christos
26 1.1 christos #define ISCMD(p, key) ((p) == &vikeys[key])
27 1.1 christos VIKEYS const *kp; /* Command/Motion VIKEYS entry. */
28 1.1 christos #define ISMOTION(vp) (vp->rkp != NULL && F_ISSET(vp->rkp, V_MOTION))
29 1.1 christos VIKEYS const *rkp; /* Related C/M VIKEYS entry. */
30 1.1 christos
31 1.1 christos /*
32 1.1 christos * Historic vi allowed "dl" when the cursor was on the last column,
33 1.1 christos * deleting the last character, and similarly allowed "dw" when
34 1.1 christos * the cursor was on the last column of the file. It didn't allow
35 1.1 christos * "dh" when the cursor was on column 1, although these cases are
36 1.1 christos * not strictly analogous. The point is that some movements would
37 1.1 christos * succeed if they were associated with a motion command, and fail
38 1.1 christos * otherwise. This is part of the off-by-1 schizophrenia that
39 1.1 christos * plagued vi. Other examples are that "dfb" deleted everything
40 1.1 christos * up to and including the next 'b' character, while "d/b" deleted
41 1.1 christos * everything up to the next 'b' character. While this implementation
42 1.1 christos * regularizes the interface to the extent possible, there are many
43 1.1 christos * special cases that can't be fixed. The special cases are handled
44 1.1 christos * by setting flags per command so that the underlying command and
45 1.1 christos * motion routines know what's really going on.
46 1.1 christos *
47 1.1 christos * The VM_* flags are set in the vikeys array and by the underlying
48 1.1 christos * functions (motion component or command) as well. For this reason,
49 1.1 christos * the flags in the VICMD and VIKEYS structures live in the same name
50 1.1 christos * space.
51 1.1 christos */
52 1.1 christos #define VM_CMDFAILED 0x00000001 /* Command failed. */
53 1.1 christos #define VM_CUTREQ 0x00000002 /* Always cut into numeric buffers. */
54 1.1 christos #define VM_LDOUBLE 0x00000004 /* Doubled command for line mode. */
55 1.1 christos #define VM_LMODE 0x00000008 /* Motion is line oriented. */
56 1.1 christos #define VM_COMMASK 0x0000000f /* Mask for VM flags. */
57 1.1 christos
58 1.1 christos /*
59 1.1 christos * The VM_RCM_* flags are single usage, i.e. if you set one, you have
60 1.1 christos * to clear the others.
61 1.1 christos */
62 1.1 christos #define VM_RCM 0x00000010 /* Use relative cursor movment (RCM). */
63 1.1 christos #define VM_RCM_SET 0x00000020 /* RCM: set to current position. */
64 1.1 christos #define VM_RCM_SETFNB 0x00000040 /* RCM: set to first non-blank (FNB). */
65 1.1 christos #define VM_RCM_SETLAST 0x00000080 /* RCM: set to last character. */
66 1.1 christos #define VM_RCM_SETNNB 0x00000100 /* RCM: set to next non-blank. */
67 1.1 christos #define VM_RCM_MASK 0x000001f0 /* Mask for RCM flags. */
68 1.1 christos
69 1.1 christos /* Flags for the underlying function. */
70 1.1 christos #define VC_BUFFER 0x00000200 /* The buffer was set. */
71 1.1 christos #define VC_C1RESET 0x00000400 /* Reset C1SET flag for dot commands. */
72 1.1 christos #define VC_C1SET 0x00000800 /* Count 1 was set. */
73 1.1 christos #define VC_C2SET 0x00001000 /* Count 2 was set. */
74 1.1 christos #define VC_ISDOT 0x00002000 /* Command was the dot command. */
75 1.1 christos u_int32_t flags;
76 1.1 christos
77 1.1 christos /*
78 1.1 christos * There are four cursor locations that we worry about: the initial
79 1.1 christos * cursor position, the start of the range, the end of the range,
80 1.1 christos * and the final cursor position. The initial cursor position and
81 1.1 christos * the start of the range are both m_start, and are always the same.
82 1.1 christos * All locations are initialized to the starting cursor position by
83 1.1 christos * the main vi routines, and the underlying functions depend on this.
84 1.1 christos *
85 1.1 christos * Commands that can be motion components set the end of the range
86 1.1 christos * cursor position, m_stop. All commands must set the ending cursor
87 1.1 christos * position, m_final. The reason that m_stop isn't the same as m_final
88 1.1 christos * is that there are situations where the final position of the cursor
89 1.1 christos * is outside of the cut/delete range (e.g. 'd[[' from the first column
90 1.1 christos * of a line). The final cursor position often varies based on the
91 1.1 christos * direction of the movement, as well as the command. The only special
92 1.1 christos * case that the delete code handles is that it will make adjustments
93 1.1 christos * if the final cursor position is deleted.
94 1.1 christos *
95 1.1 christos * The reason for all of this is that the historic vi semantics were
96 1.1 christos * defined command-by-command. Every function has to roll its own
97 1.1 christos * starting and stopping positions, and adjust them if it's being used
98 1.1 christos * as a motion component. The general rules are as follows:
99 1.1 christos *
100 1.1 christos * 1: If not a motion component, the final cursor is at the end
101 1.1 christos * of the range.
102 1.1 christos * 2: If moving backward in the file, delete and yank move the
103 1.1 christos * final cursor to the end of the range.
104 1.1 christos * 3: If moving forward in the file, delete and yank leave the
105 1.1 christos * final cursor at the start of the range.
106 1.1 christos *
107 1.1 christos * Usually, if moving backward in the file and it's a motion component,
108 1.1 christos * the starting cursor is decremented by a single character (or, in a
109 1.1 christos * few cases, to the end of the previous line) so that the starting
110 1.1 christos * cursor character isn't cut or deleted. No cursor adjustment is
111 1.1 christos * needed for moving forward, because the cut/delete routines handle
112 1.1 christos * m_stop inclusively, i.e. the last character in the range is cut or
113 1.1 christos * deleted. This makes cutting to the EOF/EOL reasonable.
114 1.1 christos *
115 1.1 christos * The 'c', '<', '>', and '!' commands are special cases. We ignore
116 1.1 christos * the final cursor position for all of them: for 'c', the text input
117 1.1 christos * routines set the cursor to the last character inserted; for '<',
118 1.1 christos * '>' and '!', the underlying ex commands that do the operation will
119 1.1 christos * set the cursor for us, usually to something related to the first
120 1.1 christos * <nonblank>.
121 1.1 christos */
122 1.1 christos MARK m_start; /* mark: initial cursor, range start. */
123 1.1 christos MARK m_stop; /* mark: range end. */
124 1.1 christos MARK m_final; /* mark: final cursor position. */
125 1.1 christos } VICMD;
126 1.1 christos
127 1.1 christos /* Vi command table structure. */
128 1.1 christos struct _vikeys { /* Underlying function. */
129 1.1 christos int (*func) __P((SCR *, VICMD *));
130 1.1 christos #define V_ABS 0x00004000 /* Absolute movement, set '' mark. */
131 1.1 christos #define V_ABS_C 0x00008000 /* V_ABS: if the line/column changed. */
132 1.1 christos #define V_ABS_L 0x00010000 /* V_ABS: if the line changed. */
133 1.1 christos #define V_CHAR 0x00020000 /* Character (required, trailing). */
134 1.1 christos #define V_CNT 0x00040000 /* Count (optional, leading). */
135 1.1 christos #define V_DOT 0x00080000 /* On success, sets dot command. */
136 1.1 christos #define V_KEYW 0x00100000 /* Cursor referenced word. */
137 1.1 christos #define V_MOTION 0x00200000 /* Motion (required, trailing). */
138 1.1 christos #define V_MOVE 0x00400000 /* Command defines movement. */
139 1.1 christos #define V_OBUF 0x00800000 /* Buffer (optional, leading). */
140 1.1 christos #define V_RBUF 0x01000000 /* Buffer (required, trailing). */
141 1.1 christos #define V_SECURE 0x02000000 /* Permission denied if O_SECURE set. */
142 1.1 christos u_int32_t flags;
143 1.1 christos char *usage; /* Usage line. */
144 1.1 christos char *help; /* Help line. */
145 1.1 christos };
146 1.1 christos #define MAXVIKEY 126 /* List of vi commands. */
147 1.1 christos extern VIKEYS const vikeys[MAXVIKEY + 1];
148 1.1 christos extern VIKEYS const tmotion; /* XXX Hacked ~ command. */
149 1.1 christos
150 1.1 christos /* Character stream structure, prototypes. */
151 1.1 christos typedef struct _vcs {
152 1.1 christos db_recno_t cs_lno; /* Line. */
153 1.1 christos size_t cs_cno; /* Column. */
154 1.1 christos CHAR_T *cs_bp; /* Buffer. */
155 1.1 christos size_t cs_len; /* Length. */
156 1.1 christos CHAR_T cs_ch; /* Character. */
157 1.1 christos #define CS_EMP 1 /* Empty line. */
158 1.1 christos #define CS_EOF 2 /* End-of-file. */
159 1.1 christos #define CS_EOL 3 /* End-of-line. */
160 1.1 christos #define CS_SOF 4 /* Start-of-file. */
161 1.1 christos int cs_flags; /* Return flags. */
162 1.1 christos } VCS;
163 1.1 christos
164 1.1 christos int cs_bblank __P((SCR *, VCS *));
165 1.1 christos int cs_fblank __P((SCR *, VCS *));
166 1.1 christos int cs_fspace __P((SCR *, VCS *));
167 1.1 christos int cs_init __P((SCR *, VCS *));
168 1.1 christos int cs_next __P((SCR *, VCS *));
169 1.1 christos int cs_prev __P((SCR *, VCS *));
170 1.1 christos
171 1.1 christos /*
172 1.1 christos * We use a single "window" for each set of vi screens. The model would be
173 1.1 christos * simpler with two windows (one for the text, and one for the modeline)
174 1.1 christos * because scrolling the text window down would work correctly then, not
175 1.1 christos * affecting the mode line. As it is we have to play games to make it look
176 1.1 christos * right. The reason for this choice is that it would be difficult for
177 1.1 christos * curses to optimize the movement, i.e. detect that the downward scroll
178 1.1 christos * isn't going to change the modeline, set the scrolling region on the
179 1.1 christos * terminal and only scroll the first part of the text window.
180 1.1 christos *
181 1.1 christos * Structure for mapping lines to the screen. An SMAP is an array, with one
182 1.1 christos * structure element per screen line, which holds information describing the
183 1.1 christos * physical line which is displayed in the screen line. The first two fields
184 1.1 christos * (lno and off) are all that are necessary to describe a line. The rest of
185 1.1 christos * the information is useful to keep information from being re-calculated.
186 1.1 christos *
187 1.1 christos * The SMAP always has an entry for each line of the physical screen, plus a
188 1.1 christos * slot for the colon command line, so there is room to add any screen into
189 1.1 christos * another one at screen exit.
190 1.1 christos *
191 1.1 christos * Lno is the line number. If doing the historic vi long line folding, soff
192 1.1 christos * is the screen offset into the line. For example, the pair 2:1 would be
193 1.1 christos * the first screen of line 2, and 2:2 would be the second. In the case of
194 1.1 christos * long lines, the screen map will tend to be staggered, e.g., 1:1, 1:2, 1:3,
195 1.1 christos * 2:1, 3:1, etc. If doing left-right scrolling, the coff field is the screen
196 1.1 christos * column offset into the lines, and can take on any value, as it's adjusted
197 1.1 christos * by the user set value O_SIDESCROLL.
198 1.1 christos */
199 1.1 christos typedef struct _smap {
200 1.1 christos db_recno_t lno; /* 1-N: Physical file line number. */
201 1.1 christos size_t coff; /* 0-N: Column offset in the line. */
202 1.1 christos size_t soff; /* 1-N: Screen offset in the line. */
203 1.1 christos
204 1.1 christos /* vs_line() cache information. */
205 1.1 christos size_t c_sboff; /* 0-N: offset of first character on screen. */
206 1.1 christos size_t c_eboff; /* 0-N: offset of last character on screen. */
207 1.1 christos u_int8_t c_scoff; /* 0-N: offset into the first character. */
208 1.1 christos /* 255: no character of line visible. */
209 1.1 christos u_int8_t c_eclen; /* 1-N: columns from the last character. */
210 1.1 christos u_int8_t c_ecsize; /* 1-N: size of the last character. */
211 1.1 christos } SMAP;
212 1.1 christos /* Macros to flush/test cached information. */
213 1.1 christos #define SMAP_CACHE(smp) ((smp)->c_ecsize != 0)
214 1.1 christos #define SMAP_FLUSH(smp) ((smp)->c_ecsize = 0)
215 1.1 christos
216 1.1 christos /* Character search information. */
217 1.1 christos typedef enum { CNOTSET, FSEARCH, fSEARCH, TSEARCH, tSEARCH } cdir_t;
218 1.1 christos
219 1.1 christos typedef enum { AB_NOTSET, AB_NOTWORD, AB_INWORD } abb_t;
220 1.1 christos typedef enum { Q_NOTSET, Q_BNEXT, Q_BTHIS, Q_VNEXT, Q_VTHIS } quote_t;
221 1.1 christos
222 1.1 christos /* Vi private, per-screen memory. */
223 1.1 christos typedef struct _vi_private {
224 1.1 christos VICMD cmd; /* Current command, motion. */
225 1.1 christos VICMD motion;
226 1.1 christos
227 1.1 christos /*
228 1.1 christos * !!!
229 1.1 christos * The saved command structure can be modified by the underlying
230 1.1 christos * vi functions, see v_Put() and v_put().
231 1.1 christos */
232 1.1 christos VICMD sdot; /* Saved dot, motion command. */
233 1.1 christos VICMD sdotmotion;
234 1.1 christos
235 1.1 christos CHAR_T *keyw; /* Keyword buffer. */
236 1.1 christos size_t klen; /* Keyword length. */
237 1.1 christos size_t keywlen; /* Keyword buffer length. */
238 1.1 christos
239 1.1 christos CHAR_T rlast; /* Last 'r' replacement character. */
240 1.1 christos e_key_t rvalue; /* Value of last replacement character. */
241 1.1 christos
242 1.1 christos EVENT *rep; /* Input replay buffer. */
243 1.1 christos size_t rep_len; /* Input replay buffer length. */
244 1.1 christos size_t rep_cnt; /* Input replay buffer characters. */
245 1.1 christos
246 1.1 christos mtype_t mtype; /* Last displayed message type. */
247 1.1 christos size_t linecount; /* 1-N: Output overwrite count. */
248 1.1 christos size_t lcontinue; /* 1-N: Output line continue value. */
249 1.1 christos size_t totalcount; /* 1-N: Output overwrite count. */
250 1.1 christos
251 1.1 christos /* Busy state. */
252 1.1 christos int busy_ref; /* Busy reference count. */
253 1.1 christos int busy_ch; /* Busy character. */
254 1.1 christos size_t busy_fx; /* Busy character x coordinate. */
255 1.1 christos size_t busy_oldy; /* Saved y coordinate. */
256 1.1 christos size_t busy_oldx; /* Saved x coordinate. */
257 1.1 christos struct timeval busy_tv; /* Busy timer. */
258 1.1 christos
259 1.1 christos MARK sel; /* Select start position. */
260 1.1 christos
261 1.1 christos char *ps; /* Paragraph plus section list. */
262 1.1 christos
263 1.1 christos u_long u_ccnt; /* Undo command count. */
264 1.1 christos
265 1.1 christos CHAR_T lastckey; /* Last search character. */
266 1.1 christos cdir_t csearchdir; /* Character search direction. */
267 1.1 christos
268 1.1 christos SMAP *h_smap; /* First slot of the line map. */
269 1.1 christos SMAP *t_smap; /* Last slot of the line map. */
270 1.1 christos
271 1.1 christos /*
272 1.1 christos * One extra slot is always allocated for the map so that we can use
273 1.1 christos * it to do vi :colon command input; see v_tcmd().
274 1.1 christos */
275 1.1 christos db_recno_t sv_tm_lno; /* tcmd: saved TMAP lno field. */
276 1.1 christos size_t sv_tm_coff; /* tcmd: saved TMAP coff field. */
277 1.1 christos size_t sv_tm_soff; /* tcmd: saved TMAP soff field. */
278 1.1 christos size_t sv_t_maxrows; /* tcmd: saved t_maxrows. */
279 1.1 christos size_t sv_t_minrows; /* tcmd: saved t_minrows. */
280 1.1 christos size_t sv_t_rows; /* tcmd: saved t_rows. */
281 1.1 christos #define SIZE_HMAP(sp) (VIP(sp)->srows + 1)
282 1.1 christos
283 1.1 christos /*
284 1.1 christos * Macros to get to the head/tail of the smap. If the screen only has
285 1.1 christos * one line, HMAP can be equal to TMAP, so the code has to understand
286 1.1 christos * the off-by-one errors that can result. If stepping through an SMAP
287 1.1 christos * and operating on each entry, use sp->t_rows as the count of slots,
288 1.1 christos * don't use a loop that compares <= TMAP.
289 1.1 christos */
290 1.1 christos #define _HMAP(sp) (VIP(sp)->h_smap)
291 1.1 christos #define HMAP _HMAP(sp)
292 1.1 christos #define _TMAP(sp) (VIP(sp)->t_smap)
293 1.1 christos #define TMAP _TMAP(sp)
294 1.1 christos
295 1.1 christos db_recno_t ss_lno; /* 1-N: vi_opt_screens cached line number. */
296 1.1 christos size_t ss_screens; /* vi_opt_screens cached return value. */
297 1.1 christos #define VI_SCR_CFLUSH(vip) vip->ss_lno = OOBLNO
298 1.1 christos
299 1.1 christos size_t srows; /* 1-N: rows in the terminal/window. */
300 1.1 christos db_recno_t olno; /* 1-N: old cursor file line. */
301 1.1 christos size_t ocno; /* 0-N: old file cursor column. */
302 1.1 christos size_t sc_col; /* 0-N: LOGICAL screen column. */
303 1.1 christos SMAP *sc_smap; /* SMAP entry where sc_col occurs. */
304 1.1 christos
305 1.1 christos #define VIP_CUR_INVALID 0x0001 /* Cursor position is unknown. */
306 1.1 christos #define VIP_DIVIDER 0x0002 /* Divider line was displayed. */
307 1.1 christos #define VIP_N_EX_PAINT 0x0004 /* Clear and repaint when ex finishes. */
308 1.1 christos #define VIP_N_EX_REDRAW 0x0008 /* Schedule SC_SCR_REDRAW when ex finishes. */
309 1.1 christos #define VIP_N_REFRESH 0x0010 /* Repaint (from SMAP) on the next refresh. */
310 1.1 christos #define VIP_N_RENUMBER 0x0020 /* Renumber screen on the next refresh. */
311 1.1 christos #define VIP_RCM_LAST 0x0040 /* Cursor drawn to the last column. */
312 1.1 christos #define VIP_S_MODELINE 0x0080 /* Skip next modeline refresh. */
313 1.1 christos #define VIP_S_REFRESH 0x0100 /* Skip next refresh. */
314 1.1 christos u_int16_t flags;
315 1.1 christos } VI_PRIVATE;
316 1.1 christos
317 1.1 christos /* Vi private area. */
318 1.1 christos #define VIP(sp) ((VI_PRIVATE *)((sp)->vi_private))
319 1.1 christos
320 1.1 christos #define O_NUMBER_FMT "%7lu " /* O_NUMBER format, length. */
321 1.1 christos #define O_NUMBER_LENGTH 8
322 1.1 christos #define SCREEN_COLS(sp) /* Screen columns. */ \
323 1.1 christos ((O_ISSET(sp, O_NUMBER) ? (sp)->cols - O_NUMBER_LENGTH : (sp)->cols))
324 1.1 christos
325 1.1 christos /*
326 1.1 christos * LASTLINE is the zero-based, last line in the screen. Note that it is correct
327 1.1 christos * regardless of the changes in the screen to permit text input on the last line
328 1.1 christos * of the screen, or the existence of small screens.
329 1.1 christos */
330 1.1 christos #define LASTLINE(sp) \
331 1.1 christos ((sp)->t_maxrows < (sp)->rows ? (sp)->t_maxrows : (sp)->rows - 1)
332 1.1 christos
333 1.1 christos /*
334 1.1 christos * Small screen (see vs_refresh.c, section 6a) and one-line screen test.
335 1.1 christos * Note, both cannot be true for the same screen.
336 1.1 christos */
337 1.1 christos #define IS_SMALL(sp) ((sp)->t_minrows != (sp)->t_maxrows)
338 1.1 christos #define IS_ONELINE(sp) ((sp)->rows == 1)
339 1.1 christos
340 1.1 christos #define HALFTEXT(sp) /* Half text. */ \
341 1.1 christos ((sp)->t_rows == 1 ? 1 : (sp)->t_rows / 2)
342 1.1 christos #define HALFSCREEN(sp) /* Half text screen. */ \
343 1.1 christos ((sp)->t_maxrows == 1 ? 1 : (sp)->t_maxrows / 2)
344 1.1 christos
345 1.1 christos /*
346 1.1 christos * Next tab offset.
347 1.1 christos *
348 1.1 christos * !!!
349 1.1 christos * There are problems with how the historical vi handled tabs. For example,
350 1.1 christos * by doing "set ts=3" and building lines that fold, you can get it to step
351 1.1 christos * through tabs as if they were spaces and move inserted characters to new
352 1.1 christos * positions when <esc> is entered. I believe that nvi does tabs correctly,
353 1.1 christos * but there are some historical incompatibilities.
354 1.1 christos */
355 1.1 christos #define TAB_OFF(c) COL_OFF((c), O_VAL(sp, O_TABSTOP))
356 1.1 christos
357 1.1 christos /* If more than one horizontal screen being shown. */
358 1.1 christos #define IS_HSPLIT(sp) \
359 1.1 christos ((sp)->rows != O_VAL(sp, O_LINES))
360 1.1 christos /* If more than one vertical screen being shown. */
361 1.1 christos #define IS_VSPLIT(sp) \
362 1.1 christos ((sp)->cols != O_VAL(sp, O_COLUMNS))
363 1.1 christos /* If more than one screen being shown. */
364 1.1 christos #define IS_SPLIT(sp) \
365 1.1 christos (IS_HSPLIT(sp) || IS_VSPLIT(sp))
366 1.1 christos
367 1.1 christos /* Screen adjustment operations. */
368 1.1 christos typedef enum { A_DECREASE, A_INCREASE, A_SET } adj_t;
369 1.1 christos
370 1.1 christos /* Screen position operations. */
371 1.1 christos typedef enum { P_BOTTOM, P_FILL, P_MIDDLE, P_TOP } pos_t;
372 1.1 christos
373 1.1 christos /* Scrolling operations. */
374 1.1 christos typedef enum {
375 1.1 christos CNTRL_B, CNTRL_D, CNTRL_E, CNTRL_F,
376 1.1 christos CNTRL_U, CNTRL_Y, Z_CARAT, Z_PLUS
377 1.1 christos } scroll_t;
378 1.1 christos
379 1.1 christos /* Vi common error messages. */
380 1.1 christos typedef enum {
381 1.1 christos VIM_COMBUF, VIM_EMPTY, VIM_EOF, VIM_EOL,
382 1.1 christos VIM_NOCOM, VIM_NOCOM_B, VIM_USAGE, VIM_WRESIZE
383 1.1 christos } vim_t;
384 1.1 christos
385 1.1 christos #include "extern.h"
386