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