1 /*-
2 * Copyright (c) 1991, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
4 * Copyright (c) 1991, 1993, 1994, 1995, 1996
5 * Keith Bostic. All rights reserved.
6 *
7 * See the LICENSE file for redistribution information.
8 */
9
10 #include "multibyte.h"
11
12 #ifdef USE_WIDECHAR
13 #define FILE2INT5(sp,buf,n,nlen,w,wlen) \
14 sp->conv.file2int(sp, n, nlen, &buf, &wlen, &w)
15 #define INT2FILE(sp,w,wlen,n,nlen) \
16 sp->conv.int2file(sp, w, wlen, &sp->cw, &nlen, &n)
17 #define CHAR2INT5(sp,buf,n,nlen,w,wlen) \
18 sp->conv.sys2int(sp, n, nlen, &buf, &wlen, &w)
19 #define INT2CHAR(sp,w,wlen,n,nlen) \
20 sp->conv.int2sys(sp, w, wlen, &sp->cw, &nlen, &n)
21 #define INPUT2INT5(sp,cw,n,nlen,w,wlen) \
22 sp->conv.input2int(sp, n, nlen, &(cw), &wlen, &w)
23 #define CONST
24 #define INTISWIDE(c) (wctob(c) == EOF)
25 #define CHAR_WIDTH(sp, ch) wcwidth(ch)
26 #define CAN_PRINT(sp, ch) (CHAR_WIDTH(sp, ch) > 0)
27 #else
28 #define FILE2INT5(sp,buf,n,nlen,w,wlen) \
29 (w = n, wlen = nlen, 0)
30 #define INT2FILE(sp,w,wlen,n,nlen) \
31 (n = w, nlen = wlen, 0)
32 #define CHAR2INT5(sp,buf,n,nlen,w,wlen) \
33 (w = n, wlen = nlen, 0)
34 #define INT2CHAR(sp,w,wlen,n,nlen) \
35 (n = w, nlen = wlen, 0)
36 #define INPUT2INT5(sp,buf,n,nlen,w,wlen) \
37 (w = n, wlen = nlen, 0)
38 #define CONST const
39 #define INTISWIDE(c) 0
40 #define CHAR_WIDTH(sp, ch) 1
41 #define CAN_PRINT(sp, ch) isprint(ch)
42 #endif
43 #define FILE2INT(sp,n,nlen,w,wlen) \
44 FILE2INT5(sp,sp->cw,n,nlen,w,wlen)
45 #define CHAR2INT(sp,n,nlen,w,wlen) \
46 CHAR2INT5(sp,sp->cw,n,nlen,w,wlen)
47
48 /* The maximum number of columns any character can take up on a screen. */
49 #define MAX_CHARACTER_COLUMNS 7
50
51 /*
52 * Event types.
53 *
54 * The program structure depends on the event loop being able to return
55 * E_EOF/E_ERR multiple times -- eventually enough things will end due
56 * to the events that vi will reach the command level for the screen, at
57 * which point the exit flags will be set and vi will exit.
58 */
59 typedef enum {
60 E_NOTUSED = 0, /* Not set. */
61 E_CHARACTER, /* Input character: e_c set. */
62 E_EOF, /* End of input (NOT ^D). */
63 E_ERR, /* Input error. */
64 E_INTERRUPT, /* Interrupt. */
65 E_REPAINT, /* Repaint: e_flno, e_tlno set. */
66 E_SIGHUP, /* SIGHUP. */
67 E_SIGTERM, /* SIGTERM. */
68 E_STRING, /* Input string: e_csp, e_len set. */
69 E_TIMEOUT, /* Timeout. */
70 E_WRESIZE, /* Window resize. */
71 } e_event_t;
72
73 /*
74 * Character values.
75 */
76 typedef enum {
77 K_NOTUSED = 0, /* Not set. */
78 K_BACKSLASH, /* \ */
79 K_CARAT, /* ^ */
80 K_CNTRLD, /* ^D */
81 K_CNTRLR, /* ^R */
82 K_CNTRLT, /* ^T */
83 K_CNTRLZ, /* ^Z */
84 K_COLON, /* : */
85 K_CR, /* \r */
86 K_ESCAPE, /* ^[ */
87 K_FORMFEED, /* \f */
88 K_HEXCHAR, /* ^X */
89 K_NL, /* \n */
90 K_RIGHTBRACE, /* } */
91 K_RIGHTPAREN, /* ) */
92 K_TAB, /* \t */
93 K_VERASE, /* set from tty: default ^H */
94 K_VKILL, /* set from tty: default ^U */
95 K_VLNEXT, /* set from tty: default ^V */
96 K_VWERASE, /* set from tty: default ^W */
97 K_ZERO /* 0 */
98 } e_key_t;
99
100 struct _event {
101 TAILQ_ENTRY(_event) q; /* Linked list of events. */
102 e_event_t e_event; /* Event type. */
103 union {
104 struct { /* Input character. */
105 CHAR_T c; /* Character. */
106 e_key_t value; /* Key type. */
107
108 #define CH_ABBREVIATED 0x01 /* Character is from an abbreviation. */
109 #define CH_MAPPED 0x02 /* Character is from a map. */
110 #define CH_NOMAP 0x04 /* Do not map the character. */
111 #define CH_QUOTED 0x08 /* Character is already quoted. */
112 u_int8_t flags;
113 } _e_ch;
114 #define e_ch _u_event._e_ch /* !!! The structure, not the char. */
115 #define e_c _u_event._e_ch.c
116 #define e_value _u_event._e_ch.value
117 #define e_flags _u_event._e_ch.flags
118
119 struct { /* Screen position, size. */
120 size_t lno1; /* Line number. */
121 size_t cno1; /* Column number. */
122 size_t lno2; /* Line number. */
123 size_t cno2; /* Column number. */
124 } _e_mark;
125 #define e_lno _u_event._e_mark.lno1 /* Single location. */
126 #define e_cno _u_event._e_mark.cno1
127 #define e_flno _u_event._e_mark.lno1 /* Text region. */
128 #define e_fcno _u_event._e_mark.cno1
129 #define e_tlno _u_event._e_mark.lno2
130 #define e_tcno _u_event._e_mark.cno2
131
132 struct { /* Input string. */
133 CHAR_T *asp; /* Allocated string. */
134 CHAR_T *csp; /* String. */
135 size_t len; /* String length. */
136 } _e_str;
137 #define e_asp _u_event._e_str.asp
138 #define e_csp _u_event._e_str.csp
139 #define e_len _u_event._e_str.len
140 } _u_event;
141 };
142
143 typedef struct _keylist {
144 e_key_t value; /* Special value. */
145 int ch; /* Key. */
146 } KEYLIST;
147 extern KEYLIST keylist[];
148
149 /* Return if more keys in queue. */
150 #define KEYS_WAITING(sp) ((sp)->gp->i_cnt != 0)
151 #define MAPPED_KEYS_WAITING(sp) \
152 (KEYS_WAITING(sp) && \
153 F_ISSET(&sp->gp->i_event[sp->gp->i_next].e_ch, CH_MAPPED))
154
155 /*
156 * Ex/vi commands are generally separated by whitespace characters. We
157 * can't use the standard isspace(3) macro because it returns true for
158 * characters like ^K in the ASCII character set. The POSIX isblank(3)
159 * has the same problem for non-ASCII locale, so we need a standalone one.
160 */
161
162 static __inline int
cmdskip(CHAR_T ch)163 cmdskip(CHAR_T ch)
164 {
165 return ch == ' ' || ch == '\t';
166 }
167
168 /* The "standard" tab width, for displaying things to users. */
169 #define STANDARD_TAB 6
170
171 /* Various special characters, messages. */
172 #define CH_BSEARCH '?' /* Backward search prompt. */
173 #define CH_CURSOR ' ' /* Cursor character. */
174 #define CH_ENDMARK '$' /* End of a range. */
175 #define CH_EXPROMPT ':' /* Ex prompt. */
176 #define CH_FSEARCH '/' /* Forward search prompt. */
177 #define CH_HEX '\030' /* Leading hex character. */
178 #define CH_LITERAL '\026' /* ASCII ^V. */
179 #define CH_NO 'n' /* No. */
180 #define CH_NOT_DIGIT 'a' /* A non-isdigit() character. */
181 #define CH_QUIT 'q' /* Quit. */
182 #define CH_YES 'y' /* Yes. */
183
184 /*
185 * Checking for interrupts means that we look at the bit that gets set if the
186 * screen code supports asynchronous events, and call back into the event code
187 * so that non-asynchronous screens get a chance to post the interrupt.
188 *
189 * INTERRUPT_CHECK is the number of lines "operated" on before checking for
190 * interrupts.
191 */
192 #define INTERRUPT_CHECK 100
193 #define INTERRUPTED(sp) \
194 (F_ISSET((sp)->gp, G_INTERRUPTED) || \
195 (!v_event_get(sp, NULL, 0, EC_INTERRUPT) && \
196 F_ISSET((sp)->gp, G_INTERRUPTED)))
197 #define CLR_INTERRUPT(sp) \
198 F_CLR((sp)->gp, G_INTERRUPTED)
199
200 /* Flags describing types of characters being requested. */
201 #define EC_INTERRUPT 0x001 /* Checking for interrupts. */
202 #define EC_MAPCOMMAND 0x002 /* Apply the command map. */
203 #define EC_MAPINPUT 0x004 /* Apply the input map. */
204 #define EC_MAPNODIGIT 0x008 /* Return to a digit. */
205 #define EC_QUOTED 0x010 /* Try to quote next character */
206 #define EC_RAW 0x020 /* Any next character. XXX: not used. */
207 #define EC_TIMEOUT 0x040 /* Timeout to next character. */
208
209 /* Flags describing text input special cases. */
210 #define TXT_ADDNEWLINE 0x00000001 /* Replay starts on a new line. */
211 #define TXT_AICHARS 0x00000002 /* Leading autoindent chars. */
212 #define TXT_ALTWERASE 0x00000004 /* Option: altwerase. */
213 #define TXT_APPENDEOL 0x00000008 /* Appending after EOL. */
214 #define TXT_AUTOINDENT 0x00000010 /* Autoindent set this line. */
215 #define TXT_BACKSLASH 0x00000020 /* Backslashes escape characters. */
216 #define TXT_BEAUTIFY 0x00000040 /* Only printable characters. */
217 #define TXT_BS 0x00000080 /* Backspace returns the buffer. */
218 #define TXT_CEDIT 0x00000100 /* Can return TERM_CEDIT. */
219 #define TXT_CNTRLD 0x00000200 /* Control-D is a command. */
220 #define TXT_CNTRLT 0x00000400 /* Control-T is an indent special. */
221 #define TXT_CR 0x00000800 /* CR returns the buffer. */
222 #define TXT_DOTTERM 0x00001000 /* Leading '.' terminates the input. */
223 #define TXT_EMARK 0x00002000 /* End of replacement mark. */
224 #define TXT_EOFCHAR 0x00004000 /* ICANON set, return EOF character. */
225 #define TXT_ESCAPE 0x00008000 /* Escape returns the buffer. */
226 #define TXT_FILEC 0x00010000 /* Option: filec. */
227 #define TXT_INFOLINE 0x00020000 /* Editing the info line. */
228 #define TXT_MAPINPUT 0x00040000 /* Apply the input map. */
229 #define TXT_NLECHO 0x00080000 /* Echo the newline. */
230 #define TXT_NUMBER 0x00100000 /* Number the line. */
231 #define TXT_OVERWRITE 0x00200000 /* Overwrite characters. */
232 #define TXT_PROMPT 0x00400000 /* Display a prompt. */
233 #define TXT_RECORD 0x00800000 /* Record for replay. */
234 #define TXT_REPLACE 0x01000000 /* Replace; don't delete overwrite. */
235 #define TXT_REPLAY 0x02000000 /* Replay the last input. */
236 #define TXT_RESOLVE 0x04000000 /* Resolve the text into the file. */
237 #define TXT_SEARCHINCR 0x08000000 /* Incremental search. */
238 #define TXT_SHOWMATCH 0x10000000 /* Option: showmatch. */
239 #define TXT_TTYWERASE 0x20000000 /* Option: ttywerase. */
240 #define TXT_WRAPMARGIN 0x40000000 /* Option: wrapmargin. */
241