1 |
|
|
/* $OpenBSD: input.c,v 1.102 2016/07/15 00:42:56 nicm Exp $ */ |
2 |
|
|
|
3 |
|
|
/* |
4 |
|
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> |
5 |
|
|
* |
6 |
|
|
* Permission to use, copy, modify, and distribute this software for any |
7 |
|
|
* purpose with or without fee is hereby granted, provided that the above |
8 |
|
|
* copyright notice and this permission notice appear in all copies. |
9 |
|
|
* |
10 |
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
11 |
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
12 |
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
13 |
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
14 |
|
|
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER |
15 |
|
|
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING |
16 |
|
|
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
17 |
|
|
*/ |
18 |
|
|
|
19 |
|
|
#include <sys/types.h> |
20 |
|
|
|
21 |
|
|
#include <stdlib.h> |
22 |
|
|
#include <string.h> |
23 |
|
|
#include <time.h> |
24 |
|
|
|
25 |
|
|
#include "tmux.h" |
26 |
|
|
|
27 |
|
|
/* |
28 |
|
|
* Based on the description by Paul Williams at: |
29 |
|
|
* |
30 |
|
|
* http://vt100.net/emu/dec_ansi_parser |
31 |
|
|
* |
32 |
|
|
* With the following changes: |
33 |
|
|
* |
34 |
|
|
* - 7-bit only. |
35 |
|
|
* |
36 |
|
|
* - Support for UTF-8. |
37 |
|
|
* |
38 |
|
|
* - OSC (but not APC) may be terminated by \007 as well as ST. |
39 |
|
|
* |
40 |
|
|
* - A state for APC similar to OSC. Some terminals appear to use this to set |
41 |
|
|
* the title. |
42 |
|
|
* |
43 |
|
|
* - A state for the screen \033k...\033\\ sequence to rename a window. This is |
44 |
|
|
* pretty stupid but not supporting it is more trouble than it is worth. |
45 |
|
|
* |
46 |
|
|
* - Special handling for ESC inside a DCS to allow arbitrary byte sequences to |
47 |
|
|
* be passed to the underlying terminals. |
48 |
|
|
*/ |
49 |
|
|
|
50 |
|
|
/* Input parser cell. */ |
51 |
|
|
struct input_cell { |
52 |
|
|
struct grid_cell cell; |
53 |
|
|
int set; |
54 |
|
|
int g0set; /* 1 if ACS */ |
55 |
|
|
int g1set; /* 1 if ACS */ |
56 |
|
|
}; |
57 |
|
|
|
58 |
|
|
/* Input parser context. */ |
59 |
|
|
struct input_ctx { |
60 |
|
|
struct window_pane *wp; |
61 |
|
|
struct screen_write_ctx ctx; |
62 |
|
|
|
63 |
|
|
struct input_cell cell; |
64 |
|
|
|
65 |
|
|
struct input_cell old_cell; |
66 |
|
|
u_int old_cx; |
67 |
|
|
u_int old_cy; |
68 |
|
|
|
69 |
|
|
u_char interm_buf[4]; |
70 |
|
|
size_t interm_len; |
71 |
|
|
|
72 |
|
|
u_char param_buf[64]; |
73 |
|
|
size_t param_len; |
74 |
|
|
|
75 |
|
|
#define INPUT_BUF_START 32 |
76 |
|
|
#define INPUT_BUF_LIMIT 1048576 |
77 |
|
|
u_char *input_buf; |
78 |
|
|
size_t input_len; |
79 |
|
|
size_t input_space; |
80 |
|
|
|
81 |
|
|
int param_list[24]; /* -1 not present */ |
82 |
|
|
u_int param_list_len; |
83 |
|
|
|
84 |
|
|
struct utf8_data utf8data; |
85 |
|
|
|
86 |
|
|
int ch; |
87 |
|
|
int flags; |
88 |
|
|
#define INPUT_DISCARD 0x1 |
89 |
|
|
|
90 |
|
|
const struct input_state *state; |
91 |
|
|
|
92 |
|
|
/* |
93 |
|
|
* All input received since we were last in the ground state. Sent to |
94 |
|
|
* control clients on connection. |
95 |
|
|
*/ |
96 |
|
|
struct evbuffer *since_ground; |
97 |
|
|
}; |
98 |
|
|
|
99 |
|
|
/* Helper functions. */ |
100 |
|
|
struct input_transition; |
101 |
|
|
int input_split(struct input_ctx *); |
102 |
|
|
int input_get(struct input_ctx *, u_int, int, int); |
103 |
|
|
void printflike(2, 3) input_reply(struct input_ctx *, const char *, ...); |
104 |
|
|
void input_set_state(struct window_pane *, const struct input_transition *); |
105 |
|
|
void input_reset_cell(struct input_ctx *); |
106 |
|
|
|
107 |
|
|
/* Transition entry/exit handlers. */ |
108 |
|
|
void input_clear(struct input_ctx *); |
109 |
|
|
void input_ground(struct input_ctx *); |
110 |
|
|
void input_enter_osc(struct input_ctx *); |
111 |
|
|
void input_exit_osc(struct input_ctx *); |
112 |
|
|
void input_enter_apc(struct input_ctx *); |
113 |
|
|
void input_exit_apc(struct input_ctx *); |
114 |
|
|
void input_enter_rename(struct input_ctx *); |
115 |
|
|
void input_exit_rename(struct input_ctx *); |
116 |
|
|
|
117 |
|
|
/* Input state handlers. */ |
118 |
|
|
int input_print(struct input_ctx *); |
119 |
|
|
int input_intermediate(struct input_ctx *); |
120 |
|
|
int input_parameter(struct input_ctx *); |
121 |
|
|
int input_input(struct input_ctx *); |
122 |
|
|
int input_c0_dispatch(struct input_ctx *); |
123 |
|
|
int input_esc_dispatch(struct input_ctx *); |
124 |
|
|
int input_csi_dispatch(struct input_ctx *); |
125 |
|
|
void input_csi_dispatch_rm(struct input_ctx *); |
126 |
|
|
void input_csi_dispatch_rm_private(struct input_ctx *); |
127 |
|
|
void input_csi_dispatch_sm(struct input_ctx *); |
128 |
|
|
void input_csi_dispatch_sm_private(struct input_ctx *); |
129 |
|
|
void input_csi_dispatch_winops(struct input_ctx *); |
130 |
|
|
void input_csi_dispatch_sgr_256(struct input_ctx *, int, u_int *); |
131 |
|
|
void input_csi_dispatch_sgr_rgb(struct input_ctx *, int, u_int *); |
132 |
|
|
void input_csi_dispatch_sgr(struct input_ctx *); |
133 |
|
|
int input_dcs_dispatch(struct input_ctx *); |
134 |
|
|
int input_utf8_open(struct input_ctx *); |
135 |
|
|
int input_utf8_add(struct input_ctx *); |
136 |
|
|
int input_utf8_close(struct input_ctx *); |
137 |
|
|
|
138 |
|
|
/* Command table comparison function. */ |
139 |
|
|
int input_table_compare(const void *, const void *); |
140 |
|
|
|
141 |
|
|
/* Command table entry. */ |
142 |
|
|
struct input_table_entry { |
143 |
|
|
int ch; |
144 |
|
|
const char *interm; |
145 |
|
|
int type; |
146 |
|
|
}; |
147 |
|
|
|
148 |
|
|
/* Escape commands. */ |
149 |
|
|
enum input_esc_type { |
150 |
|
|
INPUT_ESC_DECALN, |
151 |
|
|
INPUT_ESC_DECKPAM, |
152 |
|
|
INPUT_ESC_DECKPNM, |
153 |
|
|
INPUT_ESC_DECRC, |
154 |
|
|
INPUT_ESC_DECSC, |
155 |
|
|
INPUT_ESC_HTS, |
156 |
|
|
INPUT_ESC_IND, |
157 |
|
|
INPUT_ESC_NEL, |
158 |
|
|
INPUT_ESC_RI, |
159 |
|
|
INPUT_ESC_RIS, |
160 |
|
|
INPUT_ESC_SCSG0_OFF, |
161 |
|
|
INPUT_ESC_SCSG0_ON, |
162 |
|
|
INPUT_ESC_SCSG1_OFF, |
163 |
|
|
INPUT_ESC_SCSG1_ON, |
164 |
|
|
}; |
165 |
|
|
|
166 |
|
|
/* Escape command table. */ |
167 |
|
|
const struct input_table_entry input_esc_table[] = { |
168 |
|
|
{ '0', "(", INPUT_ESC_SCSG0_ON }, |
169 |
|
|
{ '0', ")", INPUT_ESC_SCSG1_ON }, |
170 |
|
|
{ '7', "", INPUT_ESC_DECSC }, |
171 |
|
|
{ '8', "", INPUT_ESC_DECRC }, |
172 |
|
|
{ '8', "#", INPUT_ESC_DECALN }, |
173 |
|
|
{ '=', "", INPUT_ESC_DECKPAM }, |
174 |
|
|
{ '>', "", INPUT_ESC_DECKPNM }, |
175 |
|
|
{ 'B', "(", INPUT_ESC_SCSG0_OFF }, |
176 |
|
|
{ 'B', ")", INPUT_ESC_SCSG1_OFF }, |
177 |
|
|
{ 'D', "", INPUT_ESC_IND }, |
178 |
|
|
{ 'E', "", INPUT_ESC_NEL }, |
179 |
|
|
{ 'H', "", INPUT_ESC_HTS }, |
180 |
|
|
{ 'M', "", INPUT_ESC_RI }, |
181 |
|
|
{ 'c', "", INPUT_ESC_RIS }, |
182 |
|
|
}; |
183 |
|
|
|
184 |
|
|
/* Control (CSI) commands. */ |
185 |
|
|
enum input_csi_type { |
186 |
|
|
INPUT_CSI_CBT, |
187 |
|
|
INPUT_CSI_CNL, |
188 |
|
|
INPUT_CSI_CPL, |
189 |
|
|
INPUT_CSI_CUB, |
190 |
|
|
INPUT_CSI_CUD, |
191 |
|
|
INPUT_CSI_CUF, |
192 |
|
|
INPUT_CSI_CUP, |
193 |
|
|
INPUT_CSI_CUU, |
194 |
|
|
INPUT_CSI_DA, |
195 |
|
|
INPUT_CSI_DA_TWO, |
196 |
|
|
INPUT_CSI_DCH, |
197 |
|
|
INPUT_CSI_DECSCUSR, |
198 |
|
|
INPUT_CSI_DECSTBM, |
199 |
|
|
INPUT_CSI_DL, |
200 |
|
|
INPUT_CSI_DSR, |
201 |
|
|
INPUT_CSI_ECH, |
202 |
|
|
INPUT_CSI_ED, |
203 |
|
|
INPUT_CSI_EL, |
204 |
|
|
INPUT_CSI_HPA, |
205 |
|
|
INPUT_CSI_ICH, |
206 |
|
|
INPUT_CSI_IL, |
207 |
|
|
INPUT_CSI_RCP, |
208 |
|
|
INPUT_CSI_RM, |
209 |
|
|
INPUT_CSI_RM_PRIVATE, |
210 |
|
|
INPUT_CSI_SCP, |
211 |
|
|
INPUT_CSI_SGR, |
212 |
|
|
INPUT_CSI_SM, |
213 |
|
|
INPUT_CSI_SM_PRIVATE, |
214 |
|
|
INPUT_CSI_TBC, |
215 |
|
|
INPUT_CSI_VPA, |
216 |
|
|
INPUT_CSI_WINOPS, |
217 |
|
|
}; |
218 |
|
|
|
219 |
|
|
/* Control (CSI) command table. */ |
220 |
|
|
const struct input_table_entry input_csi_table[] = { |
221 |
|
|
{ '@', "", INPUT_CSI_ICH }, |
222 |
|
|
{ 'A', "", INPUT_CSI_CUU }, |
223 |
|
|
{ 'B', "", INPUT_CSI_CUD }, |
224 |
|
|
{ 'C', "", INPUT_CSI_CUF }, |
225 |
|
|
{ 'D', "", INPUT_CSI_CUB }, |
226 |
|
|
{ 'E', "", INPUT_CSI_CNL }, |
227 |
|
|
{ 'F', "", INPUT_CSI_CPL }, |
228 |
|
|
{ 'G', "", INPUT_CSI_HPA }, |
229 |
|
|
{ 'H', "", INPUT_CSI_CUP }, |
230 |
|
|
{ 'J', "", INPUT_CSI_ED }, |
231 |
|
|
{ 'K', "", INPUT_CSI_EL }, |
232 |
|
|
{ 'L', "", INPUT_CSI_IL }, |
233 |
|
|
{ 'M', "", INPUT_CSI_DL }, |
234 |
|
|
{ 'P', "", INPUT_CSI_DCH }, |
235 |
|
|
{ 'X', "", INPUT_CSI_ECH }, |
236 |
|
|
{ 'Z', "", INPUT_CSI_CBT }, |
237 |
|
|
{ 'c', "", INPUT_CSI_DA }, |
238 |
|
|
{ 'c', ">", INPUT_CSI_DA_TWO }, |
239 |
|
|
{ 'd', "", INPUT_CSI_VPA }, |
240 |
|
|
{ 'f', "", INPUT_CSI_CUP }, |
241 |
|
|
{ 'g', "", INPUT_CSI_TBC }, |
242 |
|
|
{ 'h', "", INPUT_CSI_SM }, |
243 |
|
|
{ 'h', "?", INPUT_CSI_SM_PRIVATE }, |
244 |
|
|
{ 'l', "", INPUT_CSI_RM }, |
245 |
|
|
{ 'l', "?", INPUT_CSI_RM_PRIVATE }, |
246 |
|
|
{ 'm', "", INPUT_CSI_SGR }, |
247 |
|
|
{ 'n', "", INPUT_CSI_DSR }, |
248 |
|
|
{ 'q', " ", INPUT_CSI_DECSCUSR }, |
249 |
|
|
{ 'r', "", INPUT_CSI_DECSTBM }, |
250 |
|
|
{ 's', "", INPUT_CSI_SCP }, |
251 |
|
|
{ 't', "", INPUT_CSI_WINOPS }, |
252 |
|
|
{ 'u', "", INPUT_CSI_RCP }, |
253 |
|
|
}; |
254 |
|
|
|
255 |
|
|
/* Input transition. */ |
256 |
|
|
struct input_transition { |
257 |
|
|
int first; |
258 |
|
|
int last; |
259 |
|
|
|
260 |
|
|
int (*handler)(struct input_ctx *); |
261 |
|
|
const struct input_state *state; |
262 |
|
|
}; |
263 |
|
|
|
264 |
|
|
/* Input state. */ |
265 |
|
|
struct input_state { |
266 |
|
|
const char *name; |
267 |
|
|
void (*enter)(struct input_ctx *); |
268 |
|
|
void (*exit)(struct input_ctx *); |
269 |
|
|
const struct input_transition *transitions; |
270 |
|
|
}; |
271 |
|
|
|
272 |
|
|
/* State transitions available from all states. */ |
273 |
|
|
#define INPUT_STATE_ANYWHERE \ |
274 |
|
|
{ 0x18, 0x18, input_c0_dispatch, &input_state_ground }, \ |
275 |
|
|
{ 0x1a, 0x1a, input_c0_dispatch, &input_state_ground }, \ |
276 |
|
|
{ 0x1b, 0x1b, NULL, &input_state_esc_enter } |
277 |
|
|
|
278 |
|
|
/* Forward declarations of state tables. */ |
279 |
|
|
const struct input_transition input_state_ground_table[]; |
280 |
|
|
const struct input_transition input_state_esc_enter_table[]; |
281 |
|
|
const struct input_transition input_state_esc_intermediate_table[]; |
282 |
|
|
const struct input_transition input_state_csi_enter_table[]; |
283 |
|
|
const struct input_transition input_state_csi_parameter_table[]; |
284 |
|
|
const struct input_transition input_state_csi_intermediate_table[]; |
285 |
|
|
const struct input_transition input_state_csi_ignore_table[]; |
286 |
|
|
const struct input_transition input_state_dcs_enter_table[]; |
287 |
|
|
const struct input_transition input_state_dcs_parameter_table[]; |
288 |
|
|
const struct input_transition input_state_dcs_intermediate_table[]; |
289 |
|
|
const struct input_transition input_state_dcs_handler_table[]; |
290 |
|
|
const struct input_transition input_state_dcs_escape_table[]; |
291 |
|
|
const struct input_transition input_state_dcs_ignore_table[]; |
292 |
|
|
const struct input_transition input_state_osc_string_table[]; |
293 |
|
|
const struct input_transition input_state_apc_string_table[]; |
294 |
|
|
const struct input_transition input_state_rename_string_table[]; |
295 |
|
|
const struct input_transition input_state_consume_st_table[]; |
296 |
|
|
const struct input_transition input_state_utf8_three_table[]; |
297 |
|
|
const struct input_transition input_state_utf8_two_table[]; |
298 |
|
|
const struct input_transition input_state_utf8_one_table[]; |
299 |
|
|
|
300 |
|
|
/* ground state definition. */ |
301 |
|
|
const struct input_state input_state_ground = { |
302 |
|
|
"ground", |
303 |
|
|
input_ground, NULL, |
304 |
|
|
input_state_ground_table |
305 |
|
|
}; |
306 |
|
|
|
307 |
|
|
/* esc_enter state definition. */ |
308 |
|
|
const struct input_state input_state_esc_enter = { |
309 |
|
|
"esc_enter", |
310 |
|
|
input_clear, NULL, |
311 |
|
|
input_state_esc_enter_table |
312 |
|
|
}; |
313 |
|
|
|
314 |
|
|
/* esc_intermediate state definition. */ |
315 |
|
|
const struct input_state input_state_esc_intermediate = { |
316 |
|
|
"esc_intermediate", |
317 |
|
|
NULL, NULL, |
318 |
|
|
input_state_esc_intermediate_table |
319 |
|
|
}; |
320 |
|
|
|
321 |
|
|
/* csi_enter state definition. */ |
322 |
|
|
const struct input_state input_state_csi_enter = { |
323 |
|
|
"csi_enter", |
324 |
|
|
input_clear, NULL, |
325 |
|
|
input_state_csi_enter_table |
326 |
|
|
}; |
327 |
|
|
|
328 |
|
|
/* csi_parameter state definition. */ |
329 |
|
|
const struct input_state input_state_csi_parameter = { |
330 |
|
|
"csi_parameter", |
331 |
|
|
NULL, NULL, |
332 |
|
|
input_state_csi_parameter_table |
333 |
|
|
}; |
334 |
|
|
|
335 |
|
|
/* csi_intermediate state definition. */ |
336 |
|
|
const struct input_state input_state_csi_intermediate = { |
337 |
|
|
"csi_intermediate", |
338 |
|
|
NULL, NULL, |
339 |
|
|
input_state_csi_intermediate_table |
340 |
|
|
}; |
341 |
|
|
|
342 |
|
|
/* csi_ignore state definition. */ |
343 |
|
|
const struct input_state input_state_csi_ignore = { |
344 |
|
|
"csi_ignore", |
345 |
|
|
NULL, NULL, |
346 |
|
|
input_state_csi_ignore_table |
347 |
|
|
}; |
348 |
|
|
|
349 |
|
|
/* dcs_enter state definition. */ |
350 |
|
|
const struct input_state input_state_dcs_enter = { |
351 |
|
|
"dcs_enter", |
352 |
|
|
input_clear, NULL, |
353 |
|
|
input_state_dcs_enter_table |
354 |
|
|
}; |
355 |
|
|
|
356 |
|
|
/* dcs_parameter state definition. */ |
357 |
|
|
const struct input_state input_state_dcs_parameter = { |
358 |
|
|
"dcs_parameter", |
359 |
|
|
NULL, NULL, |
360 |
|
|
input_state_dcs_parameter_table |
361 |
|
|
}; |
362 |
|
|
|
363 |
|
|
/* dcs_intermediate state definition. */ |
364 |
|
|
const struct input_state input_state_dcs_intermediate = { |
365 |
|
|
"dcs_intermediate", |
366 |
|
|
NULL, NULL, |
367 |
|
|
input_state_dcs_intermediate_table |
368 |
|
|
}; |
369 |
|
|
|
370 |
|
|
/* dcs_handler state definition. */ |
371 |
|
|
const struct input_state input_state_dcs_handler = { |
372 |
|
|
"dcs_handler", |
373 |
|
|
NULL, NULL, |
374 |
|
|
input_state_dcs_handler_table |
375 |
|
|
}; |
376 |
|
|
|
377 |
|
|
/* dcs_escape state definition. */ |
378 |
|
|
const struct input_state input_state_dcs_escape = { |
379 |
|
|
"dcs_escape", |
380 |
|
|
NULL, NULL, |
381 |
|
|
input_state_dcs_escape_table |
382 |
|
|
}; |
383 |
|
|
|
384 |
|
|
/* dcs_ignore state definition. */ |
385 |
|
|
const struct input_state input_state_dcs_ignore = { |
386 |
|
|
"dcs_ignore", |
387 |
|
|
NULL, NULL, |
388 |
|
|
input_state_dcs_ignore_table |
389 |
|
|
}; |
390 |
|
|
|
391 |
|
|
/* osc_string state definition. */ |
392 |
|
|
const struct input_state input_state_osc_string = { |
393 |
|
|
"osc_string", |
394 |
|
|
input_enter_osc, input_exit_osc, |
395 |
|
|
input_state_osc_string_table |
396 |
|
|
}; |
397 |
|
|
|
398 |
|
|
/* apc_string state definition. */ |
399 |
|
|
const struct input_state input_state_apc_string = { |
400 |
|
|
"apc_string", |
401 |
|
|
input_enter_apc, input_exit_apc, |
402 |
|
|
input_state_apc_string_table |
403 |
|
|
}; |
404 |
|
|
|
405 |
|
|
/* rename_string state definition. */ |
406 |
|
|
const struct input_state input_state_rename_string = { |
407 |
|
|
"rename_string", |
408 |
|
|
input_enter_rename, input_exit_rename, |
409 |
|
|
input_state_rename_string_table |
410 |
|
|
}; |
411 |
|
|
|
412 |
|
|
/* consume_st state definition. */ |
413 |
|
|
const struct input_state input_state_consume_st = { |
414 |
|
|
"consume_st", |
415 |
|
|
NULL, NULL, |
416 |
|
|
input_state_consume_st_table |
417 |
|
|
}; |
418 |
|
|
|
419 |
|
|
/* utf8_three state definition. */ |
420 |
|
|
const struct input_state input_state_utf8_three = { |
421 |
|
|
"utf8_three", |
422 |
|
|
NULL, NULL, |
423 |
|
|
input_state_utf8_three_table |
424 |
|
|
}; |
425 |
|
|
|
426 |
|
|
/* utf8_two state definition. */ |
427 |
|
|
const struct input_state input_state_utf8_two = { |
428 |
|
|
"utf8_two", |
429 |
|
|
NULL, NULL, |
430 |
|
|
input_state_utf8_two_table |
431 |
|
|
}; |
432 |
|
|
|
433 |
|
|
/* utf8_one state definition. */ |
434 |
|
|
const struct input_state input_state_utf8_one = { |
435 |
|
|
"utf8_one", |
436 |
|
|
NULL, NULL, |
437 |
|
|
input_state_utf8_one_table |
438 |
|
|
}; |
439 |
|
|
|
440 |
|
|
/* ground state table. */ |
441 |
|
|
const struct input_transition input_state_ground_table[] = { |
442 |
|
|
INPUT_STATE_ANYWHERE, |
443 |
|
|
|
444 |
|
|
{ 0x00, 0x17, input_c0_dispatch, NULL }, |
445 |
|
|
{ 0x19, 0x19, input_c0_dispatch, NULL }, |
446 |
|
|
{ 0x1c, 0x1f, input_c0_dispatch, NULL }, |
447 |
|
|
{ 0x20, 0x7e, input_print, NULL }, |
448 |
|
|
{ 0x7f, 0x7f, NULL, NULL }, |
449 |
|
|
{ 0x80, 0xc1, NULL, NULL }, |
450 |
|
|
{ 0xc2, 0xdf, input_utf8_open, &input_state_utf8_one }, |
451 |
|
|
{ 0xe0, 0xef, input_utf8_open, &input_state_utf8_two }, |
452 |
|
|
{ 0xf0, 0xf4, input_utf8_open, &input_state_utf8_three }, |
453 |
|
|
{ 0xf5, 0xff, NULL, NULL }, |
454 |
|
|
|
455 |
|
|
{ -1, -1, NULL, NULL } |
456 |
|
|
}; |
457 |
|
|
|
458 |
|
|
/* esc_enter state table. */ |
459 |
|
|
const struct input_transition input_state_esc_enter_table[] = { |
460 |
|
|
INPUT_STATE_ANYWHERE, |
461 |
|
|
|
462 |
|
|
{ 0x00, 0x17, input_c0_dispatch, NULL }, |
463 |
|
|
{ 0x19, 0x19, input_c0_dispatch, NULL }, |
464 |
|
|
{ 0x1c, 0x1f, input_c0_dispatch, NULL }, |
465 |
|
|
{ 0x20, 0x2f, input_intermediate, &input_state_esc_intermediate }, |
466 |
|
|
{ 0x30, 0x4f, input_esc_dispatch, &input_state_ground }, |
467 |
|
|
{ 0x50, 0x50, NULL, &input_state_dcs_enter }, |
468 |
|
|
{ 0x51, 0x57, input_esc_dispatch, &input_state_ground }, |
469 |
|
|
{ 0x58, 0x58, NULL, &input_state_consume_st }, |
470 |
|
|
{ 0x59, 0x59, input_esc_dispatch, &input_state_ground }, |
471 |
|
|
{ 0x5a, 0x5a, input_esc_dispatch, &input_state_ground }, |
472 |
|
|
{ 0x5b, 0x5b, NULL, &input_state_csi_enter }, |
473 |
|
|
{ 0x5c, 0x5c, input_esc_dispatch, &input_state_ground }, |
474 |
|
|
{ 0x5d, 0x5d, NULL, &input_state_osc_string }, |
475 |
|
|
{ 0x5e, 0x5e, NULL, &input_state_consume_st }, |
476 |
|
|
{ 0x5f, 0x5f, NULL, &input_state_apc_string }, |
477 |
|
|
{ 0x60, 0x6a, input_esc_dispatch, &input_state_ground }, |
478 |
|
|
{ 0x6b, 0x6b, NULL, &input_state_rename_string }, |
479 |
|
|
{ 0x6c, 0x7e, input_esc_dispatch, &input_state_ground }, |
480 |
|
|
{ 0x7f, 0xff, NULL, NULL }, |
481 |
|
|
|
482 |
|
|
{ -1, -1, NULL, NULL } |
483 |
|
|
}; |
484 |
|
|
|
485 |
|
|
/* esc_interm state table. */ |
486 |
|
|
const struct input_transition input_state_esc_intermediate_table[] = { |
487 |
|
|
INPUT_STATE_ANYWHERE, |
488 |
|
|
|
489 |
|
|
{ 0x00, 0x17, input_c0_dispatch, NULL }, |
490 |
|
|
{ 0x19, 0x19, input_c0_dispatch, NULL }, |
491 |
|
|
{ 0x1c, 0x1f, input_c0_dispatch, NULL }, |
492 |
|
|
{ 0x20, 0x2f, input_intermediate, NULL }, |
493 |
|
|
{ 0x30, 0x7e, input_esc_dispatch, &input_state_ground }, |
494 |
|
|
{ 0x7f, 0xff, NULL, NULL }, |
495 |
|
|
|
496 |
|
|
{ -1, -1, NULL, NULL } |
497 |
|
|
}; |
498 |
|
|
|
499 |
|
|
/* csi_enter state table. */ |
500 |
|
|
const struct input_transition input_state_csi_enter_table[] = { |
501 |
|
|
INPUT_STATE_ANYWHERE, |
502 |
|
|
|
503 |
|
|
{ 0x00, 0x17, input_c0_dispatch, NULL }, |
504 |
|
|
{ 0x19, 0x19, input_c0_dispatch, NULL }, |
505 |
|
|
{ 0x1c, 0x1f, input_c0_dispatch, NULL }, |
506 |
|
|
{ 0x20, 0x2f, input_intermediate, &input_state_csi_intermediate }, |
507 |
|
|
{ 0x30, 0x39, input_parameter, &input_state_csi_parameter }, |
508 |
|
|
{ 0x3a, 0x3a, NULL, &input_state_csi_ignore }, |
509 |
|
|
{ 0x3b, 0x3b, input_parameter, &input_state_csi_parameter }, |
510 |
|
|
{ 0x3c, 0x3f, input_intermediate, &input_state_csi_parameter }, |
511 |
|
|
{ 0x40, 0x7e, input_csi_dispatch, &input_state_ground }, |
512 |
|
|
{ 0x7f, 0xff, NULL, NULL }, |
513 |
|
|
|
514 |
|
|
{ -1, -1, NULL, NULL } |
515 |
|
|
}; |
516 |
|
|
|
517 |
|
|
/* csi_parameter state table. */ |
518 |
|
|
const struct input_transition input_state_csi_parameter_table[] = { |
519 |
|
|
INPUT_STATE_ANYWHERE, |
520 |
|
|
|
521 |
|
|
{ 0x00, 0x17, input_c0_dispatch, NULL }, |
522 |
|
|
{ 0x19, 0x19, input_c0_dispatch, NULL }, |
523 |
|
|
{ 0x1c, 0x1f, input_c0_dispatch, NULL }, |
524 |
|
|
{ 0x20, 0x2f, input_intermediate, &input_state_csi_intermediate }, |
525 |
|
|
{ 0x30, 0x39, input_parameter, NULL }, |
526 |
|
|
{ 0x3a, 0x3a, NULL, &input_state_csi_ignore }, |
527 |
|
|
{ 0x3b, 0x3b, input_parameter, NULL }, |
528 |
|
|
{ 0x3c, 0x3f, NULL, &input_state_csi_ignore }, |
529 |
|
|
{ 0x40, 0x7e, input_csi_dispatch, &input_state_ground }, |
530 |
|
|
{ 0x7f, 0xff, NULL, NULL }, |
531 |
|
|
|
532 |
|
|
{ -1, -1, NULL, NULL } |
533 |
|
|
}; |
534 |
|
|
|
535 |
|
|
/* csi_intermediate state table. */ |
536 |
|
|
const struct input_transition input_state_csi_intermediate_table[] = { |
537 |
|
|
INPUT_STATE_ANYWHERE, |
538 |
|
|
|
539 |
|
|
{ 0x00, 0x17, input_c0_dispatch, NULL }, |
540 |
|
|
{ 0x19, 0x19, input_c0_dispatch, NULL }, |
541 |
|
|
{ 0x1c, 0x1f, input_c0_dispatch, NULL }, |
542 |
|
|
{ 0x20, 0x2f, input_intermediate, NULL }, |
543 |
|
|
{ 0x30, 0x3f, NULL, &input_state_csi_ignore }, |
544 |
|
|
{ 0x40, 0x7e, input_csi_dispatch, &input_state_ground }, |
545 |
|
|
{ 0x7f, 0xff, NULL, NULL }, |
546 |
|
|
|
547 |
|
|
{ -1, -1, NULL, NULL } |
548 |
|
|
}; |
549 |
|
|
|
550 |
|
|
/* csi_ignore state table. */ |
551 |
|
|
const struct input_transition input_state_csi_ignore_table[] = { |
552 |
|
|
INPUT_STATE_ANYWHERE, |
553 |
|
|
|
554 |
|
|
{ 0x00, 0x17, input_c0_dispatch, NULL }, |
555 |
|
|
{ 0x19, 0x19, input_c0_dispatch, NULL }, |
556 |
|
|
{ 0x1c, 0x1f, input_c0_dispatch, NULL }, |
557 |
|
|
{ 0x20, 0x3f, NULL, NULL }, |
558 |
|
|
{ 0x40, 0x7e, NULL, &input_state_ground }, |
559 |
|
|
{ 0x7f, 0xff, NULL, NULL }, |
560 |
|
|
|
561 |
|
|
{ -1, -1, NULL, NULL } |
562 |
|
|
}; |
563 |
|
|
|
564 |
|
|
/* dcs_enter state table. */ |
565 |
|
|
const struct input_transition input_state_dcs_enter_table[] = { |
566 |
|
|
INPUT_STATE_ANYWHERE, |
567 |
|
|
|
568 |
|
|
{ 0x00, 0x17, NULL, NULL }, |
569 |
|
|
{ 0x19, 0x19, NULL, NULL }, |
570 |
|
|
{ 0x1c, 0x1f, NULL, NULL }, |
571 |
|
|
{ 0x20, 0x2f, input_intermediate, &input_state_dcs_intermediate }, |
572 |
|
|
{ 0x30, 0x39, input_parameter, &input_state_dcs_parameter }, |
573 |
|
|
{ 0x3a, 0x3a, NULL, &input_state_dcs_ignore }, |
574 |
|
|
{ 0x3b, 0x3b, input_parameter, &input_state_dcs_parameter }, |
575 |
|
|
{ 0x3c, 0x3f, input_intermediate, &input_state_dcs_parameter }, |
576 |
|
|
{ 0x40, 0x7e, input_input, &input_state_dcs_handler }, |
577 |
|
|
{ 0x7f, 0xff, NULL, NULL }, |
578 |
|
|
|
579 |
|
|
{ -1, -1, NULL, NULL } |
580 |
|
|
}; |
581 |
|
|
|
582 |
|
|
/* dcs_parameter state table. */ |
583 |
|
|
const struct input_transition input_state_dcs_parameter_table[] = { |
584 |
|
|
INPUT_STATE_ANYWHERE, |
585 |
|
|
|
586 |
|
|
{ 0x00, 0x17, NULL, NULL }, |
587 |
|
|
{ 0x19, 0x19, NULL, NULL }, |
588 |
|
|
{ 0x1c, 0x1f, NULL, NULL }, |
589 |
|
|
{ 0x20, 0x2f, input_intermediate, &input_state_dcs_intermediate }, |
590 |
|
|
{ 0x30, 0x39, input_parameter, NULL }, |
591 |
|
|
{ 0x3a, 0x3a, NULL, &input_state_dcs_ignore }, |
592 |
|
|
{ 0x3b, 0x3b, input_parameter, NULL }, |
593 |
|
|
{ 0x3c, 0x3f, NULL, &input_state_dcs_ignore }, |
594 |
|
|
{ 0x40, 0x7e, input_input, &input_state_dcs_handler }, |
595 |
|
|
{ 0x7f, 0xff, NULL, NULL }, |
596 |
|
|
|
597 |
|
|
{ -1, -1, NULL, NULL } |
598 |
|
|
}; |
599 |
|
|
|
600 |
|
|
/* dcs_interm state table. */ |
601 |
|
|
const struct input_transition input_state_dcs_intermediate_table[] = { |
602 |
|
|
INPUT_STATE_ANYWHERE, |
603 |
|
|
|
604 |
|
|
{ 0x00, 0x17, NULL, NULL }, |
605 |
|
|
{ 0x19, 0x19, NULL, NULL }, |
606 |
|
|
{ 0x1c, 0x1f, NULL, NULL }, |
607 |
|
|
{ 0x20, 0x2f, input_intermediate, NULL }, |
608 |
|
|
{ 0x30, 0x3f, NULL, &input_state_dcs_ignore }, |
609 |
|
|
{ 0x40, 0x7e, input_input, &input_state_dcs_handler }, |
610 |
|
|
{ 0x7f, 0xff, NULL, NULL }, |
611 |
|
|
|
612 |
|
|
{ -1, -1, NULL, NULL } |
613 |
|
|
}; |
614 |
|
|
|
615 |
|
|
/* dcs_handler state table. */ |
616 |
|
|
const struct input_transition input_state_dcs_handler_table[] = { |
617 |
|
|
/* No INPUT_STATE_ANYWHERE */ |
618 |
|
|
|
619 |
|
|
{ 0x00, 0x1a, input_input, NULL }, |
620 |
|
|
{ 0x1b, 0x1b, NULL, &input_state_dcs_escape }, |
621 |
|
|
{ 0x1c, 0xff, input_input, NULL }, |
622 |
|
|
|
623 |
|
|
{ -1, -1, NULL, NULL } |
624 |
|
|
}; |
625 |
|
|
|
626 |
|
|
/* dcs_escape state table. */ |
627 |
|
|
const struct input_transition input_state_dcs_escape_table[] = { |
628 |
|
|
/* No INPUT_STATE_ANYWHERE */ |
629 |
|
|
|
630 |
|
|
{ 0x00, 0x5b, input_input, &input_state_dcs_handler }, |
631 |
|
|
{ 0x5c, 0x5c, input_dcs_dispatch, &input_state_ground }, |
632 |
|
|
{ 0x5d, 0xff, input_input, &input_state_dcs_handler }, |
633 |
|
|
|
634 |
|
|
{ -1, -1, NULL, NULL } |
635 |
|
|
}; |
636 |
|
|
|
637 |
|
|
/* dcs_ignore state table. */ |
638 |
|
|
const struct input_transition input_state_dcs_ignore_table[] = { |
639 |
|
|
INPUT_STATE_ANYWHERE, |
640 |
|
|
|
641 |
|
|
{ 0x00, 0x17, NULL, NULL }, |
642 |
|
|
{ 0x19, 0x19, NULL, NULL }, |
643 |
|
|
{ 0x1c, 0x1f, NULL, NULL }, |
644 |
|
|
{ 0x20, 0xff, NULL, NULL }, |
645 |
|
|
|
646 |
|
|
{ -1, -1, NULL, NULL } |
647 |
|
|
}; |
648 |
|
|
|
649 |
|
|
/* osc_string state table. */ |
650 |
|
|
const struct input_transition input_state_osc_string_table[] = { |
651 |
|
|
INPUT_STATE_ANYWHERE, |
652 |
|
|
|
653 |
|
|
{ 0x00, 0x06, NULL, NULL }, |
654 |
|
|
{ 0x07, 0x07, NULL, &input_state_ground }, |
655 |
|
|
{ 0x08, 0x17, NULL, NULL }, |
656 |
|
|
{ 0x19, 0x19, NULL, NULL }, |
657 |
|
|
{ 0x1c, 0x1f, NULL, NULL }, |
658 |
|
|
{ 0x20, 0xff, input_input, NULL }, |
659 |
|
|
|
660 |
|
|
{ -1, -1, NULL, NULL } |
661 |
|
|
}; |
662 |
|
|
|
663 |
|
|
/* apc_string state table. */ |
664 |
|
|
const struct input_transition input_state_apc_string_table[] = { |
665 |
|
|
INPUT_STATE_ANYWHERE, |
666 |
|
|
|
667 |
|
|
{ 0x00, 0x17, NULL, NULL }, |
668 |
|
|
{ 0x19, 0x19, NULL, NULL }, |
669 |
|
|
{ 0x1c, 0x1f, NULL, NULL }, |
670 |
|
|
{ 0x20, 0xff, input_input, NULL }, |
671 |
|
|
|
672 |
|
|
{ -1, -1, NULL, NULL } |
673 |
|
|
}; |
674 |
|
|
|
675 |
|
|
/* rename_string state table. */ |
676 |
|
|
const struct input_transition input_state_rename_string_table[] = { |
677 |
|
|
INPUT_STATE_ANYWHERE, |
678 |
|
|
|
679 |
|
|
{ 0x00, 0x17, NULL, NULL }, |
680 |
|
|
{ 0x19, 0x19, NULL, NULL }, |
681 |
|
|
{ 0x1c, 0x1f, NULL, NULL }, |
682 |
|
|
{ 0x20, 0xff, input_input, NULL }, |
683 |
|
|
|
684 |
|
|
{ -1, -1, NULL, NULL } |
685 |
|
|
}; |
686 |
|
|
|
687 |
|
|
/* consume_st state table. */ |
688 |
|
|
const struct input_transition input_state_consume_st_table[] = { |
689 |
|
|
INPUT_STATE_ANYWHERE, |
690 |
|
|
|
691 |
|
|
{ 0x00, 0x17, NULL, NULL }, |
692 |
|
|
{ 0x19, 0x19, NULL, NULL }, |
693 |
|
|
{ 0x1c, 0x1f, NULL, NULL }, |
694 |
|
|
{ 0x20, 0xff, NULL, NULL }, |
695 |
|
|
|
696 |
|
|
{ -1, -1, NULL, NULL } |
697 |
|
|
}; |
698 |
|
|
|
699 |
|
|
/* utf8_three state table. */ |
700 |
|
|
const struct input_transition input_state_utf8_three_table[] = { |
701 |
|
|
/* No INPUT_STATE_ANYWHERE */ |
702 |
|
|
|
703 |
|
|
{ 0x00, 0x7f, NULL, &input_state_ground }, |
704 |
|
|
{ 0x80, 0xbf, input_utf8_add, &input_state_utf8_two }, |
705 |
|
|
{ 0xc0, 0xff, NULL, &input_state_ground }, |
706 |
|
|
|
707 |
|
|
{ -1, -1, NULL, NULL } |
708 |
|
|
}; |
709 |
|
|
|
710 |
|
|
/* utf8_two state table. */ |
711 |
|
|
const struct input_transition input_state_utf8_two_table[] = { |
712 |
|
|
/* No INPUT_STATE_ANYWHERE */ |
713 |
|
|
|
714 |
|
|
{ 0x00, 0x7f, NULL, &input_state_ground }, |
715 |
|
|
{ 0x80, 0xbf, input_utf8_add, &input_state_utf8_one }, |
716 |
|
|
{ 0xc0, 0xff, NULL, &input_state_ground }, |
717 |
|
|
|
718 |
|
|
{ -1, -1, NULL, NULL } |
719 |
|
|
}; |
720 |
|
|
|
721 |
|
|
/* utf8_one state table. */ |
722 |
|
|
const struct input_transition input_state_utf8_one_table[] = { |
723 |
|
|
/* No INPUT_STATE_ANYWHERE */ |
724 |
|
|
|
725 |
|
|
{ 0x00, 0x7f, NULL, &input_state_ground }, |
726 |
|
|
{ 0x80, 0xbf, input_utf8_close, &input_state_ground }, |
727 |
|
|
{ 0xc0, 0xff, NULL, &input_state_ground }, |
728 |
|
|
|
729 |
|
|
{ -1, -1, NULL, NULL } |
730 |
|
|
}; |
731 |
|
|
|
732 |
|
|
/* Input table compare. */ |
733 |
|
|
int |
734 |
|
|
input_table_compare(const void *key, const void *value) |
735 |
|
|
{ |
736 |
|
|
const struct input_ctx *ictx = key; |
737 |
|
|
const struct input_table_entry *entry = value; |
738 |
|
|
|
739 |
|
|
if (ictx->ch != entry->ch) |
740 |
|
|
return (ictx->ch - entry->ch); |
741 |
|
|
return (strcmp(ictx->interm_buf, entry->interm)); |
742 |
|
|
} |
743 |
|
|
|
744 |
|
|
/* Reset cell state to default. */ |
745 |
|
|
void |
746 |
|
|
input_reset_cell(struct input_ctx *ictx) |
747 |
|
|
{ |
748 |
|
|
memcpy(&ictx->cell.cell, &grid_default_cell, sizeof ictx->cell.cell); |
749 |
|
|
ictx->cell.set = 0; |
750 |
|
|
ictx->cell.g0set = ictx->cell.g1set = 0; |
751 |
|
|
|
752 |
|
|
memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell); |
753 |
|
|
ictx->old_cx = 0; |
754 |
|
|
ictx->old_cy = 0; |
755 |
|
|
} |
756 |
|
|
|
757 |
|
|
/* Initialise input parser. */ |
758 |
|
|
void |
759 |
|
|
input_init(struct window_pane *wp) |
760 |
|
|
{ |
761 |
|
|
struct input_ctx *ictx; |
762 |
|
|
|
763 |
|
|
ictx = wp->ictx = xcalloc(1, sizeof *ictx); |
764 |
|
|
|
765 |
|
|
ictx->input_space = INPUT_BUF_START; |
766 |
|
|
ictx->input_buf = xmalloc(INPUT_BUF_START); |
767 |
|
|
|
768 |
|
|
ictx->since_ground = evbuffer_new(); |
769 |
|
|
|
770 |
|
|
input_reset(wp, 0); |
771 |
|
|
} |
772 |
|
|
|
773 |
|
|
/* Destroy input parser. */ |
774 |
|
|
void |
775 |
|
|
input_free(struct window_pane *wp) |
776 |
|
|
{ |
777 |
|
|
struct input_ctx *ictx = wp->ictx; |
778 |
|
|
|
779 |
|
|
free(ictx->input_buf); |
780 |
|
|
evbuffer_free(ictx->since_ground); |
781 |
|
|
|
782 |
|
|
free (ictx); |
783 |
|
|
wp->ictx = NULL; |
784 |
|
|
} |
785 |
|
|
|
786 |
|
|
/* Reset input state and clear screen. */ |
787 |
|
|
void |
788 |
|
|
input_reset(struct window_pane *wp, int clear) |
789 |
|
|
{ |
790 |
|
|
struct input_ctx *ictx = wp->ictx; |
791 |
|
|
|
792 |
|
|
input_reset_cell(ictx); |
793 |
|
|
|
794 |
|
|
if (clear) { |
795 |
|
|
if (wp->mode == NULL) |
796 |
|
|
screen_write_start(&ictx->ctx, wp, &wp->base); |
797 |
|
|
else |
798 |
|
|
screen_write_start(&ictx->ctx, NULL, &wp->base); |
799 |
|
|
screen_write_reset(&ictx->ctx); |
800 |
|
|
screen_write_stop(&ictx->ctx); |
801 |
|
|
} |
802 |
|
|
|
803 |
|
|
*ictx->interm_buf = '\0'; |
804 |
|
|
ictx->interm_len = 0; |
805 |
|
|
|
806 |
|
|
*ictx->param_buf = '\0'; |
807 |
|
|
ictx->param_len = 0; |
808 |
|
|
|
809 |
|
|
*ictx->input_buf = '\0'; |
810 |
|
|
ictx->input_len = 0; |
811 |
|
|
|
812 |
|
|
ictx->state = &input_state_ground; |
813 |
|
|
ictx->flags = 0; |
814 |
|
|
} |
815 |
|
|
|
816 |
|
|
/* Return pending data. */ |
817 |
|
|
struct evbuffer * |
818 |
|
|
input_pending(struct window_pane *wp) |
819 |
|
|
{ |
820 |
|
|
return (wp->ictx->since_ground); |
821 |
|
|
} |
822 |
|
|
|
823 |
|
|
/* Change input state. */ |
824 |
|
|
void |
825 |
|
|
input_set_state(struct window_pane *wp, const struct input_transition *itr) |
826 |
|
|
{ |
827 |
|
|
struct input_ctx *ictx = wp->ictx; |
828 |
|
|
|
829 |
|
|
if (ictx->state->exit != NULL) |
830 |
|
|
ictx->state->exit(ictx); |
831 |
|
|
ictx->state = itr->state; |
832 |
|
|
if (ictx->state->enter != NULL) |
833 |
|
|
ictx->state->enter(ictx); |
834 |
|
|
} |
835 |
|
|
|
836 |
|
|
/* Parse input. */ |
837 |
|
|
void |
838 |
|
|
input_parse(struct window_pane *wp) |
839 |
|
|
{ |
840 |
|
|
struct input_ctx *ictx = wp->ictx; |
841 |
|
|
const struct input_transition *itr; |
842 |
|
|
struct evbuffer *evb = wp->event->input; |
843 |
|
|
u_char *buf; |
844 |
|
|
size_t len, off; |
845 |
|
|
|
846 |
|
|
if (EVBUFFER_LENGTH(evb) == 0) |
847 |
|
|
return; |
848 |
|
|
|
849 |
|
|
window_update_activity(wp->window); |
850 |
|
|
wp->flags |= PANE_CHANGED; |
851 |
|
|
|
852 |
|
|
/* |
853 |
|
|
* Open the screen. Use NULL wp if there is a mode set as don't want to |
854 |
|
|
* update the tty. |
855 |
|
|
*/ |
856 |
|
|
if (wp->mode == NULL) |
857 |
|
|
screen_write_start(&ictx->ctx, wp, &wp->base); |
858 |
|
|
else |
859 |
|
|
screen_write_start(&ictx->ctx, NULL, &wp->base); |
860 |
|
|
ictx->wp = wp; |
861 |
|
|
|
862 |
|
|
buf = EVBUFFER_DATA(evb); |
863 |
|
|
len = EVBUFFER_LENGTH(evb); |
864 |
|
|
notify_input(wp, evb); |
865 |
|
|
off = 0; |
866 |
|
|
|
867 |
|
|
log_debug("%s: %%%u %s, %zu bytes: %.*s", __func__, wp->id, |
868 |
|
|
ictx->state->name, len, (int)len, buf); |
869 |
|
|
|
870 |
|
|
/* Parse the input. */ |
871 |
|
|
while (off < len) { |
872 |
|
|
ictx->ch = buf[off++]; |
873 |
|
|
|
874 |
|
|
/* Find the transition. */ |
875 |
|
|
itr = ictx->state->transitions; |
876 |
|
|
while (itr->first != -1 && itr->last != -1) { |
877 |
|
|
if (ictx->ch >= itr->first && ictx->ch <= itr->last) |
878 |
|
|
break; |
879 |
|
|
itr++; |
880 |
|
|
} |
881 |
|
|
if (itr->first == -1 || itr->last == -1) { |
882 |
|
|
/* No transition? Eh? */ |
883 |
|
|
fatalx("no transition from state"); |
884 |
|
|
} |
885 |
|
|
|
886 |
|
|
/* |
887 |
|
|
* Execute the handler, if any. Don't switch state if it |
888 |
|
|
* returns non-zero. |
889 |
|
|
*/ |
890 |
|
|
if (itr->handler != NULL && itr->handler(ictx) != 0) |
891 |
|
|
continue; |
892 |
|
|
|
893 |
|
|
/* And switch state, if necessary. */ |
894 |
|
|
if (itr->state != NULL) |
895 |
|
|
input_set_state(wp, itr); |
896 |
|
|
|
897 |
|
|
/* If not in ground state, save input. */ |
898 |
|
|
if (ictx->state != &input_state_ground) |
899 |
|
|
evbuffer_add(ictx->since_ground, &ictx->ch, 1); |
900 |
|
|
} |
901 |
|
|
|
902 |
|
|
/* Close the screen. */ |
903 |
|
|
screen_write_stop(&ictx->ctx); |
904 |
|
|
|
905 |
|
|
evbuffer_drain(evb, len); |
906 |
|
|
} |
907 |
|
|
|
908 |
|
|
/* Split the parameter list (if any). */ |
909 |
|
|
int |
910 |
|
|
input_split(struct input_ctx *ictx) |
911 |
|
|
|
912 |
|
|
{ |
913 |
|
|
const char *errstr; |
914 |
|
|
char *ptr, *out; |
915 |
|
|
int n; |
916 |
|
|
|
917 |
|
|
ictx->param_list_len = 0; |
918 |
|
|
if (ictx->param_len == 0) |
919 |
|
|
return (0); |
920 |
|
|
|
921 |
|
|
ptr = ictx->param_buf; |
922 |
|
|
while ((out = strsep(&ptr, ";")) != NULL) { |
923 |
|
|
if (*out == '\0') |
924 |
|
|
n = -1; |
925 |
|
|
else { |
926 |
|
|
n = strtonum(out, 0, INT_MAX, &errstr); |
927 |
|
|
if (errstr != NULL) |
928 |
|
|
return (-1); |
929 |
|
|
} |
930 |
|
|
|
931 |
|
|
ictx->param_list[ictx->param_list_len++] = n; |
932 |
|
|
if (ictx->param_list_len == nitems(ictx->param_list)) |
933 |
|
|
return (-1); |
934 |
|
|
} |
935 |
|
|
|
936 |
|
|
return (0); |
937 |
|
|
} |
938 |
|
|
|
939 |
|
|
/* Get an argument or return default value. */ |
940 |
|
|
int |
941 |
|
|
input_get(struct input_ctx *ictx, u_int validx, int minval, int defval) |
942 |
|
|
{ |
943 |
|
|
int retval; |
944 |
|
|
|
945 |
|
|
if (validx >= ictx->param_list_len) |
946 |
|
|
return (defval); |
947 |
|
|
|
948 |
|
|
retval = ictx->param_list[validx]; |
949 |
|
|
if (retval == -1) |
950 |
|
|
return (defval); |
951 |
|
|
if (retval < minval) |
952 |
|
|
return (minval); |
953 |
|
|
return (retval); |
954 |
|
|
} |
955 |
|
|
|
956 |
|
|
/* Reply to terminal query. */ |
957 |
|
|
void |
958 |
|
|
input_reply(struct input_ctx *ictx, const char *fmt, ...) |
959 |
|
|
{ |
960 |
|
|
va_list ap; |
961 |
|
|
char *reply; |
962 |
|
|
|
963 |
|
|
va_start(ap, fmt); |
964 |
|
|
vasprintf(&reply, fmt, ap); |
965 |
|
|
va_end(ap); |
966 |
|
|
|
967 |
|
|
bufferevent_write(ictx->wp->event, reply, strlen(reply)); |
968 |
|
|
free(reply); |
969 |
|
|
} |
970 |
|
|
|
971 |
|
|
/* Clear saved state. */ |
972 |
|
|
void |
973 |
|
|
input_clear(struct input_ctx *ictx) |
974 |
|
|
{ |
975 |
|
|
*ictx->interm_buf = '\0'; |
976 |
|
|
ictx->interm_len = 0; |
977 |
|
|
|
978 |
|
|
*ictx->param_buf = '\0'; |
979 |
|
|
ictx->param_len = 0; |
980 |
|
|
|
981 |
|
|
*ictx->input_buf = '\0'; |
982 |
|
|
ictx->input_len = 0; |
983 |
|
|
|
984 |
|
|
ictx->flags &= ~INPUT_DISCARD; |
985 |
|
|
} |
986 |
|
|
|
987 |
|
|
/* Reset for ground state. */ |
988 |
|
|
void |
989 |
|
|
input_ground(struct input_ctx *ictx) |
990 |
|
|
{ |
991 |
|
|
evbuffer_drain(ictx->since_ground, EVBUFFER_LENGTH(ictx->since_ground)); |
992 |
|
|
|
993 |
|
|
if (ictx->input_space > INPUT_BUF_START) { |
994 |
|
|
ictx->input_space = INPUT_BUF_START; |
995 |
|
|
ictx->input_buf = xrealloc(ictx->input_buf, INPUT_BUF_START); |
996 |
|
|
} |
997 |
|
|
} |
998 |
|
|
|
999 |
|
|
/* Output this character to the screen. */ |
1000 |
|
|
int |
1001 |
|
|
input_print(struct input_ctx *ictx) |
1002 |
|
|
{ |
1003 |
|
|
int set; |
1004 |
|
|
|
1005 |
|
|
set = ictx->cell.set == 0 ? ictx->cell.g0set : ictx->cell.g1set; |
1006 |
|
|
if (set == 1) |
1007 |
|
|
ictx->cell.cell.attr |= GRID_ATTR_CHARSET; |
1008 |
|
|
else |
1009 |
|
|
ictx->cell.cell.attr &= ~GRID_ATTR_CHARSET; |
1010 |
|
|
|
1011 |
|
|
utf8_set(&ictx->cell.cell.data, ictx->ch); |
1012 |
|
|
screen_write_cell(&ictx->ctx, &ictx->cell.cell); |
1013 |
|
|
|
1014 |
|
|
ictx->cell.cell.attr &= ~GRID_ATTR_CHARSET; |
1015 |
|
|
|
1016 |
|
|
return (0); |
1017 |
|
|
} |
1018 |
|
|
|
1019 |
|
|
/* Collect intermediate string. */ |
1020 |
|
|
int |
1021 |
|
|
input_intermediate(struct input_ctx *ictx) |
1022 |
|
|
{ |
1023 |
|
|
if (ictx->interm_len == (sizeof ictx->interm_buf) - 1) |
1024 |
|
|
ictx->flags |= INPUT_DISCARD; |
1025 |
|
|
else { |
1026 |
|
|
ictx->interm_buf[ictx->interm_len++] = ictx->ch; |
1027 |
|
|
ictx->interm_buf[ictx->interm_len] = '\0'; |
1028 |
|
|
} |
1029 |
|
|
|
1030 |
|
|
return (0); |
1031 |
|
|
} |
1032 |
|
|
|
1033 |
|
|
/* Collect parameter string. */ |
1034 |
|
|
int |
1035 |
|
|
input_parameter(struct input_ctx *ictx) |
1036 |
|
|
{ |
1037 |
|
|
if (ictx->param_len == (sizeof ictx->param_buf) - 1) |
1038 |
|
|
ictx->flags |= INPUT_DISCARD; |
1039 |
|
|
else { |
1040 |
|
|
ictx->param_buf[ictx->param_len++] = ictx->ch; |
1041 |
|
|
ictx->param_buf[ictx->param_len] = '\0'; |
1042 |
|
|
} |
1043 |
|
|
|
1044 |
|
|
return (0); |
1045 |
|
|
} |
1046 |
|
|
|
1047 |
|
|
/* Collect input string. */ |
1048 |
|
|
int |
1049 |
|
|
input_input(struct input_ctx *ictx) |
1050 |
|
|
{ |
1051 |
|
|
size_t available; |
1052 |
|
|
|
1053 |
|
|
available = ictx->input_space; |
1054 |
|
|
while (ictx->input_len + 1 >= available) { |
1055 |
|
|
available *= 2; |
1056 |
|
|
if (available > INPUT_BUF_LIMIT) { |
1057 |
|
|
ictx->flags |= INPUT_DISCARD; |
1058 |
|
|
return (0); |
1059 |
|
|
} |
1060 |
|
|
ictx->input_buf = xrealloc(ictx->input_buf, available); |
1061 |
|
|
ictx->input_space = available; |
1062 |
|
|
} |
1063 |
|
|
ictx->input_buf[ictx->input_len++] = ictx->ch; |
1064 |
|
|
ictx->input_buf[ictx->input_len] = '\0'; |
1065 |
|
|
|
1066 |
|
|
return (0); |
1067 |
|
|
} |
1068 |
|
|
|
1069 |
|
|
/* Execute C0 control sequence. */ |
1070 |
|
|
int |
1071 |
|
|
input_c0_dispatch(struct input_ctx *ictx) |
1072 |
|
|
{ |
1073 |
|
|
struct screen_write_ctx *sctx = &ictx->ctx; |
1074 |
|
|
struct window_pane *wp = ictx->wp; |
1075 |
|
|
struct screen *s = sctx->s; |
1076 |
|
|
|
1077 |
|
|
log_debug("%s: '%c'", __func__, ictx->ch); |
1078 |
|
|
|
1079 |
|
|
switch (ictx->ch) { |
1080 |
|
|
case '\000': /* NUL */ |
1081 |
|
|
break; |
1082 |
|
|
case '\007': /* BEL */ |
1083 |
|
|
alerts_queue(wp->window, WINDOW_BELL); |
1084 |
|
|
break; |
1085 |
|
|
case '\010': /* BS */ |
1086 |
|
|
screen_write_backspace(sctx); |
1087 |
|
|
break; |
1088 |
|
|
case '\011': /* HT */ |
1089 |
|
|
/* Don't tab beyond the end of the line. */ |
1090 |
|
|
if (s->cx >= screen_size_x(s) - 1) |
1091 |
|
|
break; |
1092 |
|
|
|
1093 |
|
|
/* Find the next tab point, or use the last column if none. */ |
1094 |
|
|
do { |
1095 |
|
|
s->cx++; |
1096 |
|
|
if (bit_test(s->tabs, s->cx)) |
1097 |
|
|
break; |
1098 |
|
|
} while (s->cx < screen_size_x(s) - 1); |
1099 |
|
|
break; |
1100 |
|
|
case '\012': /* LF */ |
1101 |
|
|
case '\013': /* VT */ |
1102 |
|
|
case '\014': /* FF */ |
1103 |
|
|
screen_write_linefeed(sctx, 0); |
1104 |
|
|
break; |
1105 |
|
|
case '\015': /* CR */ |
1106 |
|
|
screen_write_carriagereturn(sctx); |
1107 |
|
|
break; |
1108 |
|
|
case '\016': /* SO */ |
1109 |
|
|
ictx->cell.set = 1; |
1110 |
|
|
break; |
1111 |
|
|
case '\017': /* SI */ |
1112 |
|
|
ictx->cell.set = 0; |
1113 |
|
|
break; |
1114 |
|
|
default: |
1115 |
|
|
log_debug("%s: unknown '%c'", __func__, ictx->ch); |
1116 |
|
|
break; |
1117 |
|
|
} |
1118 |
|
|
|
1119 |
|
|
return (0); |
1120 |
|
|
} |
1121 |
|
|
|
1122 |
|
|
/* Execute escape sequence. */ |
1123 |
|
|
int |
1124 |
|
|
input_esc_dispatch(struct input_ctx *ictx) |
1125 |
|
|
{ |
1126 |
|
|
struct screen_write_ctx *sctx = &ictx->ctx; |
1127 |
|
|
struct screen *s = sctx->s; |
1128 |
|
|
struct input_table_entry *entry; |
1129 |
|
|
|
1130 |
|
|
if (ictx->flags & INPUT_DISCARD) |
1131 |
|
|
return (0); |
1132 |
|
|
log_debug("%s: '%c', %s", __func__, ictx->ch, ictx->interm_buf); |
1133 |
|
|
|
1134 |
|
|
entry = bsearch(ictx, input_esc_table, nitems(input_esc_table), |
1135 |
|
|
sizeof input_esc_table[0], input_table_compare); |
1136 |
|
|
if (entry == NULL) { |
1137 |
|
|
log_debug("%s: unknown '%c'", __func__, ictx->ch); |
1138 |
|
|
return (0); |
1139 |
|
|
} |
1140 |
|
|
|
1141 |
|
|
switch (entry->type) { |
1142 |
|
|
case INPUT_ESC_RIS: |
1143 |
|
|
input_reset_cell(ictx); |
1144 |
|
|
screen_write_reset(sctx); |
1145 |
|
|
break; |
1146 |
|
|
case INPUT_ESC_IND: |
1147 |
|
|
screen_write_linefeed(sctx, 0); |
1148 |
|
|
break; |
1149 |
|
|
case INPUT_ESC_NEL: |
1150 |
|
|
screen_write_carriagereturn(sctx); |
1151 |
|
|
screen_write_linefeed(sctx, 0); |
1152 |
|
|
break; |
1153 |
|
|
case INPUT_ESC_HTS: |
1154 |
|
|
if (s->cx < screen_size_x(s)) |
1155 |
|
|
bit_set(s->tabs, s->cx); |
1156 |
|
|
break; |
1157 |
|
|
case INPUT_ESC_RI: |
1158 |
|
|
screen_write_reverseindex(sctx); |
1159 |
|
|
break; |
1160 |
|
|
case INPUT_ESC_DECKPAM: |
1161 |
|
|
screen_write_mode_set(sctx, MODE_KKEYPAD); |
1162 |
|
|
break; |
1163 |
|
|
case INPUT_ESC_DECKPNM: |
1164 |
|
|
screen_write_mode_clear(sctx, MODE_KKEYPAD); |
1165 |
|
|
break; |
1166 |
|
|
case INPUT_ESC_DECSC: |
1167 |
|
|
memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell); |
1168 |
|
|
ictx->old_cx = s->cx; |
1169 |
|
|
ictx->old_cy = s->cy; |
1170 |
|
|
break; |
1171 |
|
|
case INPUT_ESC_DECRC: |
1172 |
|
|
memcpy(&ictx->cell, &ictx->old_cell, sizeof ictx->cell); |
1173 |
|
|
screen_write_cursormove(sctx, ictx->old_cx, ictx->old_cy); |
1174 |
|
|
break; |
1175 |
|
|
case INPUT_ESC_DECALN: |
1176 |
|
|
screen_write_alignmenttest(sctx); |
1177 |
|
|
break; |
1178 |
|
|
case INPUT_ESC_SCSG0_ON: |
1179 |
|
|
ictx->cell.g0set = 1; |
1180 |
|
|
break; |
1181 |
|
|
case INPUT_ESC_SCSG0_OFF: |
1182 |
|
|
ictx->cell.g0set = 0; |
1183 |
|
|
break; |
1184 |
|
|
case INPUT_ESC_SCSG1_ON: |
1185 |
|
|
ictx->cell.g1set = 1; |
1186 |
|
|
break; |
1187 |
|
|
case INPUT_ESC_SCSG1_OFF: |
1188 |
|
|
ictx->cell.g1set = 0; |
1189 |
|
|
break; |
1190 |
|
|
} |
1191 |
|
|
|
1192 |
|
|
return (0); |
1193 |
|
|
} |
1194 |
|
|
|
1195 |
|
|
/* Execute control sequence. */ |
1196 |
|
|
int |
1197 |
|
|
input_csi_dispatch(struct input_ctx *ictx) |
1198 |
|
|
{ |
1199 |
|
|
struct screen_write_ctx *sctx = &ictx->ctx; |
1200 |
|
|
struct screen *s = sctx->s; |
1201 |
|
|
struct input_table_entry *entry; |
1202 |
|
|
int n, m; |
1203 |
|
|
u_int cx; |
1204 |
|
|
|
1205 |
|
|
if (ictx->flags & INPUT_DISCARD) |
1206 |
|
|
return (0); |
1207 |
|
|
if (input_split(ictx) != 0) |
1208 |
|
|
return (0); |
1209 |
|
|
log_debug("%s: '%c' \"%s\" \"%s\"", |
1210 |
|
|
__func__, ictx->ch, ictx->interm_buf, ictx->param_buf); |
1211 |
|
|
|
1212 |
|
|
entry = bsearch(ictx, input_csi_table, nitems(input_csi_table), |
1213 |
|
|
sizeof input_csi_table[0], input_table_compare); |
1214 |
|
|
if (entry == NULL) { |
1215 |
|
|
log_debug("%s: unknown '%c'", __func__, ictx->ch); |
1216 |
|
|
return (0); |
1217 |
|
|
} |
1218 |
|
|
|
1219 |
|
|
switch (entry->type) { |
1220 |
|
|
case INPUT_CSI_CBT: |
1221 |
|
|
/* Find the previous tab point, n times. */ |
1222 |
|
|
cx = s->cx; |
1223 |
|
|
if (cx > screen_size_x(s) - 1) |
1224 |
|
|
cx = screen_size_x(s) - 1; |
1225 |
|
|
n = input_get(ictx, 0, 1, 1); |
1226 |
|
|
while (cx > 0 && n-- > 0) { |
1227 |
|
|
do |
1228 |
|
|
cx--; |
1229 |
|
|
while (cx > 0 && !bit_test(s->tabs, cx)); |
1230 |
|
|
} |
1231 |
|
|
s->cx = cx; |
1232 |
|
|
break; |
1233 |
|
|
case INPUT_CSI_CUB: |
1234 |
|
|
screen_write_cursorleft(sctx, input_get(ictx, 0, 1, 1)); |
1235 |
|
|
break; |
1236 |
|
|
case INPUT_CSI_CUD: |
1237 |
|
|
screen_write_cursordown(sctx, input_get(ictx, 0, 1, 1)); |
1238 |
|
|
break; |
1239 |
|
|
case INPUT_CSI_CUF: |
1240 |
|
|
screen_write_cursorright(sctx, input_get(ictx, 0, 1, 1)); |
1241 |
|
|
break; |
1242 |
|
|
case INPUT_CSI_CUP: |
1243 |
|
|
n = input_get(ictx, 0, 1, 1); |
1244 |
|
|
m = input_get(ictx, 1, 1, 1); |
1245 |
|
|
screen_write_cursormove(sctx, m - 1, n - 1); |
1246 |
|
|
break; |
1247 |
|
|
case INPUT_CSI_WINOPS: |
1248 |
|
|
input_csi_dispatch_winops(ictx); |
1249 |
|
|
break; |
1250 |
|
|
case INPUT_CSI_CUU: |
1251 |
|
|
screen_write_cursorup(sctx, input_get(ictx, 0, 1, 1)); |
1252 |
|
|
break; |
1253 |
|
|
case INPUT_CSI_CNL: |
1254 |
|
|
screen_write_carriagereturn(sctx); |
1255 |
|
|
screen_write_cursordown(sctx, input_get(ictx, 0, 1, 1)); |
1256 |
|
|
break; |
1257 |
|
|
case INPUT_CSI_CPL: |
1258 |
|
|
screen_write_carriagereturn(sctx); |
1259 |
|
|
screen_write_cursorup(sctx, input_get(ictx, 0, 1, 1)); |
1260 |
|
|
break; |
1261 |
|
|
case INPUT_CSI_DA: |
1262 |
|
|
switch (input_get(ictx, 0, 0, 0)) { |
1263 |
|
|
case 0: |
1264 |
|
|
input_reply(ictx, "\033[?1;2c"); |
1265 |
|
|
break; |
1266 |
|
|
default: |
1267 |
|
|
log_debug("%s: unknown '%c'", __func__, ictx->ch); |
1268 |
|
|
break; |
1269 |
|
|
} |
1270 |
|
|
break; |
1271 |
|
|
case INPUT_CSI_DA_TWO: |
1272 |
|
|
switch (input_get(ictx, 0, 0, 0)) { |
1273 |
|
|
case 0: |
1274 |
|
|
input_reply(ictx, "\033[>84;0;0c"); |
1275 |
|
|
break; |
1276 |
|
|
default: |
1277 |
|
|
log_debug("%s: unknown '%c'", __func__, ictx->ch); |
1278 |
|
|
break; |
1279 |
|
|
} |
1280 |
|
|
break; |
1281 |
|
|
case INPUT_CSI_ECH: |
1282 |
|
|
screen_write_clearcharacter(sctx, input_get(ictx, 0, 1, 1)); |
1283 |
|
|
break; |
1284 |
|
|
case INPUT_CSI_DCH: |
1285 |
|
|
screen_write_deletecharacter(sctx, input_get(ictx, 0, 1, 1)); |
1286 |
|
|
break; |
1287 |
|
|
case INPUT_CSI_DECSTBM: |
1288 |
|
|
n = input_get(ictx, 0, 1, 1); |
1289 |
|
|
m = input_get(ictx, 1, 1, screen_size_y(s)); |
1290 |
|
|
screen_write_scrollregion(sctx, n - 1, m - 1); |
1291 |
|
|
break; |
1292 |
|
|
case INPUT_CSI_DL: |
1293 |
|
|
screen_write_deleteline(sctx, input_get(ictx, 0, 1, 1)); |
1294 |
|
|
break; |
1295 |
|
|
case INPUT_CSI_DSR: |
1296 |
|
|
switch (input_get(ictx, 0, 0, 0)) { |
1297 |
|
|
case 5: |
1298 |
|
|
input_reply(ictx, "\033[0n"); |
1299 |
|
|
break; |
1300 |
|
|
case 6: |
1301 |
|
|
input_reply(ictx, "\033[%u;%uR", s->cy + 1, s->cx + 1); |
1302 |
|
|
break; |
1303 |
|
|
default: |
1304 |
|
|
log_debug("%s: unknown '%c'", __func__, ictx->ch); |
1305 |
|
|
break; |
1306 |
|
|
} |
1307 |
|
|
break; |
1308 |
|
|
case INPUT_CSI_ED: |
1309 |
|
|
switch (input_get(ictx, 0, 0, 0)) { |
1310 |
|
|
case 0: |
1311 |
|
|
screen_write_clearendofscreen(sctx); |
1312 |
|
|
break; |
1313 |
|
|
case 1: |
1314 |
|
|
screen_write_clearstartofscreen(sctx); |
1315 |
|
|
break; |
1316 |
|
|
case 2: |
1317 |
|
|
screen_write_clearscreen(sctx); |
1318 |
|
|
break; |
1319 |
|
|
case 3: |
1320 |
|
|
switch (input_get(ictx, 1, 0, 0)) { |
1321 |
|
|
case 0: |
1322 |
|
|
/* |
1323 |
|
|
* Linux console extension to clear history |
1324 |
|
|
* (for example before locking the screen). |
1325 |
|
|
*/ |
1326 |
|
|
screen_write_clearhistory(sctx); |
1327 |
|
|
break; |
1328 |
|
|
} |
1329 |
|
|
break; |
1330 |
|
|
default: |
1331 |
|
|
log_debug("%s: unknown '%c'", __func__, ictx->ch); |
1332 |
|
|
break; |
1333 |
|
|
} |
1334 |
|
|
break; |
1335 |
|
|
case INPUT_CSI_EL: |
1336 |
|
|
switch (input_get(ictx, 0, 0, 0)) { |
1337 |
|
|
case 0: |
1338 |
|
|
screen_write_clearendofline(sctx); |
1339 |
|
|
break; |
1340 |
|
|
case 1: |
1341 |
|
|
screen_write_clearstartofline(sctx); |
1342 |
|
|
break; |
1343 |
|
|
case 2: |
1344 |
|
|
screen_write_clearline(sctx); |
1345 |
|
|
break; |
1346 |
|
|
default: |
1347 |
|
|
log_debug("%s: unknown '%c'", __func__, ictx->ch); |
1348 |
|
|
break; |
1349 |
|
|
} |
1350 |
|
|
break; |
1351 |
|
|
case INPUT_CSI_HPA: |
1352 |
|
|
n = input_get(ictx, 0, 1, 1); |
1353 |
|
|
screen_write_cursormove(sctx, n - 1, s->cy); |
1354 |
|
|
break; |
1355 |
|
|
case INPUT_CSI_ICH: |
1356 |
|
|
screen_write_insertcharacter(sctx, input_get(ictx, 0, 1, 1)); |
1357 |
|
|
break; |
1358 |
|
|
case INPUT_CSI_IL: |
1359 |
|
|
screen_write_insertline(sctx, input_get(ictx, 0, 1, 1)); |
1360 |
|
|
break; |
1361 |
|
|
case INPUT_CSI_RCP: |
1362 |
|
|
memcpy(&ictx->cell, &ictx->old_cell, sizeof ictx->cell); |
1363 |
|
|
screen_write_cursormove(sctx, ictx->old_cx, ictx->old_cy); |
1364 |
|
|
break; |
1365 |
|
|
case INPUT_CSI_RM: |
1366 |
|
|
input_csi_dispatch_rm(ictx); |
1367 |
|
|
break; |
1368 |
|
|
case INPUT_CSI_RM_PRIVATE: |
1369 |
|
|
input_csi_dispatch_rm_private(ictx); |
1370 |
|
|
break; |
1371 |
|
|
case INPUT_CSI_SCP: |
1372 |
|
|
memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell); |
1373 |
|
|
ictx->old_cx = s->cx; |
1374 |
|
|
ictx->old_cy = s->cy; |
1375 |
|
|
break; |
1376 |
|
|
case INPUT_CSI_SGR: |
1377 |
|
|
input_csi_dispatch_sgr(ictx); |
1378 |
|
|
break; |
1379 |
|
|
case INPUT_CSI_SM: |
1380 |
|
|
input_csi_dispatch_sm(ictx); |
1381 |
|
|
break; |
1382 |
|
|
case INPUT_CSI_SM_PRIVATE: |
1383 |
|
|
input_csi_dispatch_sm_private(ictx); |
1384 |
|
|
break; |
1385 |
|
|
case INPUT_CSI_TBC: |
1386 |
|
|
switch (input_get(ictx, 0, 0, 0)) { |
1387 |
|
|
case 0: |
1388 |
|
|
if (s->cx < screen_size_x(s)) |
1389 |
|
|
bit_clear(s->tabs, s->cx); |
1390 |
|
|
break; |
1391 |
|
|
case 3: |
1392 |
|
|
bit_nclear(s->tabs, 0, screen_size_x(s) - 1); |
1393 |
|
|
break; |
1394 |
|
|
default: |
1395 |
|
|
log_debug("%s: unknown '%c'", __func__, ictx->ch); |
1396 |
|
|
break; |
1397 |
|
|
} |
1398 |
|
|
break; |
1399 |
|
|
case INPUT_CSI_VPA: |
1400 |
|
|
n = input_get(ictx, 0, 1, 1); |
1401 |
|
|
screen_write_cursormove(sctx, s->cx, n - 1); |
1402 |
|
|
break; |
1403 |
|
|
case INPUT_CSI_DECSCUSR: |
1404 |
|
|
n = input_get(ictx, 0, 0, 0); |
1405 |
|
|
screen_set_cursor_style(s, n); |
1406 |
|
|
break; |
1407 |
|
|
} |
1408 |
|
|
|
1409 |
|
|
return (0); |
1410 |
|
|
} |
1411 |
|
|
|
1412 |
|
|
/* Handle CSI RM. */ |
1413 |
|
|
void |
1414 |
|
|
input_csi_dispatch_rm(struct input_ctx *ictx) |
1415 |
|
|
{ |
1416 |
|
|
u_int i; |
1417 |
|
|
|
1418 |
|
|
for (i = 0; i < ictx->param_list_len; i++) { |
1419 |
|
|
switch (input_get(ictx, i, 0, -1)) { |
1420 |
|
|
case 4: /* IRM */ |
1421 |
|
|
screen_write_mode_clear(&ictx->ctx, MODE_INSERT); |
1422 |
|
|
break; |
1423 |
|
|
case 34: |
1424 |
|
|
screen_write_mode_set(&ictx->ctx, MODE_BLINKING); |
1425 |
|
|
break; |
1426 |
|
|
default: |
1427 |
|
|
log_debug("%s: unknown '%c'", __func__, ictx->ch); |
1428 |
|
|
break; |
1429 |
|
|
} |
1430 |
|
|
} |
1431 |
|
|
} |
1432 |
|
|
|
1433 |
|
|
/* Handle CSI private RM. */ |
1434 |
|
|
void |
1435 |
|
|
input_csi_dispatch_rm_private(struct input_ctx *ictx) |
1436 |
|
|
{ |
1437 |
|
|
struct window_pane *wp = ictx->wp; |
1438 |
|
|
u_int i; |
1439 |
|
|
|
1440 |
|
|
for (i = 0; i < ictx->param_list_len; i++) { |
1441 |
|
|
switch (input_get(ictx, i, 0, -1)) { |
1442 |
|
|
case 1: /* DECCKM */ |
1443 |
|
|
screen_write_mode_clear(&ictx->ctx, MODE_KCURSOR); |
1444 |
|
|
break; |
1445 |
|
|
case 3: /* DECCOLM */ |
1446 |
|
|
screen_write_cursormove(&ictx->ctx, 0, 0); |
1447 |
|
|
screen_write_clearscreen(&ictx->ctx); |
1448 |
|
|
break; |
1449 |
|
|
case 7: /* DECAWM */ |
1450 |
|
|
screen_write_mode_clear(&ictx->ctx, MODE_WRAP); |
1451 |
|
|
break; |
1452 |
|
|
case 12: |
1453 |
|
|
screen_write_mode_clear(&ictx->ctx, MODE_BLINKING); |
1454 |
|
|
break; |
1455 |
|
|
case 25: /* TCEM */ |
1456 |
|
|
screen_write_mode_clear(&ictx->ctx, MODE_CURSOR); |
1457 |
|
|
break; |
1458 |
|
|
case 1000: |
1459 |
|
|
case 1001: |
1460 |
|
|
case 1002: |
1461 |
|
|
screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES); |
1462 |
|
|
break; |
1463 |
|
|
case 1004: |
1464 |
|
|
screen_write_mode_clear(&ictx->ctx, MODE_FOCUSON); |
1465 |
|
|
break; |
1466 |
|
|
case 1005: |
1467 |
|
|
screen_write_mode_clear(&ictx->ctx, MODE_MOUSE_UTF8); |
1468 |
|
|
break; |
1469 |
|
|
case 1006: |
1470 |
|
|
screen_write_mode_clear(&ictx->ctx, MODE_MOUSE_SGR); |
1471 |
|
|
break; |
1472 |
|
|
case 47: |
1473 |
|
|
case 1047: |
1474 |
|
|
window_pane_alternate_off(wp, &ictx->cell.cell, 0); |
1475 |
|
|
break; |
1476 |
|
|
case 1049: |
1477 |
|
|
window_pane_alternate_off(wp, &ictx->cell.cell, 1); |
1478 |
|
|
break; |
1479 |
|
|
case 2004: |
1480 |
|
|
screen_write_mode_clear(&ictx->ctx, MODE_BRACKETPASTE); |
1481 |
|
|
break; |
1482 |
|
|
default: |
1483 |
|
|
log_debug("%s: unknown '%c'", __func__, ictx->ch); |
1484 |
|
|
break; |
1485 |
|
|
} |
1486 |
|
|
} |
1487 |
|
|
} |
1488 |
|
|
|
1489 |
|
|
/* Handle CSI SM. */ |
1490 |
|
|
void |
1491 |
|
|
input_csi_dispatch_sm(struct input_ctx *ictx) |
1492 |
|
|
{ |
1493 |
|
|
u_int i; |
1494 |
|
|
|
1495 |
|
|
for (i = 0; i < ictx->param_list_len; i++) { |
1496 |
|
|
switch (input_get(ictx, i, 0, -1)) { |
1497 |
|
|
case 4: /* IRM */ |
1498 |
|
|
screen_write_mode_set(&ictx->ctx, MODE_INSERT); |
1499 |
|
|
break; |
1500 |
|
|
case 34: |
1501 |
|
|
screen_write_mode_clear(&ictx->ctx, MODE_BLINKING); |
1502 |
|
|
break; |
1503 |
|
|
default: |
1504 |
|
|
log_debug("%s: unknown '%c'", __func__, ictx->ch); |
1505 |
|
|
break; |
1506 |
|
|
} |
1507 |
|
|
} |
1508 |
|
|
} |
1509 |
|
|
|
1510 |
|
|
/* Handle CSI private SM. */ |
1511 |
|
|
void |
1512 |
|
|
input_csi_dispatch_sm_private(struct input_ctx *ictx) |
1513 |
|
|
{ |
1514 |
|
|
struct window_pane *wp = ictx->wp; |
1515 |
|
|
u_int i; |
1516 |
|
|
|
1517 |
|
|
for (i = 0; i < ictx->param_list_len; i++) { |
1518 |
|
|
switch (input_get(ictx, i, 0, -1)) { |
1519 |
|
|
case 1: /* DECCKM */ |
1520 |
|
|
screen_write_mode_set(&ictx->ctx, MODE_KCURSOR); |
1521 |
|
|
break; |
1522 |
|
|
case 3: /* DECCOLM */ |
1523 |
|
|
screen_write_cursormove(&ictx->ctx, 0, 0); |
1524 |
|
|
screen_write_clearscreen(&ictx->ctx); |
1525 |
|
|
break; |
1526 |
|
|
case 7: /* DECAWM */ |
1527 |
|
|
screen_write_mode_set(&ictx->ctx, MODE_WRAP); |
1528 |
|
|
break; |
1529 |
|
|
case 12: |
1530 |
|
|
screen_write_mode_set(&ictx->ctx, MODE_BLINKING); |
1531 |
|
|
break; |
1532 |
|
|
case 25: /* TCEM */ |
1533 |
|
|
screen_write_mode_set(&ictx->ctx, MODE_CURSOR); |
1534 |
|
|
break; |
1535 |
|
|
case 1000: |
1536 |
|
|
screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES); |
1537 |
|
|
screen_write_mode_set(&ictx->ctx, MODE_MOUSE_STANDARD); |
1538 |
|
|
break; |
1539 |
|
|
case 1002: |
1540 |
|
|
screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES); |
1541 |
|
|
screen_write_mode_set(&ictx->ctx, MODE_MOUSE_BUTTON); |
1542 |
|
|
break; |
1543 |
|
|
case 1004: |
1544 |
|
|
if (ictx->ctx.s->mode & MODE_FOCUSON) |
1545 |
|
|
break; |
1546 |
|
|
screen_write_mode_set(&ictx->ctx, MODE_FOCUSON); |
1547 |
|
|
wp->flags |= PANE_FOCUSPUSH; /* force update */ |
1548 |
|
|
break; |
1549 |
|
|
case 1005: |
1550 |
|
|
screen_write_mode_set(&ictx->ctx, MODE_MOUSE_UTF8); |
1551 |
|
|
break; |
1552 |
|
|
case 1006: |
1553 |
|
|
screen_write_mode_set(&ictx->ctx, MODE_MOUSE_SGR); |
1554 |
|
|
break; |
1555 |
|
|
case 47: |
1556 |
|
|
case 1047: |
1557 |
|
|
window_pane_alternate_on(wp, &ictx->cell.cell, 0); |
1558 |
|
|
break; |
1559 |
|
|
case 1049: |
1560 |
|
|
window_pane_alternate_on(wp, &ictx->cell.cell, 1); |
1561 |
|
|
break; |
1562 |
|
|
case 2004: |
1563 |
|
|
screen_write_mode_set(&ictx->ctx, MODE_BRACKETPASTE); |
1564 |
|
|
break; |
1565 |
|
|
default: |
1566 |
|
|
log_debug("%s: unknown '%c'", __func__, ictx->ch); |
1567 |
|
|
break; |
1568 |
|
|
} |
1569 |
|
|
} |
1570 |
|
|
} |
1571 |
|
|
|
1572 |
|
|
/* Handle CSI window operations. */ |
1573 |
|
|
void |
1574 |
|
|
input_csi_dispatch_winops(struct input_ctx *ictx) |
1575 |
|
|
{ |
1576 |
|
|
struct window_pane *wp = ictx->wp; |
1577 |
|
|
int n, m; |
1578 |
|
|
|
1579 |
|
|
m = 0; |
1580 |
|
|
while ((n = input_get(ictx, m, 0, -1)) != -1) { |
1581 |
|
|
switch (n) { |
1582 |
|
|
case 1: |
1583 |
|
|
case 2: |
1584 |
|
|
case 5: |
1585 |
|
|
case 6: |
1586 |
|
|
case 7: |
1587 |
|
|
case 11: |
1588 |
|
|
case 13: |
1589 |
|
|
case 14: |
1590 |
|
|
case 19: |
1591 |
|
|
case 20: |
1592 |
|
|
case 21: |
1593 |
|
|
case 24: |
1594 |
|
|
break; |
1595 |
|
|
case 3: |
1596 |
|
|
case 4: |
1597 |
|
|
case 8: |
1598 |
|
|
m++; |
1599 |
|
|
if (input_get(ictx, m, 0, -1) == -1) |
1600 |
|
|
return; |
1601 |
|
|
/* FALLTHROUGH */ |
1602 |
|
|
case 9: |
1603 |
|
|
case 10: |
1604 |
|
|
case 22: |
1605 |
|
|
case 23: |
1606 |
|
|
m++; |
1607 |
|
|
if (input_get(ictx, m, 0, -1) == -1) |
1608 |
|
|
return; |
1609 |
|
|
break; |
1610 |
|
|
case 18: |
1611 |
|
|
input_reply(ictx, "\033[8;%u;%ut", wp->sy, wp->sx); |
1612 |
|
|
break; |
1613 |
|
|
default: |
1614 |
|
|
log_debug("%s: unknown '%c'", __func__, ictx->ch); |
1615 |
|
|
break; |
1616 |
|
|
} |
1617 |
|
|
m++; |
1618 |
|
|
} |
1619 |
|
|
} |
1620 |
|
|
|
1621 |
|
|
/* Handle CSI SGR for 256 colours. */ |
1622 |
|
|
void |
1623 |
|
|
input_csi_dispatch_sgr_256(struct input_ctx *ictx, int fgbg, u_int *i) |
1624 |
|
|
{ |
1625 |
|
|
struct grid_cell *gc = &ictx->cell.cell; |
1626 |
|
|
int c; |
1627 |
|
|
|
1628 |
|
|
(*i)++; |
1629 |
|
|
c = input_get(ictx, *i, 0, -1); |
1630 |
|
|
if (c == -1) { |
1631 |
|
|
if (fgbg == 38) |
1632 |
|
|
gc->fg = 8; |
1633 |
|
|
else if (fgbg == 48) |
1634 |
|
|
gc->bg = 8; |
1635 |
|
|
} else { |
1636 |
|
|
if (fgbg == 38) |
1637 |
|
|
gc->fg = c | COLOUR_FLAG_256; |
1638 |
|
|
else if (fgbg == 48) |
1639 |
|
|
gc->bg = c | COLOUR_FLAG_256; |
1640 |
|
|
} |
1641 |
|
|
} |
1642 |
|
|
|
1643 |
|
|
/* Handle CSI SGR for RGB colours. */ |
1644 |
|
|
void |
1645 |
|
|
input_csi_dispatch_sgr_rgb(struct input_ctx *ictx, int fgbg, u_int *i) |
1646 |
|
|
{ |
1647 |
|
|
struct grid_cell *gc = &ictx->cell.cell; |
1648 |
|
|
int r, g, b; |
1649 |
|
|
|
1650 |
|
|
(*i)++; |
1651 |
|
|
r = input_get(ictx, *i, 0, -1); |
1652 |
|
|
if (r == -1 || r > 255) |
1653 |
|
|
return; |
1654 |
|
|
(*i)++; |
1655 |
|
|
g = input_get(ictx, *i, 0, -1); |
1656 |
|
|
if (g == -1 || g > 255) |
1657 |
|
|
return; |
1658 |
|
|
(*i)++; |
1659 |
|
|
b = input_get(ictx, *i, 0, -1); |
1660 |
|
|
if (b == -1 || b > 255) |
1661 |
|
|
return; |
1662 |
|
|
|
1663 |
|
|
if (fgbg == 38) |
1664 |
|
|
gc->fg = colour_join_rgb(r, g, b); |
1665 |
|
|
else if (fgbg == 48) |
1666 |
|
|
gc->bg = colour_join_rgb(r, g, b); |
1667 |
|
|
} |
1668 |
|
|
|
1669 |
|
|
/* Handle CSI SGR. */ |
1670 |
|
|
void |
1671 |
|
|
input_csi_dispatch_sgr(struct input_ctx *ictx) |
1672 |
|
|
{ |
1673 |
|
|
struct grid_cell *gc = &ictx->cell.cell; |
1674 |
|
|
u_int i; |
1675 |
|
|
int n; |
1676 |
|
|
|
1677 |
|
|
if (ictx->param_list_len == 0) { |
1678 |
|
|
memcpy(gc, &grid_default_cell, sizeof *gc); |
1679 |
|
|
return; |
1680 |
|
|
} |
1681 |
|
|
|
1682 |
|
|
for (i = 0; i < ictx->param_list_len; i++) { |
1683 |
|
|
n = input_get(ictx, i, 0, 0); |
1684 |
|
|
|
1685 |
|
|
if (n == 38 || n == 48) { |
1686 |
|
|
i++; |
1687 |
|
|
switch (input_get(ictx, i, 0, -1)) { |
1688 |
|
|
case 2: |
1689 |
|
|
input_csi_dispatch_sgr_rgb(ictx, n, &i); |
1690 |
|
|
break; |
1691 |
|
|
case 5: |
1692 |
|
|
input_csi_dispatch_sgr_256(ictx, n, &i); |
1693 |
|
|
break; |
1694 |
|
|
} |
1695 |
|
|
continue; |
1696 |
|
|
} |
1697 |
|
|
|
1698 |
|
|
switch (n) { |
1699 |
|
|
case 0: |
1700 |
|
|
case 10: |
1701 |
|
|
memcpy(gc, &grid_default_cell, sizeof *gc); |
1702 |
|
|
break; |
1703 |
|
|
case 1: |
1704 |
|
|
gc->attr |= GRID_ATTR_BRIGHT; |
1705 |
|
|
break; |
1706 |
|
|
case 2: |
1707 |
|
|
gc->attr |= GRID_ATTR_DIM; |
1708 |
|
|
break; |
1709 |
|
|
case 3: |
1710 |
|
|
gc->attr |= GRID_ATTR_ITALICS; |
1711 |
|
|
break; |
1712 |
|
|
case 4: |
1713 |
|
|
gc->attr |= GRID_ATTR_UNDERSCORE; |
1714 |
|
|
break; |
1715 |
|
|
case 5: |
1716 |
|
|
gc->attr |= GRID_ATTR_BLINK; |
1717 |
|
|
break; |
1718 |
|
|
case 7: |
1719 |
|
|
gc->attr |= GRID_ATTR_REVERSE; |
1720 |
|
|
break; |
1721 |
|
|
case 8: |
1722 |
|
|
gc->attr |= GRID_ATTR_HIDDEN; |
1723 |
|
|
break; |
1724 |
|
|
case 22: |
1725 |
|
|
gc->attr &= ~(GRID_ATTR_BRIGHT|GRID_ATTR_DIM); |
1726 |
|
|
break; |
1727 |
|
|
case 23: |
1728 |
|
|
gc->attr &= ~GRID_ATTR_ITALICS; |
1729 |
|
|
break; |
1730 |
|
|
case 24: |
1731 |
|
|
gc->attr &= ~GRID_ATTR_UNDERSCORE; |
1732 |
|
|
break; |
1733 |
|
|
case 25: |
1734 |
|
|
gc->attr &= ~GRID_ATTR_BLINK; |
1735 |
|
|
break; |
1736 |
|
|
case 27: |
1737 |
|
|
gc->attr &= ~GRID_ATTR_REVERSE; |
1738 |
|
|
break; |
1739 |
|
|
case 30: |
1740 |
|
|
case 31: |
1741 |
|
|
case 32: |
1742 |
|
|
case 33: |
1743 |
|
|
case 34: |
1744 |
|
|
case 35: |
1745 |
|
|
case 36: |
1746 |
|
|
case 37: |
1747 |
|
|
gc->fg = n - 30; |
1748 |
|
|
break; |
1749 |
|
|
case 39: |
1750 |
|
|
gc->fg = 8; |
1751 |
|
|
break; |
1752 |
|
|
case 40: |
1753 |
|
|
case 41: |
1754 |
|
|
case 42: |
1755 |
|
|
case 43: |
1756 |
|
|
case 44: |
1757 |
|
|
case 45: |
1758 |
|
|
case 46: |
1759 |
|
|
case 47: |
1760 |
|
|
gc->bg = n - 40; |
1761 |
|
|
break; |
1762 |
|
|
case 49: |
1763 |
|
|
gc->bg = 8; |
1764 |
|
|
break; |
1765 |
|
|
case 90: |
1766 |
|
|
case 91: |
1767 |
|
|
case 92: |
1768 |
|
|
case 93: |
1769 |
|
|
case 94: |
1770 |
|
|
case 95: |
1771 |
|
|
case 96: |
1772 |
|
|
case 97: |
1773 |
|
|
gc->fg = n; |
1774 |
|
|
break; |
1775 |
|
|
case 100: |
1776 |
|
|
case 101: |
1777 |
|
|
case 102: |
1778 |
|
|
case 103: |
1779 |
|
|
case 104: |
1780 |
|
|
case 105: |
1781 |
|
|
case 106: |
1782 |
|
|
case 107: |
1783 |
|
|
gc->bg = n - 10; |
1784 |
|
|
break; |
1785 |
|
|
} |
1786 |
|
|
} |
1787 |
|
|
} |
1788 |
|
|
|
1789 |
|
|
/* DCS terminator (ST) received. */ |
1790 |
|
|
int |
1791 |
|
|
input_dcs_dispatch(struct input_ctx *ictx) |
1792 |
|
|
{ |
1793 |
|
|
const char prefix[] = "tmux;"; |
1794 |
|
|
const u_int prefix_len = (sizeof prefix) - 1; |
1795 |
|
|
|
1796 |
|
|
if (ictx->flags & INPUT_DISCARD) |
1797 |
|
|
return (0); |
1798 |
|
|
|
1799 |
|
|
log_debug("%s: \"%s\"", __func__, ictx->input_buf); |
1800 |
|
|
|
1801 |
|
|
/* Check for tmux prefix. */ |
1802 |
|
|
if (ictx->input_len >= prefix_len && |
1803 |
|
|
strncmp(ictx->input_buf, prefix, prefix_len) == 0) { |
1804 |
|
|
screen_write_rawstring(&ictx->ctx, |
1805 |
|
|
ictx->input_buf + prefix_len, ictx->input_len - prefix_len); |
1806 |
|
|
} |
1807 |
|
|
|
1808 |
|
|
return (0); |
1809 |
|
|
} |
1810 |
|
|
|
1811 |
|
|
/* OSC string started. */ |
1812 |
|
|
void |
1813 |
|
|
input_enter_osc(struct input_ctx *ictx) |
1814 |
|
|
{ |
1815 |
|
|
log_debug("%s", __func__); |
1816 |
|
|
|
1817 |
|
|
input_clear(ictx); |
1818 |
|
|
} |
1819 |
|
|
|
1820 |
|
|
/* OSC terminator (ST) received. */ |
1821 |
|
|
void |
1822 |
|
|
input_exit_osc(struct input_ctx *ictx) |
1823 |
|
|
{ |
1824 |
|
|
u_char *p = ictx->input_buf; |
1825 |
|
|
u_int option; |
1826 |
|
|
|
1827 |
|
|
if (ictx->flags & INPUT_DISCARD) |
1828 |
|
|
return; |
1829 |
|
|
if (ictx->input_len < 1 || *p < '0' || *p > '9') |
1830 |
|
|
return; |
1831 |
|
|
|
1832 |
|
|
log_debug("%s: \"%s\"", __func__, p); |
1833 |
|
|
|
1834 |
|
|
option = 0; |
1835 |
|
|
while (*p >= '0' && *p <= '9') |
1836 |
|
|
option = option * 10 + *p++ - '0'; |
1837 |
|
|
if (*p == ';') |
1838 |
|
|
p++; |
1839 |
|
|
|
1840 |
|
|
switch (option) { |
1841 |
|
|
case 0: |
1842 |
|
|
case 2: |
1843 |
|
|
screen_set_title(ictx->ctx.s, p); |
1844 |
|
|
server_status_window(ictx->wp->window); |
1845 |
|
|
break; |
1846 |
|
|
case 12: |
1847 |
|
|
if (*p != '?') /* ? is colour request */ |
1848 |
|
|
screen_set_cursor_colour(ictx->ctx.s, p); |
1849 |
|
|
break; |
1850 |
|
|
case 112: |
1851 |
|
|
if (*p == '\0') /* no arguments allowed */ |
1852 |
|
|
screen_set_cursor_colour(ictx->ctx.s, ""); |
1853 |
|
|
break; |
1854 |
|
|
default: |
1855 |
|
|
log_debug("%s: unknown '%u'", __func__, option); |
1856 |
|
|
break; |
1857 |
|
|
} |
1858 |
|
|
} |
1859 |
|
|
|
1860 |
|
|
/* APC string started. */ |
1861 |
|
|
void |
1862 |
|
|
input_enter_apc(struct input_ctx *ictx) |
1863 |
|
|
{ |
1864 |
|
|
log_debug("%s", __func__); |
1865 |
|
|
|
1866 |
|
|
input_clear(ictx); |
1867 |
|
|
} |
1868 |
|
|
|
1869 |
|
|
/* APC terminator (ST) received. */ |
1870 |
|
|
void |
1871 |
|
|
input_exit_apc(struct input_ctx *ictx) |
1872 |
|
|
{ |
1873 |
|
|
if (ictx->flags & INPUT_DISCARD) |
1874 |
|
|
return; |
1875 |
|
|
log_debug("%s: \"%s\"", __func__, ictx->input_buf); |
1876 |
|
|
|
1877 |
|
|
screen_set_title(ictx->ctx.s, ictx->input_buf); |
1878 |
|
|
server_status_window(ictx->wp->window); |
1879 |
|
|
} |
1880 |
|
|
|
1881 |
|
|
/* Rename string started. */ |
1882 |
|
|
void |
1883 |
|
|
input_enter_rename(struct input_ctx *ictx) |
1884 |
|
|
{ |
1885 |
|
|
log_debug("%s", __func__); |
1886 |
|
|
|
1887 |
|
|
input_clear(ictx); |
1888 |
|
|
} |
1889 |
|
|
|
1890 |
|
|
/* Rename terminator (ST) received. */ |
1891 |
|
|
void |
1892 |
|
|
input_exit_rename(struct input_ctx *ictx) |
1893 |
|
|
{ |
1894 |
|
|
if (ictx->flags & INPUT_DISCARD) |
1895 |
|
|
return; |
1896 |
|
|
if (!options_get_number(ictx->wp->window->options, "allow-rename")) |
1897 |
|
|
return; |
1898 |
|
|
log_debug("%s: \"%s\"", __func__, ictx->input_buf); |
1899 |
|
|
|
1900 |
|
|
window_set_name(ictx->wp->window, ictx->input_buf); |
1901 |
|
|
options_set_number(ictx->wp->window->options, "automatic-rename", 0); |
1902 |
|
|
|
1903 |
|
|
server_status_window(ictx->wp->window); |
1904 |
|
|
} |
1905 |
|
|
|
1906 |
|
|
/* Open UTF-8 character. */ |
1907 |
|
|
int |
1908 |
|
|
input_utf8_open(struct input_ctx *ictx) |
1909 |
|
|
{ |
1910 |
|
|
struct utf8_data *ud = &ictx->utf8data; |
1911 |
|
|
|
1912 |
|
|
if (utf8_open(ud, ictx->ch) != UTF8_MORE) |
1913 |
|
|
fatalx("UTF-8 open invalid %#x", ictx->ch); |
1914 |
|
|
|
1915 |
|
|
log_debug("%s %hhu", __func__, ud->size); |
1916 |
|
|
|
1917 |
|
|
return (0); |
1918 |
|
|
} |
1919 |
|
|
|
1920 |
|
|
/* Append to UTF-8 character. */ |
1921 |
|
|
int |
1922 |
|
|
input_utf8_add(struct input_ctx *ictx) |
1923 |
|
|
{ |
1924 |
|
|
struct utf8_data *ud = &ictx->utf8data; |
1925 |
|
|
|
1926 |
|
|
if (utf8_append(ud, ictx->ch) != UTF8_MORE) |
1927 |
|
|
fatalx("UTF-8 add invalid %#x", ictx->ch); |
1928 |
|
|
|
1929 |
|
|
log_debug("%s", __func__); |
1930 |
|
|
|
1931 |
|
|
return (0); |
1932 |
|
|
} |
1933 |
|
|
|
1934 |
|
|
/* Close UTF-8 string. */ |
1935 |
|
|
int |
1936 |
|
|
input_utf8_close(struct input_ctx *ictx) |
1937 |
|
|
{ |
1938 |
|
|
struct utf8_data *ud = &ictx->utf8data; |
1939 |
|
|
|
1940 |
|
|
if (utf8_append(ud, ictx->ch) != UTF8_DONE) { |
1941 |
|
|
/* |
1942 |
|
|
* An error here could be invalid UTF-8 or it could be a |
1943 |
|
|
* nonprintable character for which we can't get the |
1944 |
|
|
* width. Drop it. |
1945 |
|
|
*/ |
1946 |
|
|
return (0); |
1947 |
|
|
} |
1948 |
|
|
|
1949 |
|
|
log_debug("%s %hhu '%*s' (width %hhu)", __func__, ud->size, |
1950 |
|
|
(int)ud->size, ud->data, ud->width); |
1951 |
|
|
|
1952 |
|
|
utf8_copy(&ictx->cell.cell.data, ud); |
1953 |
|
|
screen_write_cell(&ictx->ctx, &ictx->cell.cell); |
1954 |
|
|
|
1955 |
|
|
return (0); |
1956 |
|
|
} |