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