119304Speter/*- 219304Speter * Copyright (c) 1992, 1993, 1994 319304Speter * The Regents of the University of California. All rights reserved. 419304Speter * Copyright (c) 1992, 1993, 1994, 1995, 1996 519304Speter * Keith Bostic. All rights reserved. 619304Speter * 719304Speter * See the LICENSE file for redistribution information. 819304Speter * 9254225Speter * $Id: vi.h,v 10.29 2012/02/11 00:33:46 zy Exp $ 1019304Speter */ 1119304Speter 1219304Speter/* Definition of a vi "word". */ 13254225Speter#define inword(ch) ((ch) == '_' || (ISGRAPH(ch) && !ISPUNCT(ch))) 1419304Speter 1519304Spetertypedef struct _vikeys VIKEYS; 1619304Speter 1719304Speter/* Structure passed around to functions implementing vi commands. */ 1819304Spetertypedef struct _vicmd { 1919304Speter CHAR_T key; /* Command key. */ 2019304Speter CHAR_T buffer; /* Buffer. */ 2119304Speter CHAR_T character; /* Character. */ 2219304Speter u_long count; /* Count. */ 2319304Speter u_long count2; /* Second count (only used by z). */ 2419304Speter EVENT ev; /* Associated event. */ 2519304Speter 2619304Speter#define ISCMD(p, key) ((p) == &vikeys[key]) 2719304Speter VIKEYS const *kp; /* Command/Motion VIKEYS entry. */ 2819304Speter#define ISMOTION(vp) (vp->rkp != NULL && F_ISSET(vp->rkp, V_MOTION)) 2919304Speter VIKEYS const *rkp; /* Related C/M VIKEYS entry. */ 3019304Speter 3119304Speter /* 3219304Speter * Historic vi allowed "dl" when the cursor was on the last column, 3319304Speter * deleting the last character, and similarly allowed "dw" when 3419304Speter * the cursor was on the last column of the file. It didn't allow 3519304Speter * "dh" when the cursor was on column 1, although these cases are 3619304Speter * not strictly analogous. The point is that some movements would 3719304Speter * succeed if they were associated with a motion command, and fail 3819304Speter * otherwise. This is part of the off-by-1 schizophrenia that 3919304Speter * plagued vi. Other examples are that "dfb" deleted everything 4019304Speter * up to and including the next 'b' character, while "d/b" deleted 4119304Speter * everything up to the next 'b' character. While this implementation 4219304Speter * regularizes the interface to the extent possible, there are many 4319304Speter * special cases that can't be fixed. The special cases are handled 4419304Speter * by setting flags per command so that the underlying command and 4519304Speter * motion routines know what's really going on. 4619304Speter * 4719304Speter * The VM_* flags are set in the vikeys array and by the underlying 4819304Speter * functions (motion component or command) as well. For this reason, 4919304Speter * the flags in the VICMD and VIKEYS structures live in the same name 5019304Speter * space. 5119304Speter */ 5219304Speter#define VM_CMDFAILED 0x00000001 /* Command failed. */ 5319304Speter#define VM_CUTREQ 0x00000002 /* Always cut into numeric buffers. */ 5419304Speter#define VM_LDOUBLE 0x00000004 /* Doubled command for line mode. */ 5519304Speter#define VM_LMODE 0x00000008 /* Motion is line oriented. */ 5619304Speter#define VM_COMMASK 0x0000000f /* Mask for VM flags. */ 5719304Speter 5819304Speter /* 5919304Speter * The VM_RCM_* flags are single usage, i.e. if you set one, you have 6019304Speter * to clear the others. 6119304Speter */ 6219304Speter#define VM_RCM 0x00000010 /* Use relative cursor movment (RCM). */ 6319304Speter#define VM_RCM_SET 0x00000020 /* RCM: set to current position. */ 6419304Speter#define VM_RCM_SETFNB 0x00000040 /* RCM: set to first non-blank (FNB). */ 6519304Speter#define VM_RCM_SETLAST 0x00000080 /* RCM: set to last character. */ 6619304Speter#define VM_RCM_SETNNB 0x00000100 /* RCM: set to next non-blank. */ 6719304Speter#define VM_RCM_MASK 0x000001f0 /* Mask for RCM flags. */ 6819304Speter 6919304Speter /* Flags for the underlying function. */ 7019304Speter#define VC_BUFFER 0x00000200 /* The buffer was set. */ 7119304Speter#define VC_C1RESET 0x00000400 /* Reset C1SET flag for dot commands. */ 7219304Speter#define VC_C1SET 0x00000800 /* Count 1 was set. */ 7319304Speter#define VC_C2SET 0x00001000 /* Count 2 was set. */ 7419304Speter#define VC_ISDOT 0x00002000 /* Command was the dot command. */ 7519304Speter u_int32_t flags; 7619304Speter 7719304Speter /* 7819304Speter * There are four cursor locations that we worry about: the initial 7919304Speter * cursor position, the start of the range, the end of the range, 8019304Speter * and the final cursor position. The initial cursor position and 8119304Speter * the start of the range are both m_start, and are always the same. 8219304Speter * All locations are initialized to the starting cursor position by 8319304Speter * the main vi routines, and the underlying functions depend on this. 8419304Speter * 8519304Speter * Commands that can be motion components set the end of the range 8619304Speter * cursor position, m_stop. All commands must set the ending cursor 8719304Speter * position, m_final. The reason that m_stop isn't the same as m_final 8819304Speter * is that there are situations where the final position of the cursor 8919304Speter * is outside of the cut/delete range (e.g. 'd[[' from the first column 9019304Speter * of a line). The final cursor position often varies based on the 9119304Speter * direction of the movement, as well as the command. The only special 9219304Speter * case that the delete code handles is that it will make adjustments 9319304Speter * if the final cursor position is deleted. 9419304Speter * 9519304Speter * The reason for all of this is that the historic vi semantics were 9619304Speter * defined command-by-command. Every function has to roll its own 9719304Speter * starting and stopping positions, and adjust them if it's being used 9819304Speter * as a motion component. The general rules are as follows: 9919304Speter * 10019304Speter * 1: If not a motion component, the final cursor is at the end 10119304Speter * of the range. 10219304Speter * 2: If moving backward in the file, delete and yank move the 10319304Speter * final cursor to the end of the range. 10419304Speter * 3: If moving forward in the file, delete and yank leave the 10519304Speter * final cursor at the start of the range. 10619304Speter * 10719304Speter * Usually, if moving backward in the file and it's a motion component, 10819304Speter * the starting cursor is decremented by a single character (or, in a 10919304Speter * few cases, to the end of the previous line) so that the starting 11019304Speter * cursor character isn't cut or deleted. No cursor adjustment is 11119304Speter * needed for moving forward, because the cut/delete routines handle 11219304Speter * m_stop inclusively, i.e. the last character in the range is cut or 11319304Speter * deleted. This makes cutting to the EOF/EOL reasonable. 11419304Speter * 11519304Speter * The 'c', '<', '>', and '!' commands are special cases. We ignore 11619304Speter * the final cursor position for all of them: for 'c', the text input 11719304Speter * routines set the cursor to the last character inserted; for '<', 11819304Speter * '>' and '!', the underlying ex commands that do the operation will 11919304Speter * set the cursor for us, usually to something related to the first 12019304Speter * <nonblank>. 12119304Speter */ 12219304Speter MARK m_start; /* mark: initial cursor, range start. */ 12319304Speter MARK m_stop; /* mark: range end. */ 12419304Speter MARK m_final; /* mark: final cursor position. */ 12519304Speter} VICMD; 12619304Speter 12719304Speter/* Vi command table structure. */ 12819304Speterstruct _vikeys { /* Underlying function. */ 129281373Sbapt int (*func)(SCR *, VICMD *); 13019304Speter#define V_ABS 0x00004000 /* Absolute movement, set '' mark. */ 13119304Speter#define V_ABS_C 0x00008000 /* V_ABS: if the line/column changed. */ 13219304Speter#define V_ABS_L 0x00010000 /* V_ABS: if the line changed. */ 13319304Speter#define V_CHAR 0x00020000 /* Character (required, trailing). */ 13419304Speter#define V_CNT 0x00040000 /* Count (optional, leading). */ 13519304Speter#define V_DOT 0x00080000 /* On success, sets dot command. */ 13619304Speter#define V_KEYW 0x00100000 /* Cursor referenced word. */ 13719304Speter#define V_MOTION 0x00200000 /* Motion (required, trailing). */ 13819304Speter#define V_MOVE 0x00400000 /* Command defines movement. */ 13919304Speter#define V_OBUF 0x00800000 /* Buffer (optional, leading). */ 14019304Speter#define V_RBUF 0x01000000 /* Buffer (required, trailing). */ 14119304Speter#define V_SECURE 0x02000000 /* Permission denied if O_SECURE set. */ 14219304Speter u_int32_t flags; 14319304Speter char *usage; /* Usage line. */ 14419304Speter char *help; /* Help line. */ 14519304Speter}; 14619304Speter#define MAXVIKEY 126 /* List of vi commands. */ 14719304Speterextern VIKEYS const vikeys[MAXVIKEY + 1]; 14819304Speterextern VIKEYS const tmotion; /* XXX Hacked ~ command. */ 14919304Speter 15019304Speter/* Character stream structure, prototypes. */ 15119304Spetertypedef struct _vcs { 15219304Speter recno_t cs_lno; /* Line. */ 15319304Speter size_t cs_cno; /* Column. */ 15419304Speter CHAR_T *cs_bp; /* Buffer. */ 15519304Speter size_t cs_len; /* Length. */ 15619304Speter CHAR_T cs_ch; /* Character. */ 15719304Speter#define CS_EMP 1 /* Empty line. */ 15819304Speter#define CS_EOF 2 /* End-of-file. */ 15919304Speter#define CS_EOL 3 /* End-of-line. */ 16019304Speter#define CS_SOF 4 /* Start-of-file. */ 16119304Speter int cs_flags; /* Return flags. */ 16219304Speter} VCS; 16319304Speter 164281373Sbaptint cs_bblank(SCR *, VCS *); 165281373Sbaptint cs_fblank(SCR *, VCS *); 166281373Sbaptint cs_fspace(SCR *, VCS *); 167281373Sbaptint cs_init(SCR *, VCS *); 168281373Sbaptint cs_next(SCR *, VCS *); 169281373Sbaptint cs_prev(SCR *, VCS *); 17019304Speter 17119304Speter/* 17219304Speter * We use a single "window" for each set of vi screens. The model would be 17319304Speter * simpler with two windows (one for the text, and one for the modeline) 17419304Speter * because scrolling the text window down would work correctly then, not 17519304Speter * affecting the mode line. As it is we have to play games to make it look 17619304Speter * right. The reason for this choice is that it would be difficult for 17719304Speter * curses to optimize the movement, i.e. detect that the downward scroll 17819304Speter * isn't going to change the modeline, set the scrolling region on the 17919304Speter * terminal and only scroll the first part of the text window. 18019304Speter * 18119304Speter * Structure for mapping lines to the screen. An SMAP is an array, with one 18219304Speter * structure element per screen line, which holds information describing the 18319304Speter * physical line which is displayed in the screen line. The first two fields 18419304Speter * (lno and off) are all that are necessary to describe a line. The rest of 18519304Speter * the information is useful to keep information from being re-calculated. 18619304Speter * 18719304Speter * The SMAP always has an entry for each line of the physical screen, plus a 18819304Speter * slot for the colon command line, so there is room to add any screen into 18919304Speter * another one at screen exit. 19019304Speter * 191254225Speter * Lno is the line number. If doing the historic vi long line folding, soff 19219304Speter * is the screen offset into the line. For example, the pair 2:1 would be 19319304Speter * the first screen of line 2, and 2:2 would be the second. In the case of 19419304Speter * long lines, the screen map will tend to be staggered, e.g., 1:1, 1:2, 1:3, 195254225Speter * 2:1, 3:1, etc. If doing left-right scrolling, the coff field is the screen 19619304Speter * column offset into the lines, and can take on any value, as it's adjusted 19719304Speter * by the user set value O_SIDESCROLL. 19819304Speter */ 19919304Spetertypedef struct _smap { 200254225Speter recno_t lno; /* 1-N: Physical file line number. */ 20119304Speter size_t coff; /* 0-N: Column offset in the line. */ 20219304Speter size_t soff; /* 1-N: Screen offset in the line. */ 20319304Speter 20419304Speter /* vs_line() cache information. */ 205254225Speter size_t c_sboff; /* 0-N: offset of first character on screen. */ 206254225Speter size_t c_eboff; /* 0-N: offset of last character on screen. */ 20719304Speter u_int8_t c_scoff; /* 0-N: offset into the first character. */ 208254225Speter /* 255: no character of line visible. */ 20919304Speter u_int8_t c_eclen; /* 1-N: columns from the last character. */ 21019304Speter u_int8_t c_ecsize; /* 1-N: size of the last character. */ 21119304Speter} SMAP; 21219304Speter /* Macros to flush/test cached information. */ 21319304Speter#define SMAP_CACHE(smp) ((smp)->c_ecsize != 0) 21419304Speter#define SMAP_FLUSH(smp) ((smp)->c_ecsize = 0) 21519304Speter 21619304Speter /* Character search information. */ 21719304Spetertypedef enum { CNOTSET, FSEARCH, fSEARCH, TSEARCH, tSEARCH } cdir_t; 21819304Speter 21919304Spetertypedef enum { AB_NOTSET, AB_NOTWORD, AB_INWORD } abb_t; 22019304Spetertypedef enum { Q_NOTSET, Q_BNEXT, Q_BTHIS, Q_VNEXT, Q_VTHIS } quote_t; 22119304Speter 22219304Speter/* Vi private, per-screen memory. */ 22319304Spetertypedef struct _vi_private { 22419304Speter VICMD cmd; /* Current command, motion. */ 22519304Speter VICMD motion; 22619304Speter 22719304Speter /* 22819304Speter * !!! 22919304Speter * The saved command structure can be modified by the underlying 23019304Speter * vi functions, see v_Put() and v_put(). 23119304Speter */ 23219304Speter VICMD sdot; /* Saved dot, motion command. */ 23319304Speter VICMD sdotmotion; 23419304Speter 23519304Speter CHAR_T *keyw; /* Keyword buffer. */ 23619304Speter size_t klen; /* Keyword length. */ 23719304Speter size_t keywlen; /* Keyword buffer length. */ 23819304Speter 23919304Speter CHAR_T rlast; /* Last 'r' replacement character. */ 24019304Speter e_key_t rvalue; /* Value of last replacement character. */ 24119304Speter 24219304Speter EVENT *rep; /* Input replay buffer. */ 24319304Speter size_t rep_len; /* Input replay buffer length. */ 24419304Speter size_t rep_cnt; /* Input replay buffer characters. */ 24519304Speter 24619304Speter mtype_t mtype; /* Last displayed message type. */ 24719304Speter size_t linecount; /* 1-N: Output overwrite count. */ 24819304Speter size_t lcontinue; /* 1-N: Output line continue value. */ 24919304Speter size_t totalcount; /* 1-N: Output overwrite count. */ 25019304Speter 25119304Speter /* Busy state. */ 25219304Speter int busy_ref; /* Busy reference count. */ 25319304Speter int busy_ch; /* Busy character. */ 25419304Speter size_t busy_fx; /* Busy character x coordinate. */ 25519304Speter size_t busy_oldy; /* Saved y coordinate. */ 25619304Speter size_t busy_oldx; /* Saved x coordinate. */ 257254225Speter struct timespec busy_ts;/* Busy timer. */ 25819304Speter 259254225Speter MARK sel; /* Select start position. */ 260254225Speter 261254225Speter CHAR_T *mcs; /* Match character list. */ 26219304Speter char *ps; /* Paragraph plus section list. */ 26319304Speter 26419304Speter u_long u_ccnt; /* Undo command count. */ 26519304Speter 26619304Speter CHAR_T lastckey; /* Last search character. */ 26719304Speter cdir_t csearchdir; /* Character search direction. */ 26819304Speter 26919304Speter SMAP *h_smap; /* First slot of the line map. */ 27019304Speter SMAP *t_smap; /* Last slot of the line map. */ 27119304Speter 27219304Speter /* 27319304Speter * One extra slot is always allocated for the map so that we can use 27419304Speter * it to do vi :colon command input; see v_tcmd(). 27519304Speter */ 27619304Speter recno_t sv_tm_lno; /* tcmd: saved TMAP lno field. */ 27719304Speter size_t sv_tm_coff; /* tcmd: saved TMAP coff field. */ 27819304Speter size_t sv_tm_soff; /* tcmd: saved TMAP soff field. */ 27919304Speter size_t sv_t_maxrows; /* tcmd: saved t_maxrows. */ 28019304Speter size_t sv_t_minrows; /* tcmd: saved t_minrows. */ 28119304Speter size_t sv_t_rows; /* tcmd: saved t_rows. */ 28219304Speter#define SIZE_HMAP(sp) (VIP(sp)->srows + 1) 28319304Speter 28419304Speter /* 28519304Speter * Macros to get to the head/tail of the smap. If the screen only has 28619304Speter * one line, HMAP can be equal to TMAP, so the code has to understand 28719304Speter * the off-by-one errors that can result. If stepping through an SMAP 28819304Speter * and operating on each entry, use sp->t_rows as the count of slots, 28919304Speter * don't use a loop that compares <= TMAP. 29019304Speter */ 29119304Speter#define _HMAP(sp) (VIP(sp)->h_smap) 29219304Speter#define HMAP _HMAP(sp) 29319304Speter#define _TMAP(sp) (VIP(sp)->t_smap) 29419304Speter#define TMAP _TMAP(sp) 29519304Speter 29619304Speter recno_t ss_lno; /* 1-N: vi_opt_screens cached line number. */ 29719304Speter size_t ss_screens; /* vi_opt_screens cached return value. */ 29819304Speter#define VI_SCR_CFLUSH(vip) vip->ss_lno = OOBLNO 29919304Speter 30019304Speter size_t srows; /* 1-N: rows in the terminal/window. */ 30119304Speter recno_t olno; /* 1-N: old cursor file line. */ 30219304Speter size_t ocno; /* 0-N: old file cursor column. */ 30319304Speter size_t sc_col; /* 0-N: LOGICAL screen column. */ 30419304Speter SMAP *sc_smap; /* SMAP entry where sc_col occurs. */ 30519304Speter 30619304Speter#define VIP_CUR_INVALID 0x0001 /* Cursor position is unknown. */ 30719304Speter#define VIP_DIVIDER 0x0002 /* Divider line was displayed. */ 30819304Speter#define VIP_N_EX_PAINT 0x0004 /* Clear and repaint when ex finishes. */ 30919304Speter#define VIP_N_EX_REDRAW 0x0008 /* Schedule SC_SCR_REDRAW when ex finishes. */ 31019304Speter#define VIP_N_REFRESH 0x0010 /* Repaint (from SMAP) on the next refresh. */ 31119304Speter#define VIP_N_RENUMBER 0x0020 /* Renumber screen on the next refresh. */ 31219304Speter#define VIP_RCM_LAST 0x0040 /* Cursor drawn to the last column. */ 31319304Speter#define VIP_S_MODELINE 0x0080 /* Skip next modeline refresh. */ 31419304Speter#define VIP_S_REFRESH 0x0100 /* Skip next refresh. */ 31519304Speter u_int16_t flags; 31619304Speter} VI_PRIVATE; 31719304Speter 31819304Speter/* Vi private area. */ 31919304Speter#define VIP(sp) ((VI_PRIVATE *)((sp)->vi_private)) 32019304Speter 32119304Speter#define O_NUMBER_FMT "%7lu " /* O_NUMBER format, length. */ 32219304Speter#define O_NUMBER_LENGTH 8 32319304Speter#define SCREEN_COLS(sp) /* Screen columns. */ \ 32419304Speter ((O_ISSET(sp, O_NUMBER) ? (sp)->cols - O_NUMBER_LENGTH : (sp)->cols)) 32519304Speter 32619304Speter/* 32719304Speter * LASTLINE is the zero-based, last line in the screen. Note that it is correct 32819304Speter * regardless of the changes in the screen to permit text input on the last line 32919304Speter * of the screen, or the existence of small screens. 33019304Speter */ 33119304Speter#define LASTLINE(sp) \ 33219304Speter ((sp)->t_maxrows < (sp)->rows ? (sp)->t_maxrows : (sp)->rows - 1) 33319304Speter 33419304Speter/* 33519304Speter * Small screen (see vs_refresh.c, section 6a) and one-line screen test. 33619304Speter * Note, both cannot be true for the same screen. 33719304Speter */ 33819304Speter#define IS_SMALL(sp) ((sp)->t_minrows != (sp)->t_maxrows) 33919304Speter#define IS_ONELINE(sp) ((sp)->rows == 1) 34019304Speter 34119304Speter#define HALFTEXT(sp) /* Half text. */ \ 34219304Speter ((sp)->t_rows == 1 ? 1 : (sp)->t_rows / 2) 34319304Speter#define HALFSCREEN(sp) /* Half text screen. */ \ 34419304Speter ((sp)->t_maxrows == 1 ? 1 : (sp)->t_maxrows / 2) 34519304Speter 34619304Speter/* 34719304Speter * Next tab offset. 34819304Speter * 34919304Speter * !!! 35019304Speter * There are problems with how the historical vi handled tabs. For example, 35119304Speter * by doing "set ts=3" and building lines that fold, you can get it to step 35219304Speter * through tabs as if they were spaces and move inserted characters to new 35319304Speter * positions when <esc> is entered. I believe that nvi does tabs correctly, 35419304Speter * but there are some historical incompatibilities. 35519304Speter */ 35619304Speter#define TAB_OFF(c) COL_OFF((c), O_VAL(sp, O_TABSTOP)) 35719304Speter 358254225Speter/* If more than one horizontal screen being shown. */ 359254225Speter#define IS_HSPLIT(sp) \ 360254225Speter ((sp)->rows != O_VAL(sp, O_LINES)) 361254225Speter/* If more than one vertical screen being shown. */ 362254225Speter#define IS_VSPLIT(sp) \ 363254225Speter ((sp)->cols != O_VAL(sp, O_COLUMNS)) 36419304Speter/* If more than one screen being shown. */ 36519304Speter#define IS_SPLIT(sp) \ 366254225Speter (IS_HSPLIT(sp) || IS_VSPLIT(sp)) 36719304Speter 36819304Speter/* Screen adjustment operations. */ 36919304Spetertypedef enum { A_DECREASE, A_INCREASE, A_SET } adj_t; 37019304Speter 37119304Speter/* Screen position operations. */ 37219304Spetertypedef enum { P_BOTTOM, P_FILL, P_MIDDLE, P_TOP } pos_t; 37319304Speter 37419304Speter/* Scrolling operations. */ 37519304Spetertypedef enum { 37619304Speter CNTRL_B, CNTRL_D, CNTRL_E, CNTRL_F, 37719304Speter CNTRL_U, CNTRL_Y, Z_CARAT, Z_PLUS 37819304Speter} scroll_t; 37919304Speter 38019304Speter/* Vi common error messages. */ 38119304Spetertypedef enum { 38219304Speter VIM_COMBUF, VIM_EMPTY, VIM_EOF, VIM_EOL, 38319304Speter VIM_NOCOM, VIM_NOCOM_B, VIM_USAGE, VIM_WRESIZE 38419304Speter} vim_t; 38519304Speter 386254225Speter#include "extern.h" 387