1 /*        $NetBSD: vi.h,v 1.2 2013/11/22 15:52:06 christos Exp $ */
2 /*-
3  * Copyright (c) 1992, 1993, 1994
4  *        The Regents of the University of California.  All rights reserved.
5  * Copyright (c) 1992, 1993, 1994, 1995, 1996
6  *        Keith Bostic.  All rights reserved.
7  *
8  * See the LICENSE file for redistribution information.
9  *
10  *        Id: vi.h,v 10.27 2002/01/19 21:59:07 skimo Exp  (Berkeley) Date: 2002/01/19 21:59:07
11  */
12 
13 /* Definition of a vi "word". */
14 #define   inword(ch)          ((ch) == '_' || (ISGRAPH((UCHAR_T)ch) && !ISPUNCT((UCHAR_T)ch)))
15 
16 typedef struct _vikeys VIKEYS;
17 
18 /* Structure passed around to functions implementing vi commands. */
19 typedef struct _vicmd {
20           ARG_CHAR_T key;                         /* Command key. */
21           ARG_CHAR_T buffer;            /* Buffer. */
22           ARG_CHAR_T character;                   /* Character. */
23           u_long    count;                        /* Count. */
24           u_long    count2;                       /* Second count (only used by z). */
25           EVENT     ev;                           /* Associated event. */
26 
27 #define   ISCMD(p, key)       ((p) == &vikeys[key])
28           VIKEYS const *kp;             /* Command/Motion VIKEYS entry. */
29 #define   ISMOTION(vp)        (vp->rkp != NULL && F_ISSET(vp->rkp, V_MOTION))
30           VIKEYS const *rkp;            /* Related C/M VIKEYS entry. */
31 
32           /*
33            * Historic vi allowed "dl" when the cursor was on the last column,
34            * deleting the last character, and similarly allowed "dw" when
35            * the cursor was on the last column of the file.  It didn't allow
36            * "dh" when the cursor was on column 1, although these cases are
37            * not strictly analogous.  The point is that some movements would
38            * succeed if they were associated with a motion command, and fail
39            * otherwise.  This is part of the off-by-1 schizophrenia that
40            * plagued vi.  Other examples are that "dfb" deleted everything
41            * up to and including the next 'b' character, while "d/b" deleted
42            * everything up to the next 'b' character.  While this implementation
43            * regularizes the interface to the extent possible, there are many
44            * special cases that can't be fixed.  The special cases are handled
45            * by setting flags per command so that the underlying command and
46            * motion routines know what's really going on.
47            *
48            * The VM_* flags are set in the vikeys array and by the underlying
49            * functions (motion component or command) as well.  For this reason,
50            * the flags in the VICMD and VIKEYS structures live in the same name
51            * space.
52            */
53 #define   VM_CMDFAILED        0x00000001          /* Command failed. */
54 #define   VM_CUTREQ 0x00000002          /* Always cut into numeric buffers. */
55 #define   VM_LDOUBLE          0x00000004          /* Doubled command for line mode. */
56 #define   VM_LMODE  0x00000008          /* Motion is line oriented. */
57 #define   VM_COMMASK          0x0000000f          /* Mask for VM flags. */
58 
59           /*
60            * The VM_RCM_* flags are single usage, i.e. if you set one, you have
61            * to clear the others.
62            */
63 #define   VM_RCM              0x00000010          /* Use relative cursor movment (RCM). */
64 #define   VM_RCM_SET          0x00000020          /* RCM: set to current position. */
65 #define   VM_RCM_SETFNB       0x00000040          /* RCM: set to first non-blank (FNB). */
66 #define   VM_RCM_SETLAST      0x00000080          /* RCM: set to last character. */
67 #define   VM_RCM_SETNNB       0x00000100          /* RCM: set to next non-blank. */
68 #define   VM_RCM_MASK         0x000001f0          /* Mask for RCM flags. */
69 
70           /* Flags for the underlying function. */
71 #define   VC_BUFFER 0x00000200          /* The buffer was set. */
72 #define   VC_C1RESET          0x00000400          /* Reset C1SET flag for dot commands. */
73 #define   VC_C1SET  0x00000800          /* Count 1 was set. */
74 #define   VC_C2SET  0x00001000          /* Count 2 was set. */
75 #define   VC_ISDOT  0x00002000          /* Command was the dot command. */
76           u_int32_t flags;
77 
78           /*
79            * There are four cursor locations that we worry about: the initial
80            * cursor position, the start of the range, the end of the range,
81            * and the final cursor position.  The initial cursor position and
82            * the start of the range are both m_start, and are always the same.
83            * All locations are initialized to the starting cursor position by
84            * the main vi routines, and the underlying functions depend on this.
85            *
86            * Commands that can be motion components set the end of the range
87            * cursor position, m_stop.  All commands must set the ending cursor
88            * position, m_final.  The reason that m_stop isn't the same as m_final
89            * is that there are situations where the final position of the cursor
90            * is outside of the cut/delete range (e.g. 'd[[' from the first column
91            * of a line).  The final cursor position often varies based on the
92            * direction of the movement, as well as the command.  The only special
93            * case that the delete code handles is that it will make adjustments
94            * if the final cursor position is deleted.
95            *
96            * The reason for all of this is that the historic vi semantics were
97            * defined command-by-command.  Every function has to roll its own
98            * starting and stopping positions, and adjust them if it's being used
99            * as a motion component.  The general rules are as follows:
100            *
101            *        1: If not a motion component, the final cursor is at the end
102            *           of the range.
103            *        2: If moving backward in the file, delete and yank move the
104            *           final cursor to the end of the range.
105            *        3: If moving forward in the file, delete and yank leave the
106            *           final cursor at the start of the range.
107            *
108            * Usually, if moving backward in the file and it's a motion component,
109            * the starting cursor is decremented by a single character (or, in a
110            * few cases, to the end of the previous line) so that the starting
111            * cursor character isn't cut or deleted.  No cursor adjustment is
112            * needed for moving forward, because the cut/delete routines handle
113            * m_stop inclusively, i.e. the last character in the range is cut or
114            * deleted.  This makes cutting to the EOF/EOL reasonable.
115            *
116            * The 'c', '<', '>', and '!' commands are special cases.  We ignore
117            * the final cursor position for all of them: for 'c', the text input
118            * routines set the cursor to the last character inserted; for '<',
119            * '>' and '!', the underlying ex commands that do the operation will
120            * set the cursor for us, usually to something related to the first
121            * <nonblank>.
122            */
123           MARK       m_start;           /* mark: initial cursor, range start. */
124           MARK       m_stop;            /* mark: range end. */
125           MARK       m_final;           /* mark: final cursor position. */
126 } VICMD;
127 
128 /* Vi command table structure. */
129 struct _vikeys {                        /* Underlying function. */
130           int        (*func) __P((SCR *, VICMD *));
131 #define   V_ABS               0x00004000          /* Absolute movement, set '' mark. */
132 #define   V_ABS_C             0x00008000          /* V_ABS: if the line/column changed. */
133 #define   V_ABS_L             0x00010000          /* V_ABS: if the line changed. */
134 #define   V_CHAR              0x00020000          /* Character (required, trailing). */
135 #define   V_CNT               0x00040000          /* Count (optional, leading). */
136 #define   V_DOT               0x00080000          /* On success, sets dot command. */
137 #define   V_KEYW              0x00100000          /* Cursor referenced word. */
138 #define   V_MOTION  0x00200000          /* Motion (required, trailing). */
139 #define   V_MOVE              0x00400000          /* Command defines movement. */
140 #define   V_OBUF              0x00800000          /* Buffer (optional, leading). */
141 #define   V_RBUF              0x01000000          /* Buffer (required, trailing). */
142 #define   V_SECURE  0x02000000          /* Permission denied if O_SECURE set. */
143           u_int32_t flags;
144           const char *usage;            /* Usage line. */
145           const char *help;             /* Help line. */
146 };
147 #define   MAXVIKEY  126                 /* List of vi commands. */
148 extern VIKEYS const vikeys[MAXVIKEY + 1];
149 extern VIKEYS const tmotion;            /* XXX Hacked ~ command. */
150 
151 /* Character stream structure, prototypes. */
152 typedef struct _vcs {
153           db_recno_t           cs_lno;            /* Line. */
154           size_t     cs_cno;            /* Column. */
155           CHAR_T    *cs_bp;                       /* Buffer. */
156           size_t     cs_len;            /* Length. */
157           ARG_CHAR_T cs_ch;             /* Character. */
158 #define   CS_EMP    1                             /* Empty line. */
159 #define   CS_EOF    2                             /* End-of-file. */
160 #define   CS_EOL    3                             /* End-of-line. */
161 #define   CS_SOF    4                             /* Start-of-file. */
162           int        cs_flags;                    /* Return flags. */
163 } VCS;
164 
165 int       cs_bblank __P((SCR *, VCS *));
166 int       cs_fblank __P((SCR *, VCS *));
167 int       cs_fspace __P((SCR *, VCS *));
168 int       cs_init __P((SCR *, VCS *));
169 int       cs_next __P((SCR *, VCS *));
170 int       cs_prev __P((SCR *, VCS *));
171 
172 /*
173  * We use a single "window" for each set of vi screens.  The model would be
174  * simpler with two windows (one for the text, and one for the modeline)
175  * because scrolling the text window down would work correctly then, not
176  * affecting the mode line.  As it is we have to play games to make it look
177  * right.  The reason for this choice is that it would be difficult for
178  * curses to optimize the movement, i.e. detect that the downward scroll
179  * isn't going to change the modeline, set the scrolling region on the
180  * terminal and only scroll the first part of the text window.
181  *
182  * Structure for mapping lines to the screen.  An SMAP is an array, with one
183  * structure element per screen line, which holds information describing the
184  * physical line which is displayed in the screen line.  The first two fields
185  * (lno and off) are all that are necessary to describe a line.  The rest of
186  * the information is useful to keep information from being re-calculated.
187  *
188  * The SMAP always has an entry for each line of the physical screen, plus a
189  * slot for the colon command line, so there is room to add any screen into
190  * another one at screen exit.
191  *
192  * Lno is the line number.  If doing the historic vi long line folding, soff
193  * is the screen offset into the line.  For example, the pair 2:1 would be
194  * the first screen of line 2, and 2:2 would be the second.  In the case of
195  * long lines, the screen map will tend to be staggered, e.g., 1:1, 1:2, 1:3,
196  * 2:1, 3:1, etc.  If doing left-right scrolling, the coff field is the screen
197  * column offset into the lines, and can take on any value, as it's adjusted
198  * by the user set value O_SIDESCROLL.
199  */
200 typedef struct _smap {
201           db_recno_t  lno;    /* 1-N: Physical file line number. */
202           size_t     coff;              /* 0-N: Column offset in the line. */
203           size_t     soff;              /* 1-N: Screen offset in the line. */
204 
205                                         /* vs_line() cache information. */
206           size_t     c_sboff; /* 0-N: offset of first character on screen. */
207           size_t     c_eboff; /* 0-N: offset of  last character on screen. */
208           u_int8_t c_scoff;   /* 0-N: offset into the first character. */
209                                         /* 255: no character of line visible. */
210           u_int8_t c_eclen;   /* 1-N: columns from the last character. */
211           u_int8_t c_ecsize;  /* 1-N: size of the last character. */
212 } SMAP;
213                                         /* Macros to flush/test cached information. */
214 #define   SMAP_CACHE(smp)               ((smp)->c_ecsize != 0)
215 #define   SMAP_FLUSH(smp)               ((smp)->c_ecsize = 0)
216 
217                                         /* Character search information. */
218 typedef enum { CNOTSET, FSEARCH, fSEARCH, TSEARCH, tSEARCH } cdir_t;
219 
220 typedef enum { AB_NOTSET, AB_NOTWORD, AB_INWORD } abb_t;
221 typedef enum { Q_NOTSET, Q_BNEXT, Q_BTHIS, Q_VNEXT, Q_VTHIS } quote_t;
222 
223 /* Vi private, per-screen memory. */
224 typedef struct _vi_private {
225           VICMD     cmd;                /* Current command, motion. */
226           VICMD     motion;
227 
228           /*
229            * !!!
230            * The saved command structure can be modified by the underlying
231            * vi functions, see v_Put() and v_put().
232            */
233           VICMD     sdot;               /* Saved dot, motion command. */
234           VICMD     sdotmotion;
235 
236           CHAR_T *keyw;                 /* Keyword buffer. */
237           size_t    klen;               /* Keyword length. */
238           size_t    keywlen;  /* Keyword buffer length. */
239 
240           CHAR_T    rlast;              /* Last 'r' replacement character. */
241           e_key_t   rvalue;             /* Value of last replacement character. */
242 
243           EVENT  *rep;                  /* Input replay buffer. */
244           size_t    rep_len;  /* Input replay buffer length. */
245           size_t    rep_cnt;  /* Input replay buffer characters. */
246 
247           mtype_t   mtype;              /* Last displayed message type. */
248           size_t    linecount;          /* 1-N: Output overwrite count. */
249           size_t    lcontinue;          /* 1-N: Output line continue value. */
250           size_t    totalcount;         /* 1-N: Output overwrite count. */
251 
252                                         /* Busy state. */
253           int       busy_ref; /* Busy reference count. */
254           int       busy_ch;  /* Busy character. */
255           size_t    busy_fx;  /* Busy character x coordinate. */
256           size_t    busy_oldy;          /* Saved y coordinate. */
257           size_t    busy_oldx;          /* Saved x coordinate. */
258           struct timeval busy_tv;       /* Busy timer. */
259 
260           MARK      sel;                /* Select start position. */
261 
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           db_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           db_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           db_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 "vi_extern.h"
387