Import nvi2 version 2.1.3 to vendor branch
[dragonfly.git] / contrib / nvi2 / vi / vi.h
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  *      $Id: vi.h,v 10.29 2012/02/11 00:33:46 zy Exp $
10  */
11
12 /* Definition of a vi "word". */
13 #define inword(ch)      ((ch) == '_' || (ISGRAPH(ch) && !ISPUNCT(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)(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(SCR *, VCS *);
165 int     cs_fblank(SCR *, VCS *);
166 int     cs_fspace(SCR *, VCS *);
167 int     cs_init(SCR *, VCS *);
168 int     cs_next(SCR *, VCS *);
169 int     cs_prev(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, soff
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 coff 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 on screen. */
206         size_t   c_eboff;       /* 0-N: offset of  last character on screen. */
207         u_int8_t c_scoff;       /* 0-N: offset into the first character. */
208                                 /* 255: no character of line visible. */
209         u_int8_t c_eclen;       /* 1-N: columns from the last character. */
210         u_int8_t c_ecsize;      /* 1-N: size of the last character. */
211 } SMAP;
212                                 /* Macros to flush/test cached information. */
213 #define SMAP_CACHE(smp)         ((smp)->c_ecsize != 0)
214 #define SMAP_FLUSH(smp)         ((smp)->c_ecsize = 0)
215
216                                 /* Character search information. */
217 typedef enum { CNOTSET, FSEARCH, fSEARCH, TSEARCH, tSEARCH } cdir_t;
218
219 typedef enum { AB_NOTSET, AB_NOTWORD, AB_INWORD } abb_t;
220 typedef enum { Q_NOTSET, Q_BNEXT, Q_BTHIS, Q_VNEXT, Q_VTHIS } quote_t;
221
222 /* Vi private, per-screen memory. */
223 typedef struct _vi_private {
224         VICMD   cmd;            /* Current command, motion. */
225         VICMD   motion;
226
227         /*
228          * !!!
229          * The saved command structure can be modified by the underlying
230          * vi functions, see v_Put() and v_put().
231          */
232         VICMD   sdot;           /* Saved dot, motion command. */
233         VICMD   sdotmotion;
234
235         CHAR_T *keyw;           /* Keyword buffer. */
236         size_t  klen;           /* Keyword length. */
237         size_t  keywlen;        /* Keyword buffer length. */
238
239         CHAR_T  rlast;          /* Last 'r' replacement character. */
240         e_key_t rvalue;         /* Value of last replacement character. */
241
242         EVENT  *rep;            /* Input replay buffer. */
243         size_t  rep_len;        /* Input replay buffer length. */
244         size_t  rep_cnt;        /* Input replay buffer characters. */
245
246         mtype_t mtype;          /* Last displayed message type. */
247         size_t  linecount;      /* 1-N: Output overwrite count. */
248         size_t  lcontinue;      /* 1-N: Output line continue value. */
249         size_t  totalcount;     /* 1-N: Output overwrite count. */
250
251                                 /* Busy state. */
252         int     busy_ref;       /* Busy reference count. */
253         int     busy_ch;        /* Busy character. */
254         size_t  busy_fx;        /* Busy character x coordinate. */
255         size_t  busy_oldy;      /* Saved y coordinate. */
256         size_t  busy_oldx;      /* Saved x coordinate. */
257         struct timespec busy_ts;/* Busy timer. */
258
259         MARK    sel;            /* Select start position. */
260
261         CHAR_T *mcs;            /* Match character list. */
262         char   *ps;             /* Paragraph plus section list. */
263
264         u_long  u_ccnt;         /* Undo command count. */
265
266         CHAR_T  lastckey;       /* Last search character. */
267         cdir_t  csearchdir;     /* Character search direction. */
268
269         SMAP   *h_smap;         /* First slot of the line map. */
270         SMAP   *t_smap;         /* Last slot of the line map. */
271
272         /*
273          * One extra slot is always allocated for the map so that we can use
274          * it to do vi :colon command input; see v_tcmd().
275          */
276         recno_t sv_tm_lno;      /* tcmd: saved TMAP lno field. */
277         size_t  sv_tm_coff;     /* tcmd: saved TMAP coff field. */
278         size_t  sv_tm_soff;     /* tcmd: saved TMAP soff field. */
279         size_t  sv_t_maxrows;   /* tcmd: saved t_maxrows. */
280         size_t  sv_t_minrows;   /* tcmd: saved t_minrows. */
281         size_t  sv_t_rows;      /* tcmd: saved t_rows. */
282 #define SIZE_HMAP(sp)   (VIP(sp)->srows + 1)
283
284         /*
285          * Macros to get to the head/tail of the smap.  If the screen only has
286          * one line, HMAP can be equal to TMAP, so the code has to understand
287          * the off-by-one errors that can result.  If stepping through an SMAP
288          * and operating on each entry, use sp->t_rows as the count of slots,
289          * don't use a loop that compares <= TMAP.
290          */
291 #define _HMAP(sp)       (VIP(sp)->h_smap)
292 #define HMAP            _HMAP(sp)
293 #define _TMAP(sp)       (VIP(sp)->t_smap)
294 #define TMAP            _TMAP(sp)
295
296         recno_t ss_lno; /* 1-N: vi_opt_screens cached line number. */
297         size_t  ss_screens;     /* vi_opt_screens cached return value. */
298 #define VI_SCR_CFLUSH(vip)      vip->ss_lno = OOBLNO
299
300         size_t  srows;          /* 1-N: rows in the terminal/window. */
301         recno_t olno;           /* 1-N: old cursor file line. */
302         size_t  ocno;           /* 0-N: old file cursor column. */
303         size_t  sc_col;         /* 0-N: LOGICAL screen column. */
304         SMAP   *sc_smap;        /* SMAP entry where sc_col occurs. */
305
306 #define VIP_CUR_INVALID 0x0001  /* Cursor position is unknown. */
307 #define VIP_DIVIDER     0x0002  /* Divider line was displayed. */
308 #define VIP_N_EX_PAINT  0x0004  /* Clear and repaint when ex finishes. */
309 #define VIP_N_EX_REDRAW 0x0008  /* Schedule SC_SCR_REDRAW when ex finishes. */
310 #define VIP_N_REFRESH   0x0010  /* Repaint (from SMAP) on the next refresh. */
311 #define VIP_N_RENUMBER  0x0020  /* Renumber screen on the next refresh. */
312 #define VIP_RCM_LAST    0x0040  /* Cursor drawn to the last column. */
313 #define VIP_S_MODELINE  0x0080  /* Skip next modeline refresh. */
314 #define VIP_S_REFRESH   0x0100  /* Skip next refresh. */
315         u_int16_t flags;
316 } VI_PRIVATE;
317
318 /* Vi private area. */
319 #define VIP(sp) ((VI_PRIVATE *)((sp)->vi_private))
320
321 #define O_NUMBER_FMT    "%7lu "                 /* O_NUMBER format, length. */
322 #define O_NUMBER_LENGTH 8
323 #define SCREEN_COLS(sp)                         /* Screen columns. */   \
324         ((O_ISSET(sp, O_NUMBER) ? (sp)->cols - O_NUMBER_LENGTH : (sp)->cols))
325
326 /*
327  * LASTLINE is the zero-based, last line in the screen.  Note that it is correct
328  * regardless of the changes in the screen to permit text input on the last line
329  * of the screen, or the existence of small screens.
330  */
331 #define LASTLINE(sp) \
332         ((sp)->t_maxrows < (sp)->rows ? (sp)->t_maxrows : (sp)->rows - 1)
333
334 /*
335  * Small screen (see vs_refresh.c, section 6a) and one-line screen test.
336  * Note, both cannot be true for the same screen.
337  */
338 #define IS_SMALL(sp)    ((sp)->t_minrows != (sp)->t_maxrows)
339 #define IS_ONELINE(sp)  ((sp)->rows == 1)
340
341 #define HALFTEXT(sp)                            /* Half text. */        \
342         ((sp)->t_rows == 1 ? 1 : (sp)->t_rows / 2)
343 #define HALFSCREEN(sp)                          /* Half text screen. */ \
344         ((sp)->t_maxrows == 1 ? 1 : (sp)->t_maxrows / 2)
345
346 /*
347  * Next tab offset.
348  *
349  * !!!
350  * There are problems with how the historical vi handled tabs.  For example,
351  * by doing "set ts=3" and building lines that fold, you can get it to step
352  * through tabs as if they were spaces and move inserted characters to new
353  * positions when <esc> is entered.  I believe that nvi does tabs correctly,
354  * but there are some historical incompatibilities.
355  */
356 #define TAB_OFF(c)      COL_OFF((c), O_VAL(sp, O_TABSTOP))
357
358 /* If more than one horizontal screen being shown. */
359 #define IS_HSPLIT(sp)                                                   \
360         ((sp)->rows != O_VAL(sp, O_LINES))
361 /* If more than one vertical screen being shown. */
362 #define IS_VSPLIT(sp)                                                   \
363         ((sp)->cols != O_VAL(sp, O_COLUMNS))
364 /* If more than one screen being shown. */
365 #define IS_SPLIT(sp)                                                    \
366         (IS_HSPLIT(sp) || IS_VSPLIT(sp))
367
368 /* Screen adjustment operations. */
369 typedef enum { A_DECREASE, A_INCREASE, A_SET } adj_t;
370
371 /* Screen position operations. */
372 typedef enum { P_BOTTOM, P_FILL, P_MIDDLE, P_TOP } pos_t;
373
374 /* Scrolling operations. */
375 typedef enum {
376         CNTRL_B, CNTRL_D, CNTRL_E, CNTRL_F,
377         CNTRL_U, CNTRL_Y, Z_CARAT, Z_PLUS
378 } scroll_t;
379
380 /* Vi common error messages. */
381 typedef enum {
382         VIM_COMBUF, VIM_EMPTY, VIM_EOF, VIM_EOL,
383         VIM_NOCOM, VIM_NOCOM_B, VIM_USAGE, VIM_WRESIZE
384 } vim_t;
385
386 #include "extern.h"