xref: /aosp_15_r20/external/wpa_supplicant_8/src/utils/edit.c (revision 03f9172ca588f91df233974f4258bab95191f931)
1*03f9172cSAndroid Build Coastguard Worker /*
2*03f9172cSAndroid Build Coastguard Worker  * Command line editing and history
3*03f9172cSAndroid Build Coastguard Worker  * Copyright (c) 2010-2011, Jouni Malinen <[email protected]>
4*03f9172cSAndroid Build Coastguard Worker  *
5*03f9172cSAndroid Build Coastguard Worker  * This software may be distributed under the terms of the BSD license.
6*03f9172cSAndroid Build Coastguard Worker  * See README for more details.
7*03f9172cSAndroid Build Coastguard Worker  */
8*03f9172cSAndroid Build Coastguard Worker 
9*03f9172cSAndroid Build Coastguard Worker #include "includes.h"
10*03f9172cSAndroid Build Coastguard Worker #include <termios.h>
11*03f9172cSAndroid Build Coastguard Worker 
12*03f9172cSAndroid Build Coastguard Worker #include "common.h"
13*03f9172cSAndroid Build Coastguard Worker #include "eloop.h"
14*03f9172cSAndroid Build Coastguard Worker #include "list.h"
15*03f9172cSAndroid Build Coastguard Worker #include "edit.h"
16*03f9172cSAndroid Build Coastguard Worker 
17*03f9172cSAndroid Build Coastguard Worker #define CMD_BUF_LEN 4096
18*03f9172cSAndroid Build Coastguard Worker static char cmdbuf[CMD_BUF_LEN];
19*03f9172cSAndroid Build Coastguard Worker static int cmdbuf_pos = 0;
20*03f9172cSAndroid Build Coastguard Worker static int cmdbuf_len = 0;
21*03f9172cSAndroid Build Coastguard Worker static char currbuf[CMD_BUF_LEN];
22*03f9172cSAndroid Build Coastguard Worker static int currbuf_valid = 0;
23*03f9172cSAndroid Build Coastguard Worker static const char *ps2 = NULL;
24*03f9172cSAndroid Build Coastguard Worker 
25*03f9172cSAndroid Build Coastguard Worker #define HISTORY_MAX 100
26*03f9172cSAndroid Build Coastguard Worker 
27*03f9172cSAndroid Build Coastguard Worker struct edit_history {
28*03f9172cSAndroid Build Coastguard Worker 	struct dl_list list;
29*03f9172cSAndroid Build Coastguard Worker 	char str[1];
30*03f9172cSAndroid Build Coastguard Worker };
31*03f9172cSAndroid Build Coastguard Worker 
32*03f9172cSAndroid Build Coastguard Worker static struct dl_list history_list;
33*03f9172cSAndroid Build Coastguard Worker static struct edit_history *history_curr;
34*03f9172cSAndroid Build Coastguard Worker 
35*03f9172cSAndroid Build Coastguard Worker static void *edit_cb_ctx;
36*03f9172cSAndroid Build Coastguard Worker static void (*edit_cmd_cb)(void *ctx, char *cmd);
37*03f9172cSAndroid Build Coastguard Worker static void (*edit_eof_cb)(void *ctx);
38*03f9172cSAndroid Build Coastguard Worker static char ** (*edit_completion_cb)(void *ctx, const char *cmd, int pos) =
39*03f9172cSAndroid Build Coastguard Worker 	NULL;
40*03f9172cSAndroid Build Coastguard Worker 
41*03f9172cSAndroid Build Coastguard Worker static struct termios prevt, newt;
42*03f9172cSAndroid Build Coastguard Worker 
43*03f9172cSAndroid Build Coastguard Worker 
44*03f9172cSAndroid Build Coastguard Worker #define CLEAR_END_LINE "\e[K"
45*03f9172cSAndroid Build Coastguard Worker 
46*03f9172cSAndroid Build Coastguard Worker 
edit_clear_line(void)47*03f9172cSAndroid Build Coastguard Worker void edit_clear_line(void)
48*03f9172cSAndroid Build Coastguard Worker {
49*03f9172cSAndroid Build Coastguard Worker 	int i;
50*03f9172cSAndroid Build Coastguard Worker 	putchar('\r');
51*03f9172cSAndroid Build Coastguard Worker 	for (i = 0; i < cmdbuf_len + 2 + (ps2 ? (int) os_strlen(ps2) : 0); i++)
52*03f9172cSAndroid Build Coastguard Worker 		putchar(' ');
53*03f9172cSAndroid Build Coastguard Worker }
54*03f9172cSAndroid Build Coastguard Worker 
55*03f9172cSAndroid Build Coastguard Worker 
move_start(void)56*03f9172cSAndroid Build Coastguard Worker static void move_start(void)
57*03f9172cSAndroid Build Coastguard Worker {
58*03f9172cSAndroid Build Coastguard Worker 	cmdbuf_pos = 0;
59*03f9172cSAndroid Build Coastguard Worker 	edit_redraw();
60*03f9172cSAndroid Build Coastguard Worker }
61*03f9172cSAndroid Build Coastguard Worker 
62*03f9172cSAndroid Build Coastguard Worker 
move_end(void)63*03f9172cSAndroid Build Coastguard Worker static void move_end(void)
64*03f9172cSAndroid Build Coastguard Worker {
65*03f9172cSAndroid Build Coastguard Worker 	cmdbuf_pos = cmdbuf_len;
66*03f9172cSAndroid Build Coastguard Worker 	edit_redraw();
67*03f9172cSAndroid Build Coastguard Worker }
68*03f9172cSAndroid Build Coastguard Worker 
69*03f9172cSAndroid Build Coastguard Worker 
move_left(void)70*03f9172cSAndroid Build Coastguard Worker static void move_left(void)
71*03f9172cSAndroid Build Coastguard Worker {
72*03f9172cSAndroid Build Coastguard Worker 	if (cmdbuf_pos > 0) {
73*03f9172cSAndroid Build Coastguard Worker 		cmdbuf_pos--;
74*03f9172cSAndroid Build Coastguard Worker 		edit_redraw();
75*03f9172cSAndroid Build Coastguard Worker 	}
76*03f9172cSAndroid Build Coastguard Worker }
77*03f9172cSAndroid Build Coastguard Worker 
78*03f9172cSAndroid Build Coastguard Worker 
move_right(void)79*03f9172cSAndroid Build Coastguard Worker static void move_right(void)
80*03f9172cSAndroid Build Coastguard Worker {
81*03f9172cSAndroid Build Coastguard Worker 	if (cmdbuf_pos < cmdbuf_len) {
82*03f9172cSAndroid Build Coastguard Worker 		cmdbuf_pos++;
83*03f9172cSAndroid Build Coastguard Worker 		edit_redraw();
84*03f9172cSAndroid Build Coastguard Worker 	}
85*03f9172cSAndroid Build Coastguard Worker }
86*03f9172cSAndroid Build Coastguard Worker 
87*03f9172cSAndroid Build Coastguard Worker 
move_word_left(void)88*03f9172cSAndroid Build Coastguard Worker static void move_word_left(void)
89*03f9172cSAndroid Build Coastguard Worker {
90*03f9172cSAndroid Build Coastguard Worker 	while (cmdbuf_pos > 0 && cmdbuf[cmdbuf_pos - 1] == ' ')
91*03f9172cSAndroid Build Coastguard Worker 		cmdbuf_pos--;
92*03f9172cSAndroid Build Coastguard Worker 	while (cmdbuf_pos > 0 && cmdbuf[cmdbuf_pos - 1] != ' ')
93*03f9172cSAndroid Build Coastguard Worker 		cmdbuf_pos--;
94*03f9172cSAndroid Build Coastguard Worker 	edit_redraw();
95*03f9172cSAndroid Build Coastguard Worker }
96*03f9172cSAndroid Build Coastguard Worker 
97*03f9172cSAndroid Build Coastguard Worker 
move_word_right(void)98*03f9172cSAndroid Build Coastguard Worker static void move_word_right(void)
99*03f9172cSAndroid Build Coastguard Worker {
100*03f9172cSAndroid Build Coastguard Worker 	while (cmdbuf_pos < cmdbuf_len && cmdbuf[cmdbuf_pos] == ' ')
101*03f9172cSAndroid Build Coastguard Worker 		cmdbuf_pos++;
102*03f9172cSAndroid Build Coastguard Worker 	while (cmdbuf_pos < cmdbuf_len && cmdbuf[cmdbuf_pos] != ' ')
103*03f9172cSAndroid Build Coastguard Worker 		cmdbuf_pos++;
104*03f9172cSAndroid Build Coastguard Worker 	edit_redraw();
105*03f9172cSAndroid Build Coastguard Worker }
106*03f9172cSAndroid Build Coastguard Worker 
107*03f9172cSAndroid Build Coastguard Worker 
delete_left(void)108*03f9172cSAndroid Build Coastguard Worker static void delete_left(void)
109*03f9172cSAndroid Build Coastguard Worker {
110*03f9172cSAndroid Build Coastguard Worker 	if (cmdbuf_pos == 0)
111*03f9172cSAndroid Build Coastguard Worker 		return;
112*03f9172cSAndroid Build Coastguard Worker 
113*03f9172cSAndroid Build Coastguard Worker 	edit_clear_line();
114*03f9172cSAndroid Build Coastguard Worker 	os_memmove(cmdbuf + cmdbuf_pos - 1, cmdbuf + cmdbuf_pos,
115*03f9172cSAndroid Build Coastguard Worker 		   cmdbuf_len - cmdbuf_pos);
116*03f9172cSAndroid Build Coastguard Worker 	cmdbuf_pos--;
117*03f9172cSAndroid Build Coastguard Worker 	cmdbuf_len--;
118*03f9172cSAndroid Build Coastguard Worker 	edit_redraw();
119*03f9172cSAndroid Build Coastguard Worker }
120*03f9172cSAndroid Build Coastguard Worker 
121*03f9172cSAndroid Build Coastguard Worker 
delete_current(void)122*03f9172cSAndroid Build Coastguard Worker static void delete_current(void)
123*03f9172cSAndroid Build Coastguard Worker {
124*03f9172cSAndroid Build Coastguard Worker 	if (cmdbuf_pos == cmdbuf_len)
125*03f9172cSAndroid Build Coastguard Worker 		return;
126*03f9172cSAndroid Build Coastguard Worker 
127*03f9172cSAndroid Build Coastguard Worker 	edit_clear_line();
128*03f9172cSAndroid Build Coastguard Worker 	os_memmove(cmdbuf + cmdbuf_pos, cmdbuf + cmdbuf_pos + 1,
129*03f9172cSAndroid Build Coastguard Worker 		   cmdbuf_len - cmdbuf_pos);
130*03f9172cSAndroid Build Coastguard Worker 	cmdbuf_len--;
131*03f9172cSAndroid Build Coastguard Worker 	edit_redraw();
132*03f9172cSAndroid Build Coastguard Worker }
133*03f9172cSAndroid Build Coastguard Worker 
134*03f9172cSAndroid Build Coastguard Worker 
delete_word(void)135*03f9172cSAndroid Build Coastguard Worker static void delete_word(void)
136*03f9172cSAndroid Build Coastguard Worker {
137*03f9172cSAndroid Build Coastguard Worker 	int pos;
138*03f9172cSAndroid Build Coastguard Worker 
139*03f9172cSAndroid Build Coastguard Worker 	edit_clear_line();
140*03f9172cSAndroid Build Coastguard Worker 	pos = cmdbuf_pos;
141*03f9172cSAndroid Build Coastguard Worker 	while (pos > 0 && cmdbuf[pos - 1] == ' ')
142*03f9172cSAndroid Build Coastguard Worker 		pos--;
143*03f9172cSAndroid Build Coastguard Worker 	while (pos > 0 && cmdbuf[pos - 1] != ' ')
144*03f9172cSAndroid Build Coastguard Worker 		pos--;
145*03f9172cSAndroid Build Coastguard Worker 	os_memmove(cmdbuf + pos, cmdbuf + cmdbuf_pos, cmdbuf_len - cmdbuf_pos);
146*03f9172cSAndroid Build Coastguard Worker 	cmdbuf_len -= cmdbuf_pos - pos;
147*03f9172cSAndroid Build Coastguard Worker 	cmdbuf_pos = pos;
148*03f9172cSAndroid Build Coastguard Worker 	edit_redraw();
149*03f9172cSAndroid Build Coastguard Worker }
150*03f9172cSAndroid Build Coastguard Worker 
151*03f9172cSAndroid Build Coastguard Worker 
clear_left(void)152*03f9172cSAndroid Build Coastguard Worker static void clear_left(void)
153*03f9172cSAndroid Build Coastguard Worker {
154*03f9172cSAndroid Build Coastguard Worker 	if (cmdbuf_pos == 0)
155*03f9172cSAndroid Build Coastguard Worker 		return;
156*03f9172cSAndroid Build Coastguard Worker 
157*03f9172cSAndroid Build Coastguard Worker 	edit_clear_line();
158*03f9172cSAndroid Build Coastguard Worker 	os_memmove(cmdbuf, cmdbuf + cmdbuf_pos, cmdbuf_len - cmdbuf_pos);
159*03f9172cSAndroid Build Coastguard Worker 	cmdbuf_len -= cmdbuf_pos;
160*03f9172cSAndroid Build Coastguard Worker 	cmdbuf_pos = 0;
161*03f9172cSAndroid Build Coastguard Worker 	edit_redraw();
162*03f9172cSAndroid Build Coastguard Worker }
163*03f9172cSAndroid Build Coastguard Worker 
164*03f9172cSAndroid Build Coastguard Worker 
clear_right(void)165*03f9172cSAndroid Build Coastguard Worker static void clear_right(void)
166*03f9172cSAndroid Build Coastguard Worker {
167*03f9172cSAndroid Build Coastguard Worker 	if (cmdbuf_pos == cmdbuf_len)
168*03f9172cSAndroid Build Coastguard Worker 		return;
169*03f9172cSAndroid Build Coastguard Worker 
170*03f9172cSAndroid Build Coastguard Worker 	edit_clear_line();
171*03f9172cSAndroid Build Coastguard Worker 	cmdbuf_len = cmdbuf_pos;
172*03f9172cSAndroid Build Coastguard Worker 	edit_redraw();
173*03f9172cSAndroid Build Coastguard Worker }
174*03f9172cSAndroid Build Coastguard Worker 
175*03f9172cSAndroid Build Coastguard Worker 
history_add(const char * str)176*03f9172cSAndroid Build Coastguard Worker static void history_add(const char *str)
177*03f9172cSAndroid Build Coastguard Worker {
178*03f9172cSAndroid Build Coastguard Worker 	struct edit_history *h, *match = NULL, *last = NULL;
179*03f9172cSAndroid Build Coastguard Worker 	size_t len, count = 0;
180*03f9172cSAndroid Build Coastguard Worker 
181*03f9172cSAndroid Build Coastguard Worker 	if (str[0] == '\0')
182*03f9172cSAndroid Build Coastguard Worker 		return;
183*03f9172cSAndroid Build Coastguard Worker 
184*03f9172cSAndroid Build Coastguard Worker 	dl_list_for_each(h, &history_list, struct edit_history, list) {
185*03f9172cSAndroid Build Coastguard Worker 		if (os_strcmp(str, h->str) == 0) {
186*03f9172cSAndroid Build Coastguard Worker 			match = h;
187*03f9172cSAndroid Build Coastguard Worker 			break;
188*03f9172cSAndroid Build Coastguard Worker 		}
189*03f9172cSAndroid Build Coastguard Worker 		last = h;
190*03f9172cSAndroid Build Coastguard Worker 		count++;
191*03f9172cSAndroid Build Coastguard Worker 	}
192*03f9172cSAndroid Build Coastguard Worker 
193*03f9172cSAndroid Build Coastguard Worker 	if (match) {
194*03f9172cSAndroid Build Coastguard Worker 		dl_list_del(&h->list);
195*03f9172cSAndroid Build Coastguard Worker 		dl_list_add(&history_list, &h->list);
196*03f9172cSAndroid Build Coastguard Worker 		history_curr = h;
197*03f9172cSAndroid Build Coastguard Worker 		return;
198*03f9172cSAndroid Build Coastguard Worker 	}
199*03f9172cSAndroid Build Coastguard Worker 
200*03f9172cSAndroid Build Coastguard Worker 	if (count >= HISTORY_MAX && last) {
201*03f9172cSAndroid Build Coastguard Worker 		dl_list_del(&last->list);
202*03f9172cSAndroid Build Coastguard Worker 		os_free(last);
203*03f9172cSAndroid Build Coastguard Worker 	}
204*03f9172cSAndroid Build Coastguard Worker 
205*03f9172cSAndroid Build Coastguard Worker 	len = os_strlen(str);
206*03f9172cSAndroid Build Coastguard Worker 	h = os_zalloc(sizeof(*h) + len);
207*03f9172cSAndroid Build Coastguard Worker 	if (h == NULL)
208*03f9172cSAndroid Build Coastguard Worker 		return;
209*03f9172cSAndroid Build Coastguard Worker 	dl_list_add(&history_list, &h->list);
210*03f9172cSAndroid Build Coastguard Worker 	os_strlcpy(h->str, str, len + 1);
211*03f9172cSAndroid Build Coastguard Worker 	history_curr = h;
212*03f9172cSAndroid Build Coastguard Worker }
213*03f9172cSAndroid Build Coastguard Worker 
214*03f9172cSAndroid Build Coastguard Worker 
history_use(void)215*03f9172cSAndroid Build Coastguard Worker static void history_use(void)
216*03f9172cSAndroid Build Coastguard Worker {
217*03f9172cSAndroid Build Coastguard Worker 	edit_clear_line();
218*03f9172cSAndroid Build Coastguard Worker 	cmdbuf_len = cmdbuf_pos = os_strlen(history_curr->str);
219*03f9172cSAndroid Build Coastguard Worker 	os_memcpy(cmdbuf, history_curr->str, cmdbuf_len);
220*03f9172cSAndroid Build Coastguard Worker 	edit_redraw();
221*03f9172cSAndroid Build Coastguard Worker }
222*03f9172cSAndroid Build Coastguard Worker 
223*03f9172cSAndroid Build Coastguard Worker 
history_prev(void)224*03f9172cSAndroid Build Coastguard Worker static void history_prev(void)
225*03f9172cSAndroid Build Coastguard Worker {
226*03f9172cSAndroid Build Coastguard Worker 	if (history_curr == NULL)
227*03f9172cSAndroid Build Coastguard Worker 		return;
228*03f9172cSAndroid Build Coastguard Worker 
229*03f9172cSAndroid Build Coastguard Worker 	if (history_curr ==
230*03f9172cSAndroid Build Coastguard Worker 	    dl_list_first(&history_list, struct edit_history, list)) {
231*03f9172cSAndroid Build Coastguard Worker 		if (!currbuf_valid) {
232*03f9172cSAndroid Build Coastguard Worker 			cmdbuf[cmdbuf_len] = '\0';
233*03f9172cSAndroid Build Coastguard Worker 			os_memcpy(currbuf, cmdbuf, cmdbuf_len + 1);
234*03f9172cSAndroid Build Coastguard Worker 			currbuf_valid = 1;
235*03f9172cSAndroid Build Coastguard Worker 			history_use();
236*03f9172cSAndroid Build Coastguard Worker 			return;
237*03f9172cSAndroid Build Coastguard Worker 		}
238*03f9172cSAndroid Build Coastguard Worker 	}
239*03f9172cSAndroid Build Coastguard Worker 
240*03f9172cSAndroid Build Coastguard Worker 	if (history_curr ==
241*03f9172cSAndroid Build Coastguard Worker 	    dl_list_last(&history_list, struct edit_history, list))
242*03f9172cSAndroid Build Coastguard Worker 		return;
243*03f9172cSAndroid Build Coastguard Worker 
244*03f9172cSAndroid Build Coastguard Worker 	history_curr = dl_list_entry(history_curr->list.next,
245*03f9172cSAndroid Build Coastguard Worker 				     struct edit_history, list);
246*03f9172cSAndroid Build Coastguard Worker 	history_use();
247*03f9172cSAndroid Build Coastguard Worker }
248*03f9172cSAndroid Build Coastguard Worker 
249*03f9172cSAndroid Build Coastguard Worker 
history_next(void)250*03f9172cSAndroid Build Coastguard Worker static void history_next(void)
251*03f9172cSAndroid Build Coastguard Worker {
252*03f9172cSAndroid Build Coastguard Worker 	if (history_curr == NULL ||
253*03f9172cSAndroid Build Coastguard Worker 	    history_curr ==
254*03f9172cSAndroid Build Coastguard Worker 	    dl_list_first(&history_list, struct edit_history, list)) {
255*03f9172cSAndroid Build Coastguard Worker 		if (currbuf_valid) {
256*03f9172cSAndroid Build Coastguard Worker 			currbuf_valid = 0;
257*03f9172cSAndroid Build Coastguard Worker 			edit_clear_line();
258*03f9172cSAndroid Build Coastguard Worker 			cmdbuf_len = cmdbuf_pos = os_strlen(currbuf);
259*03f9172cSAndroid Build Coastguard Worker 			os_memcpy(cmdbuf, currbuf, cmdbuf_len);
260*03f9172cSAndroid Build Coastguard Worker 			edit_redraw();
261*03f9172cSAndroid Build Coastguard Worker 		}
262*03f9172cSAndroid Build Coastguard Worker 		return;
263*03f9172cSAndroid Build Coastguard Worker 	}
264*03f9172cSAndroid Build Coastguard Worker 
265*03f9172cSAndroid Build Coastguard Worker 	history_curr = dl_list_entry(history_curr->list.prev,
266*03f9172cSAndroid Build Coastguard Worker 				     struct edit_history, list);
267*03f9172cSAndroid Build Coastguard Worker 	history_use();
268*03f9172cSAndroid Build Coastguard Worker }
269*03f9172cSAndroid Build Coastguard Worker 
270*03f9172cSAndroid Build Coastguard Worker 
history_read(const char * fname)271*03f9172cSAndroid Build Coastguard Worker static void history_read(const char *fname)
272*03f9172cSAndroid Build Coastguard Worker {
273*03f9172cSAndroid Build Coastguard Worker 	FILE *f;
274*03f9172cSAndroid Build Coastguard Worker 	char buf[CMD_BUF_LEN], *pos;
275*03f9172cSAndroid Build Coastguard Worker 
276*03f9172cSAndroid Build Coastguard Worker 	f = fopen(fname, "r");
277*03f9172cSAndroid Build Coastguard Worker 	if (f == NULL)
278*03f9172cSAndroid Build Coastguard Worker 		return;
279*03f9172cSAndroid Build Coastguard Worker 
280*03f9172cSAndroid Build Coastguard Worker 	while (fgets(buf, CMD_BUF_LEN, f)) {
281*03f9172cSAndroid Build Coastguard Worker 		for (pos = buf; *pos; pos++) {
282*03f9172cSAndroid Build Coastguard Worker 			if (*pos == '\r' || *pos == '\n') {
283*03f9172cSAndroid Build Coastguard Worker 				*pos = '\0';
284*03f9172cSAndroid Build Coastguard Worker 				break;
285*03f9172cSAndroid Build Coastguard Worker 			}
286*03f9172cSAndroid Build Coastguard Worker 		}
287*03f9172cSAndroid Build Coastguard Worker 		history_add(buf);
288*03f9172cSAndroid Build Coastguard Worker 	}
289*03f9172cSAndroid Build Coastguard Worker 
290*03f9172cSAndroid Build Coastguard Worker 	fclose(f);
291*03f9172cSAndroid Build Coastguard Worker }
292*03f9172cSAndroid Build Coastguard Worker 
293*03f9172cSAndroid Build Coastguard Worker 
history_write(const char * fname,int (* filter_cb)(void * ctx,const char * cmd))294*03f9172cSAndroid Build Coastguard Worker static void history_write(const char *fname,
295*03f9172cSAndroid Build Coastguard Worker 			  int (*filter_cb)(void *ctx, const char *cmd))
296*03f9172cSAndroid Build Coastguard Worker {
297*03f9172cSAndroid Build Coastguard Worker 	FILE *f;
298*03f9172cSAndroid Build Coastguard Worker 	struct edit_history *h;
299*03f9172cSAndroid Build Coastguard Worker 
300*03f9172cSAndroid Build Coastguard Worker 	f = fopen(fname, "w");
301*03f9172cSAndroid Build Coastguard Worker 	if (f == NULL)
302*03f9172cSAndroid Build Coastguard Worker 		return;
303*03f9172cSAndroid Build Coastguard Worker 
304*03f9172cSAndroid Build Coastguard Worker 	dl_list_for_each_reverse(h, &history_list, struct edit_history, list) {
305*03f9172cSAndroid Build Coastguard Worker 		if (filter_cb && filter_cb(edit_cb_ctx, h->str))
306*03f9172cSAndroid Build Coastguard Worker 			continue;
307*03f9172cSAndroid Build Coastguard Worker 		fprintf(f, "%s\n", h->str);
308*03f9172cSAndroid Build Coastguard Worker 	}
309*03f9172cSAndroid Build Coastguard Worker 
310*03f9172cSAndroid Build Coastguard Worker 	fclose(f);
311*03f9172cSAndroid Build Coastguard Worker }
312*03f9172cSAndroid Build Coastguard Worker 
313*03f9172cSAndroid Build Coastguard Worker 
history_debug_dump(void)314*03f9172cSAndroid Build Coastguard Worker static void history_debug_dump(void)
315*03f9172cSAndroid Build Coastguard Worker {
316*03f9172cSAndroid Build Coastguard Worker 	struct edit_history *h;
317*03f9172cSAndroid Build Coastguard Worker 	edit_clear_line();
318*03f9172cSAndroid Build Coastguard Worker 	printf("\r");
319*03f9172cSAndroid Build Coastguard Worker 	dl_list_for_each_reverse(h, &history_list, struct edit_history, list)
320*03f9172cSAndroid Build Coastguard Worker 		printf("%s%s\n", h == history_curr ? "[C]" : "", h->str);
321*03f9172cSAndroid Build Coastguard Worker 	if (currbuf_valid)
322*03f9172cSAndroid Build Coastguard Worker 		printf("{%s}\n", currbuf);
323*03f9172cSAndroid Build Coastguard Worker 	edit_redraw();
324*03f9172cSAndroid Build Coastguard Worker }
325*03f9172cSAndroid Build Coastguard Worker 
326*03f9172cSAndroid Build Coastguard Worker 
insert_char(int c)327*03f9172cSAndroid Build Coastguard Worker static void insert_char(int c)
328*03f9172cSAndroid Build Coastguard Worker {
329*03f9172cSAndroid Build Coastguard Worker 	if (cmdbuf_len >= (int) sizeof(cmdbuf) - 1)
330*03f9172cSAndroid Build Coastguard Worker 		return;
331*03f9172cSAndroid Build Coastguard Worker 	if (cmdbuf_len == cmdbuf_pos) {
332*03f9172cSAndroid Build Coastguard Worker 		cmdbuf[cmdbuf_pos++] = c;
333*03f9172cSAndroid Build Coastguard Worker 		cmdbuf_len++;
334*03f9172cSAndroid Build Coastguard Worker 		putchar(c);
335*03f9172cSAndroid Build Coastguard Worker 		fflush(stdout);
336*03f9172cSAndroid Build Coastguard Worker 	} else {
337*03f9172cSAndroid Build Coastguard Worker 		os_memmove(cmdbuf + cmdbuf_pos + 1, cmdbuf + cmdbuf_pos,
338*03f9172cSAndroid Build Coastguard Worker 			   cmdbuf_len - cmdbuf_pos);
339*03f9172cSAndroid Build Coastguard Worker 		cmdbuf[cmdbuf_pos++] = c;
340*03f9172cSAndroid Build Coastguard Worker 		cmdbuf_len++;
341*03f9172cSAndroid Build Coastguard Worker 		edit_redraw();
342*03f9172cSAndroid Build Coastguard Worker 	}
343*03f9172cSAndroid Build Coastguard Worker }
344*03f9172cSAndroid Build Coastguard Worker 
345*03f9172cSAndroid Build Coastguard Worker 
process_cmd(void)346*03f9172cSAndroid Build Coastguard Worker static void process_cmd(void)
347*03f9172cSAndroid Build Coastguard Worker {
348*03f9172cSAndroid Build Coastguard Worker 	currbuf_valid = 0;
349*03f9172cSAndroid Build Coastguard Worker 	if (cmdbuf_len == 0) {
350*03f9172cSAndroid Build Coastguard Worker 		printf("\n%s> ", ps2 ? ps2 : "");
351*03f9172cSAndroid Build Coastguard Worker 		fflush(stdout);
352*03f9172cSAndroid Build Coastguard Worker 		return;
353*03f9172cSAndroid Build Coastguard Worker 	}
354*03f9172cSAndroid Build Coastguard Worker 	printf("\n");
355*03f9172cSAndroid Build Coastguard Worker 	cmdbuf[cmdbuf_len] = '\0';
356*03f9172cSAndroid Build Coastguard Worker 	history_add(cmdbuf);
357*03f9172cSAndroid Build Coastguard Worker 	cmdbuf_pos = 0;
358*03f9172cSAndroid Build Coastguard Worker 	cmdbuf_len = 0;
359*03f9172cSAndroid Build Coastguard Worker 	edit_cmd_cb(edit_cb_ctx, cmdbuf);
360*03f9172cSAndroid Build Coastguard Worker 	printf("%s> ", ps2 ? ps2 : "");
361*03f9172cSAndroid Build Coastguard Worker 	fflush(stdout);
362*03f9172cSAndroid Build Coastguard Worker }
363*03f9172cSAndroid Build Coastguard Worker 
364*03f9172cSAndroid Build Coastguard Worker 
free_completions(char ** c)365*03f9172cSAndroid Build Coastguard Worker static void free_completions(char **c)
366*03f9172cSAndroid Build Coastguard Worker {
367*03f9172cSAndroid Build Coastguard Worker 	int i;
368*03f9172cSAndroid Build Coastguard Worker 	if (c == NULL)
369*03f9172cSAndroid Build Coastguard Worker 		return;
370*03f9172cSAndroid Build Coastguard Worker 	for (i = 0; c[i]; i++)
371*03f9172cSAndroid Build Coastguard Worker 		os_free(c[i]);
372*03f9172cSAndroid Build Coastguard Worker 	os_free(c);
373*03f9172cSAndroid Build Coastguard Worker }
374*03f9172cSAndroid Build Coastguard Worker 
375*03f9172cSAndroid Build Coastguard Worker 
filter_strings(char ** c,char * str,size_t len)376*03f9172cSAndroid Build Coastguard Worker static int filter_strings(char **c, char *str, size_t len)
377*03f9172cSAndroid Build Coastguard Worker {
378*03f9172cSAndroid Build Coastguard Worker 	int i, j;
379*03f9172cSAndroid Build Coastguard Worker 
380*03f9172cSAndroid Build Coastguard Worker 	for (i = 0, j = 0; c[j]; j++) {
381*03f9172cSAndroid Build Coastguard Worker 		if (os_strncasecmp(c[j], str, len) == 0) {
382*03f9172cSAndroid Build Coastguard Worker 			if (i != j) {
383*03f9172cSAndroid Build Coastguard Worker 				c[i] = c[j];
384*03f9172cSAndroid Build Coastguard Worker 				c[j] = NULL;
385*03f9172cSAndroid Build Coastguard Worker 			}
386*03f9172cSAndroid Build Coastguard Worker 			i++;
387*03f9172cSAndroid Build Coastguard Worker 		} else {
388*03f9172cSAndroid Build Coastguard Worker 			os_free(c[j]);
389*03f9172cSAndroid Build Coastguard Worker 			c[j] = NULL;
390*03f9172cSAndroid Build Coastguard Worker 		}
391*03f9172cSAndroid Build Coastguard Worker 	}
392*03f9172cSAndroid Build Coastguard Worker 	c[i] = NULL;
393*03f9172cSAndroid Build Coastguard Worker 	return i;
394*03f9172cSAndroid Build Coastguard Worker }
395*03f9172cSAndroid Build Coastguard Worker 
396*03f9172cSAndroid Build Coastguard Worker 
common_len(const char * a,const char * b)397*03f9172cSAndroid Build Coastguard Worker static int common_len(const char *a, const char *b)
398*03f9172cSAndroid Build Coastguard Worker {
399*03f9172cSAndroid Build Coastguard Worker 	int len = 0;
400*03f9172cSAndroid Build Coastguard Worker 	while (a[len] && a[len] == b[len])
401*03f9172cSAndroid Build Coastguard Worker 		len++;
402*03f9172cSAndroid Build Coastguard Worker 	return len;
403*03f9172cSAndroid Build Coastguard Worker }
404*03f9172cSAndroid Build Coastguard Worker 
405*03f9172cSAndroid Build Coastguard Worker 
max_common_length(char ** c)406*03f9172cSAndroid Build Coastguard Worker static int max_common_length(char **c)
407*03f9172cSAndroid Build Coastguard Worker {
408*03f9172cSAndroid Build Coastguard Worker 	int len, i;
409*03f9172cSAndroid Build Coastguard Worker 
410*03f9172cSAndroid Build Coastguard Worker 	len = os_strlen(c[0]);
411*03f9172cSAndroid Build Coastguard Worker 	for (i = 1; c[i]; i++) {
412*03f9172cSAndroid Build Coastguard Worker 		int same = common_len(c[0], c[i]);
413*03f9172cSAndroid Build Coastguard Worker 		if (same < len)
414*03f9172cSAndroid Build Coastguard Worker 			len = same;
415*03f9172cSAndroid Build Coastguard Worker 	}
416*03f9172cSAndroid Build Coastguard Worker 
417*03f9172cSAndroid Build Coastguard Worker 	return len;
418*03f9172cSAndroid Build Coastguard Worker }
419*03f9172cSAndroid Build Coastguard Worker 
420*03f9172cSAndroid Build Coastguard Worker 
cmp_str(const void * a,const void * b)421*03f9172cSAndroid Build Coastguard Worker static int cmp_str(const void *a, const void *b)
422*03f9172cSAndroid Build Coastguard Worker {
423*03f9172cSAndroid Build Coastguard Worker 	return os_strcmp(* (const char **) a, * (const char **) b);
424*03f9172cSAndroid Build Coastguard Worker }
425*03f9172cSAndroid Build Coastguard Worker 
complete(int list)426*03f9172cSAndroid Build Coastguard Worker static void complete(int list)
427*03f9172cSAndroid Build Coastguard Worker {
428*03f9172cSAndroid Build Coastguard Worker 	char **c;
429*03f9172cSAndroid Build Coastguard Worker 	int i, len, count;
430*03f9172cSAndroid Build Coastguard Worker 	int start, end;
431*03f9172cSAndroid Build Coastguard Worker 	int room, plen, add_space;
432*03f9172cSAndroid Build Coastguard Worker 
433*03f9172cSAndroid Build Coastguard Worker 	if (edit_completion_cb == NULL)
434*03f9172cSAndroid Build Coastguard Worker 		return;
435*03f9172cSAndroid Build Coastguard Worker 
436*03f9172cSAndroid Build Coastguard Worker 	cmdbuf[cmdbuf_len] = '\0';
437*03f9172cSAndroid Build Coastguard Worker 	c = edit_completion_cb(edit_cb_ctx, cmdbuf, cmdbuf_pos);
438*03f9172cSAndroid Build Coastguard Worker 	if (c == NULL)
439*03f9172cSAndroid Build Coastguard Worker 		return;
440*03f9172cSAndroid Build Coastguard Worker 
441*03f9172cSAndroid Build Coastguard Worker 	end = cmdbuf_pos;
442*03f9172cSAndroid Build Coastguard Worker 	start = end;
443*03f9172cSAndroid Build Coastguard Worker 	while (start > 0 && cmdbuf[start - 1] != ' ')
444*03f9172cSAndroid Build Coastguard Worker 		start--;
445*03f9172cSAndroid Build Coastguard Worker 	plen = end - start;
446*03f9172cSAndroid Build Coastguard Worker 
447*03f9172cSAndroid Build Coastguard Worker 	count = filter_strings(c, &cmdbuf[start], plen);
448*03f9172cSAndroid Build Coastguard Worker 	if (count == 0) {
449*03f9172cSAndroid Build Coastguard Worker 		free_completions(c);
450*03f9172cSAndroid Build Coastguard Worker 		return;
451*03f9172cSAndroid Build Coastguard Worker 	}
452*03f9172cSAndroid Build Coastguard Worker 
453*03f9172cSAndroid Build Coastguard Worker 	len = max_common_length(c);
454*03f9172cSAndroid Build Coastguard Worker 	if (len <= plen && count > 1) {
455*03f9172cSAndroid Build Coastguard Worker 		if (list) {
456*03f9172cSAndroid Build Coastguard Worker 			qsort(c, count, sizeof(char *), cmp_str);
457*03f9172cSAndroid Build Coastguard Worker 			edit_clear_line();
458*03f9172cSAndroid Build Coastguard Worker 			printf("\r");
459*03f9172cSAndroid Build Coastguard Worker 			for (i = 0; c[i]; i++)
460*03f9172cSAndroid Build Coastguard Worker 				printf("%s%s", i > 0 ? " " : "", c[i]);
461*03f9172cSAndroid Build Coastguard Worker 			printf("\n");
462*03f9172cSAndroid Build Coastguard Worker 			edit_redraw();
463*03f9172cSAndroid Build Coastguard Worker 		}
464*03f9172cSAndroid Build Coastguard Worker 		free_completions(c);
465*03f9172cSAndroid Build Coastguard Worker 		return;
466*03f9172cSAndroid Build Coastguard Worker 	}
467*03f9172cSAndroid Build Coastguard Worker 	len -= plen;
468*03f9172cSAndroid Build Coastguard Worker 
469*03f9172cSAndroid Build Coastguard Worker 	room = sizeof(cmdbuf) - 1 - cmdbuf_len;
470*03f9172cSAndroid Build Coastguard Worker 	if (room < len)
471*03f9172cSAndroid Build Coastguard Worker 		len = room;
472*03f9172cSAndroid Build Coastguard Worker 	add_space = count == 1 && len < room;
473*03f9172cSAndroid Build Coastguard Worker 
474*03f9172cSAndroid Build Coastguard Worker 	os_memmove(cmdbuf + cmdbuf_pos + len + add_space, cmdbuf + cmdbuf_pos,
475*03f9172cSAndroid Build Coastguard Worker 		   cmdbuf_len - cmdbuf_pos);
476*03f9172cSAndroid Build Coastguard Worker 	os_memcpy(&cmdbuf[cmdbuf_pos - plen], c[0], plen + len);
477*03f9172cSAndroid Build Coastguard Worker 	if (add_space)
478*03f9172cSAndroid Build Coastguard Worker 		cmdbuf[cmdbuf_pos + len] = ' ';
479*03f9172cSAndroid Build Coastguard Worker 
480*03f9172cSAndroid Build Coastguard Worker 	cmdbuf_pos += len + add_space;
481*03f9172cSAndroid Build Coastguard Worker 	cmdbuf_len += len + add_space;
482*03f9172cSAndroid Build Coastguard Worker 
483*03f9172cSAndroid Build Coastguard Worker 	edit_redraw();
484*03f9172cSAndroid Build Coastguard Worker 
485*03f9172cSAndroid Build Coastguard Worker 	free_completions(c);
486*03f9172cSAndroid Build Coastguard Worker }
487*03f9172cSAndroid Build Coastguard Worker 
488*03f9172cSAndroid Build Coastguard Worker 
489*03f9172cSAndroid Build Coastguard Worker enum edit_key_code {
490*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_NONE = 256,
491*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_TAB,
492*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_UP,
493*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_DOWN,
494*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_RIGHT,
495*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_LEFT,
496*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_ENTER,
497*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_BACKSPACE,
498*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_INSERT,
499*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_DELETE,
500*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_HOME,
501*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_END,
502*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_PAGE_UP,
503*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_PAGE_DOWN,
504*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_F1,
505*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_F2,
506*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_F3,
507*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_F4,
508*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_F5,
509*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_F6,
510*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_F7,
511*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_F8,
512*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_F9,
513*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_F10,
514*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_F11,
515*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_F12,
516*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_CTRL_UP,
517*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_CTRL_DOWN,
518*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_CTRL_RIGHT,
519*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_CTRL_LEFT,
520*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_CTRL_A,
521*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_CTRL_B,
522*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_CTRL_D,
523*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_CTRL_E,
524*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_CTRL_F,
525*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_CTRL_G,
526*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_CTRL_H,
527*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_CTRL_J,
528*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_CTRL_K,
529*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_CTRL_L,
530*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_CTRL_N,
531*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_CTRL_O,
532*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_CTRL_P,
533*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_CTRL_R,
534*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_CTRL_T,
535*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_CTRL_U,
536*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_CTRL_V,
537*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_CTRL_W,
538*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_ALT_UP,
539*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_ALT_DOWN,
540*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_ALT_RIGHT,
541*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_ALT_LEFT,
542*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_SHIFT_UP,
543*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_SHIFT_DOWN,
544*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_SHIFT_RIGHT,
545*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_SHIFT_LEFT,
546*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_ALT_SHIFT_UP,
547*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_ALT_SHIFT_DOWN,
548*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_ALT_SHIFT_RIGHT,
549*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_ALT_SHIFT_LEFT,
550*03f9172cSAndroid Build Coastguard Worker 	EDIT_KEY_EOF
551*03f9172cSAndroid Build Coastguard Worker };
552*03f9172cSAndroid Build Coastguard Worker 
show_esc_buf(const char * esc_buf,char c,int i)553*03f9172cSAndroid Build Coastguard Worker static void show_esc_buf(const char *esc_buf, char c, int i)
554*03f9172cSAndroid Build Coastguard Worker {
555*03f9172cSAndroid Build Coastguard Worker 	edit_clear_line();
556*03f9172cSAndroid Build Coastguard Worker 	printf("\rESC buffer '%s' c='%c' [%d]\n", esc_buf, c, i);
557*03f9172cSAndroid Build Coastguard Worker 	edit_redraw();
558*03f9172cSAndroid Build Coastguard Worker }
559*03f9172cSAndroid Build Coastguard Worker 
560*03f9172cSAndroid Build Coastguard Worker 
esc_seq_to_key1_no(char last)561*03f9172cSAndroid Build Coastguard Worker static enum edit_key_code esc_seq_to_key1_no(char last)
562*03f9172cSAndroid Build Coastguard Worker {
563*03f9172cSAndroid Build Coastguard Worker 	switch (last) {
564*03f9172cSAndroid Build Coastguard Worker 	case 'A':
565*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_UP;
566*03f9172cSAndroid Build Coastguard Worker 	case 'B':
567*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_DOWN;
568*03f9172cSAndroid Build Coastguard Worker 	case 'C':
569*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_RIGHT;
570*03f9172cSAndroid Build Coastguard Worker 	case 'D':
571*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_LEFT;
572*03f9172cSAndroid Build Coastguard Worker 	default:
573*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_NONE;
574*03f9172cSAndroid Build Coastguard Worker 	}
575*03f9172cSAndroid Build Coastguard Worker }
576*03f9172cSAndroid Build Coastguard Worker 
577*03f9172cSAndroid Build Coastguard Worker 
esc_seq_to_key1_shift(char last)578*03f9172cSAndroid Build Coastguard Worker static enum edit_key_code esc_seq_to_key1_shift(char last)
579*03f9172cSAndroid Build Coastguard Worker {
580*03f9172cSAndroid Build Coastguard Worker 	switch (last) {
581*03f9172cSAndroid Build Coastguard Worker 	case 'A':
582*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_SHIFT_UP;
583*03f9172cSAndroid Build Coastguard Worker 	case 'B':
584*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_SHIFT_DOWN;
585*03f9172cSAndroid Build Coastguard Worker 	case 'C':
586*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_SHIFT_RIGHT;
587*03f9172cSAndroid Build Coastguard Worker 	case 'D':
588*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_SHIFT_LEFT;
589*03f9172cSAndroid Build Coastguard Worker 	default:
590*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_NONE;
591*03f9172cSAndroid Build Coastguard Worker 	}
592*03f9172cSAndroid Build Coastguard Worker }
593*03f9172cSAndroid Build Coastguard Worker 
594*03f9172cSAndroid Build Coastguard Worker 
esc_seq_to_key1_alt(char last)595*03f9172cSAndroid Build Coastguard Worker static enum edit_key_code esc_seq_to_key1_alt(char last)
596*03f9172cSAndroid Build Coastguard Worker {
597*03f9172cSAndroid Build Coastguard Worker 	switch (last) {
598*03f9172cSAndroid Build Coastguard Worker 	case 'A':
599*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_ALT_UP;
600*03f9172cSAndroid Build Coastguard Worker 	case 'B':
601*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_ALT_DOWN;
602*03f9172cSAndroid Build Coastguard Worker 	case 'C':
603*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_ALT_RIGHT;
604*03f9172cSAndroid Build Coastguard Worker 	case 'D':
605*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_ALT_LEFT;
606*03f9172cSAndroid Build Coastguard Worker 	default:
607*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_NONE;
608*03f9172cSAndroid Build Coastguard Worker 	}
609*03f9172cSAndroid Build Coastguard Worker }
610*03f9172cSAndroid Build Coastguard Worker 
611*03f9172cSAndroid Build Coastguard Worker 
esc_seq_to_key1_alt_shift(char last)612*03f9172cSAndroid Build Coastguard Worker static enum edit_key_code esc_seq_to_key1_alt_shift(char last)
613*03f9172cSAndroid Build Coastguard Worker {
614*03f9172cSAndroid Build Coastguard Worker 	switch (last) {
615*03f9172cSAndroid Build Coastguard Worker 	case 'A':
616*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_ALT_SHIFT_UP;
617*03f9172cSAndroid Build Coastguard Worker 	case 'B':
618*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_ALT_SHIFT_DOWN;
619*03f9172cSAndroid Build Coastguard Worker 	case 'C':
620*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_ALT_SHIFT_RIGHT;
621*03f9172cSAndroid Build Coastguard Worker 	case 'D':
622*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_ALT_SHIFT_LEFT;
623*03f9172cSAndroid Build Coastguard Worker 	default:
624*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_NONE;
625*03f9172cSAndroid Build Coastguard Worker 	}
626*03f9172cSAndroid Build Coastguard Worker }
627*03f9172cSAndroid Build Coastguard Worker 
628*03f9172cSAndroid Build Coastguard Worker 
esc_seq_to_key1_ctrl(char last)629*03f9172cSAndroid Build Coastguard Worker static enum edit_key_code esc_seq_to_key1_ctrl(char last)
630*03f9172cSAndroid Build Coastguard Worker {
631*03f9172cSAndroid Build Coastguard Worker 	switch (last) {
632*03f9172cSAndroid Build Coastguard Worker 	case 'A':
633*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_CTRL_UP;
634*03f9172cSAndroid Build Coastguard Worker 	case 'B':
635*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_CTRL_DOWN;
636*03f9172cSAndroid Build Coastguard Worker 	case 'C':
637*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_CTRL_RIGHT;
638*03f9172cSAndroid Build Coastguard Worker 	case 'D':
639*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_CTRL_LEFT;
640*03f9172cSAndroid Build Coastguard Worker 	default:
641*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_NONE;
642*03f9172cSAndroid Build Coastguard Worker 	}
643*03f9172cSAndroid Build Coastguard Worker }
644*03f9172cSAndroid Build Coastguard Worker 
645*03f9172cSAndroid Build Coastguard Worker 
esc_seq_to_key1(int param1,int param2,char last)646*03f9172cSAndroid Build Coastguard Worker static enum edit_key_code esc_seq_to_key1(int param1, int param2, char last)
647*03f9172cSAndroid Build Coastguard Worker {
648*03f9172cSAndroid Build Coastguard Worker 	/* ESC-[<param1>;<param2><last> */
649*03f9172cSAndroid Build Coastguard Worker 
650*03f9172cSAndroid Build Coastguard Worker 	if (param1 < 0 && param2 < 0)
651*03f9172cSAndroid Build Coastguard Worker 		return esc_seq_to_key1_no(last);
652*03f9172cSAndroid Build Coastguard Worker 
653*03f9172cSAndroid Build Coastguard Worker 	if (param1 == 1 && param2 == 2)
654*03f9172cSAndroid Build Coastguard Worker 		return esc_seq_to_key1_shift(last);
655*03f9172cSAndroid Build Coastguard Worker 
656*03f9172cSAndroid Build Coastguard Worker 	if (param1 == 1 && param2 == 3)
657*03f9172cSAndroid Build Coastguard Worker 		return esc_seq_to_key1_alt(last);
658*03f9172cSAndroid Build Coastguard Worker 
659*03f9172cSAndroid Build Coastguard Worker 	if (param1 == 1 && param2 == 4)
660*03f9172cSAndroid Build Coastguard Worker 		return esc_seq_to_key1_alt_shift(last);
661*03f9172cSAndroid Build Coastguard Worker 
662*03f9172cSAndroid Build Coastguard Worker 	if (param1 == 1 && param2 == 5)
663*03f9172cSAndroid Build Coastguard Worker 		return esc_seq_to_key1_ctrl(last);
664*03f9172cSAndroid Build Coastguard Worker 
665*03f9172cSAndroid Build Coastguard Worker 	if (param2 < 0) {
666*03f9172cSAndroid Build Coastguard Worker 		if (last != '~')
667*03f9172cSAndroid Build Coastguard Worker 			return EDIT_KEY_NONE;
668*03f9172cSAndroid Build Coastguard Worker 		switch (param1) {
669*03f9172cSAndroid Build Coastguard Worker 		case 2:
670*03f9172cSAndroid Build Coastguard Worker 			return EDIT_KEY_INSERT;
671*03f9172cSAndroid Build Coastguard Worker 		case 3:
672*03f9172cSAndroid Build Coastguard Worker 			return EDIT_KEY_DELETE;
673*03f9172cSAndroid Build Coastguard Worker 		case 5:
674*03f9172cSAndroid Build Coastguard Worker 			return EDIT_KEY_PAGE_UP;
675*03f9172cSAndroid Build Coastguard Worker 		case 6:
676*03f9172cSAndroid Build Coastguard Worker 			return EDIT_KEY_PAGE_DOWN;
677*03f9172cSAndroid Build Coastguard Worker 		case 15:
678*03f9172cSAndroid Build Coastguard Worker 			return EDIT_KEY_F5;
679*03f9172cSAndroid Build Coastguard Worker 		case 17:
680*03f9172cSAndroid Build Coastguard Worker 			return EDIT_KEY_F6;
681*03f9172cSAndroid Build Coastguard Worker 		case 18:
682*03f9172cSAndroid Build Coastguard Worker 			return EDIT_KEY_F7;
683*03f9172cSAndroid Build Coastguard Worker 		case 19:
684*03f9172cSAndroid Build Coastguard Worker 			return EDIT_KEY_F8;
685*03f9172cSAndroid Build Coastguard Worker 		case 20:
686*03f9172cSAndroid Build Coastguard Worker 			return EDIT_KEY_F9;
687*03f9172cSAndroid Build Coastguard Worker 		case 21:
688*03f9172cSAndroid Build Coastguard Worker 			return EDIT_KEY_F10;
689*03f9172cSAndroid Build Coastguard Worker 		case 23:
690*03f9172cSAndroid Build Coastguard Worker 			return EDIT_KEY_F11;
691*03f9172cSAndroid Build Coastguard Worker 		case 24:
692*03f9172cSAndroid Build Coastguard Worker 			return EDIT_KEY_F12;
693*03f9172cSAndroid Build Coastguard Worker 		}
694*03f9172cSAndroid Build Coastguard Worker 	}
695*03f9172cSAndroid Build Coastguard Worker 
696*03f9172cSAndroid Build Coastguard Worker 	return EDIT_KEY_NONE;
697*03f9172cSAndroid Build Coastguard Worker }
698*03f9172cSAndroid Build Coastguard Worker 
699*03f9172cSAndroid Build Coastguard Worker 
esc_seq_to_key2(int param1,int param2,char last)700*03f9172cSAndroid Build Coastguard Worker static enum edit_key_code esc_seq_to_key2(int param1, int param2, char last)
701*03f9172cSAndroid Build Coastguard Worker {
702*03f9172cSAndroid Build Coastguard Worker 	/* ESC-O<param1>;<param2><last> */
703*03f9172cSAndroid Build Coastguard Worker 
704*03f9172cSAndroid Build Coastguard Worker 	if (param1 >= 0 || param2 >= 0)
705*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_NONE;
706*03f9172cSAndroid Build Coastguard Worker 
707*03f9172cSAndroid Build Coastguard Worker 	switch (last) {
708*03f9172cSAndroid Build Coastguard Worker 	case 'F':
709*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_END;
710*03f9172cSAndroid Build Coastguard Worker 	case 'H':
711*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_HOME;
712*03f9172cSAndroid Build Coastguard Worker 	case 'P':
713*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_F1;
714*03f9172cSAndroid Build Coastguard Worker 	case 'Q':
715*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_F2;
716*03f9172cSAndroid Build Coastguard Worker 	case 'R':
717*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_F3;
718*03f9172cSAndroid Build Coastguard Worker 	case 'S':
719*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_F4;
720*03f9172cSAndroid Build Coastguard Worker 	default:
721*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_NONE;
722*03f9172cSAndroid Build Coastguard Worker 	}
723*03f9172cSAndroid Build Coastguard Worker }
724*03f9172cSAndroid Build Coastguard Worker 
725*03f9172cSAndroid Build Coastguard Worker 
esc_seq_to_key(char * seq)726*03f9172cSAndroid Build Coastguard Worker static enum edit_key_code esc_seq_to_key(char *seq)
727*03f9172cSAndroid Build Coastguard Worker {
728*03f9172cSAndroid Build Coastguard Worker 	char last, *pos;
729*03f9172cSAndroid Build Coastguard Worker 	int param1 = -1, param2 = -1;
730*03f9172cSAndroid Build Coastguard Worker 	enum edit_key_code ret = EDIT_KEY_NONE;
731*03f9172cSAndroid Build Coastguard Worker 
732*03f9172cSAndroid Build Coastguard Worker 	last = '\0';
733*03f9172cSAndroid Build Coastguard Worker 	for (pos = seq; *pos; pos++)
734*03f9172cSAndroid Build Coastguard Worker 		last = *pos;
735*03f9172cSAndroid Build Coastguard Worker 
736*03f9172cSAndroid Build Coastguard Worker 	if (seq[1] >= '0' && seq[1] <= '9') {
737*03f9172cSAndroid Build Coastguard Worker 		param1 = atoi(&seq[1]);
738*03f9172cSAndroid Build Coastguard Worker 		pos = os_strchr(seq, ';');
739*03f9172cSAndroid Build Coastguard Worker 		if (pos)
740*03f9172cSAndroid Build Coastguard Worker 			param2 = atoi(pos + 1);
741*03f9172cSAndroid Build Coastguard Worker 	}
742*03f9172cSAndroid Build Coastguard Worker 
743*03f9172cSAndroid Build Coastguard Worker 	if (seq[0] == '[')
744*03f9172cSAndroid Build Coastguard Worker 		ret = esc_seq_to_key1(param1, param2, last);
745*03f9172cSAndroid Build Coastguard Worker 	else if (seq[0] == 'O')
746*03f9172cSAndroid Build Coastguard Worker 		ret = esc_seq_to_key2(param1, param2, last);
747*03f9172cSAndroid Build Coastguard Worker 
748*03f9172cSAndroid Build Coastguard Worker 	if (ret != EDIT_KEY_NONE)
749*03f9172cSAndroid Build Coastguard Worker 		return ret;
750*03f9172cSAndroid Build Coastguard Worker 
751*03f9172cSAndroid Build Coastguard Worker 	edit_clear_line();
752*03f9172cSAndroid Build Coastguard Worker 	printf("\rUnknown escape sequence '%s'\n", seq);
753*03f9172cSAndroid Build Coastguard Worker 	edit_redraw();
754*03f9172cSAndroid Build Coastguard Worker 	return EDIT_KEY_NONE;
755*03f9172cSAndroid Build Coastguard Worker }
756*03f9172cSAndroid Build Coastguard Worker 
757*03f9172cSAndroid Build Coastguard Worker 
edit_read_key(int sock)758*03f9172cSAndroid Build Coastguard Worker static enum edit_key_code edit_read_key(int sock)
759*03f9172cSAndroid Build Coastguard Worker {
760*03f9172cSAndroid Build Coastguard Worker 	int c;
761*03f9172cSAndroid Build Coastguard Worker 	unsigned char buf[1];
762*03f9172cSAndroid Build Coastguard Worker 	int res;
763*03f9172cSAndroid Build Coastguard Worker 	static int esc = -1;
764*03f9172cSAndroid Build Coastguard Worker 	static char esc_buf[7];
765*03f9172cSAndroid Build Coastguard Worker 
766*03f9172cSAndroid Build Coastguard Worker 	res = read(sock, buf, 1);
767*03f9172cSAndroid Build Coastguard Worker 	if (res < 0)
768*03f9172cSAndroid Build Coastguard Worker 		perror("read");
769*03f9172cSAndroid Build Coastguard Worker 	if (res <= 0)
770*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_EOF;
771*03f9172cSAndroid Build Coastguard Worker 
772*03f9172cSAndroid Build Coastguard Worker 	c = buf[0];
773*03f9172cSAndroid Build Coastguard Worker 
774*03f9172cSAndroid Build Coastguard Worker 	if (esc >= 0) {
775*03f9172cSAndroid Build Coastguard Worker 		if (c == 27 /* ESC */) {
776*03f9172cSAndroid Build Coastguard Worker 			esc = 0;
777*03f9172cSAndroid Build Coastguard Worker 			return EDIT_KEY_NONE;
778*03f9172cSAndroid Build Coastguard Worker 		}
779*03f9172cSAndroid Build Coastguard Worker 
780*03f9172cSAndroid Build Coastguard Worker 		if (esc == 6) {
781*03f9172cSAndroid Build Coastguard Worker 			show_esc_buf(esc_buf, c, 0);
782*03f9172cSAndroid Build Coastguard Worker 			esc = -1;
783*03f9172cSAndroid Build Coastguard Worker 		} else {
784*03f9172cSAndroid Build Coastguard Worker 			esc_buf[esc++] = c;
785*03f9172cSAndroid Build Coastguard Worker 			esc_buf[esc] = '\0';
786*03f9172cSAndroid Build Coastguard Worker 		}
787*03f9172cSAndroid Build Coastguard Worker 	}
788*03f9172cSAndroid Build Coastguard Worker 
789*03f9172cSAndroid Build Coastguard Worker 	if (esc == 1) {
790*03f9172cSAndroid Build Coastguard Worker 		if (esc_buf[0] != '[' && esc_buf[0] != 'O') {
791*03f9172cSAndroid Build Coastguard Worker 			show_esc_buf(esc_buf, c, 1);
792*03f9172cSAndroid Build Coastguard Worker 			esc = -1;
793*03f9172cSAndroid Build Coastguard Worker 			return EDIT_KEY_NONE;
794*03f9172cSAndroid Build Coastguard Worker 		} else
795*03f9172cSAndroid Build Coastguard Worker 			return EDIT_KEY_NONE; /* Escape sequence continues */
796*03f9172cSAndroid Build Coastguard Worker 	}
797*03f9172cSAndroid Build Coastguard Worker 
798*03f9172cSAndroid Build Coastguard Worker 	if (esc > 1) {
799*03f9172cSAndroid Build Coastguard Worker 		if ((c >= '0' && c <= '9') || c == ';')
800*03f9172cSAndroid Build Coastguard Worker 			return EDIT_KEY_NONE; /* Escape sequence continues */
801*03f9172cSAndroid Build Coastguard Worker 
802*03f9172cSAndroid Build Coastguard Worker 		if (c == '~' || (c >= 'A' && c <= 'Z')) {
803*03f9172cSAndroid Build Coastguard Worker 			esc = -1;
804*03f9172cSAndroid Build Coastguard Worker 			return esc_seq_to_key(esc_buf);
805*03f9172cSAndroid Build Coastguard Worker 		}
806*03f9172cSAndroid Build Coastguard Worker 
807*03f9172cSAndroid Build Coastguard Worker 		show_esc_buf(esc_buf, c, 2);
808*03f9172cSAndroid Build Coastguard Worker 		esc = -1;
809*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_NONE;
810*03f9172cSAndroid Build Coastguard Worker 	}
811*03f9172cSAndroid Build Coastguard Worker 
812*03f9172cSAndroid Build Coastguard Worker 	switch (c) {
813*03f9172cSAndroid Build Coastguard Worker 	case 1:
814*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_CTRL_A;
815*03f9172cSAndroid Build Coastguard Worker 	case 2:
816*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_CTRL_B;
817*03f9172cSAndroid Build Coastguard Worker 	case 4:
818*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_CTRL_D;
819*03f9172cSAndroid Build Coastguard Worker 	case 5:
820*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_CTRL_E;
821*03f9172cSAndroid Build Coastguard Worker 	case 6:
822*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_CTRL_F;
823*03f9172cSAndroid Build Coastguard Worker 	case 7:
824*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_CTRL_G;
825*03f9172cSAndroid Build Coastguard Worker 	case 8:
826*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_CTRL_H;
827*03f9172cSAndroid Build Coastguard Worker 	case 9:
828*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_TAB;
829*03f9172cSAndroid Build Coastguard Worker 	case 10:
830*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_CTRL_J;
831*03f9172cSAndroid Build Coastguard Worker 	case 13: /* CR */
832*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_ENTER;
833*03f9172cSAndroid Build Coastguard Worker 	case 11:
834*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_CTRL_K;
835*03f9172cSAndroid Build Coastguard Worker 	case 12:
836*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_CTRL_L;
837*03f9172cSAndroid Build Coastguard Worker 	case 14:
838*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_CTRL_N;
839*03f9172cSAndroid Build Coastguard Worker 	case 15:
840*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_CTRL_O;
841*03f9172cSAndroid Build Coastguard Worker 	case 16:
842*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_CTRL_P;
843*03f9172cSAndroid Build Coastguard Worker 	case 18:
844*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_CTRL_R;
845*03f9172cSAndroid Build Coastguard Worker 	case 20:
846*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_CTRL_T;
847*03f9172cSAndroid Build Coastguard Worker 	case 21:
848*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_CTRL_U;
849*03f9172cSAndroid Build Coastguard Worker 	case 22:
850*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_CTRL_V;
851*03f9172cSAndroid Build Coastguard Worker 	case 23:
852*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_CTRL_W;
853*03f9172cSAndroid Build Coastguard Worker 	case 27: /* ESC */
854*03f9172cSAndroid Build Coastguard Worker 		esc = 0;
855*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_NONE;
856*03f9172cSAndroid Build Coastguard Worker 	case 127:
857*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_BACKSPACE;
858*03f9172cSAndroid Build Coastguard Worker 	default:
859*03f9172cSAndroid Build Coastguard Worker 		return c;
860*03f9172cSAndroid Build Coastguard Worker 	}
861*03f9172cSAndroid Build Coastguard Worker }
862*03f9172cSAndroid Build Coastguard Worker 
863*03f9172cSAndroid Build Coastguard Worker 
864*03f9172cSAndroid Build Coastguard Worker static char search_buf[21];
865*03f9172cSAndroid Build Coastguard Worker static int search_skip;
866*03f9172cSAndroid Build Coastguard Worker 
search_find(void)867*03f9172cSAndroid Build Coastguard Worker static char * search_find(void)
868*03f9172cSAndroid Build Coastguard Worker {
869*03f9172cSAndroid Build Coastguard Worker 	struct edit_history *h;
870*03f9172cSAndroid Build Coastguard Worker 	size_t len = os_strlen(search_buf);
871*03f9172cSAndroid Build Coastguard Worker 	int skip = search_skip;
872*03f9172cSAndroid Build Coastguard Worker 
873*03f9172cSAndroid Build Coastguard Worker 	if (len == 0)
874*03f9172cSAndroid Build Coastguard Worker 		return NULL;
875*03f9172cSAndroid Build Coastguard Worker 
876*03f9172cSAndroid Build Coastguard Worker 	dl_list_for_each(h, &history_list, struct edit_history, list) {
877*03f9172cSAndroid Build Coastguard Worker 		if (os_strstr(h->str, search_buf)) {
878*03f9172cSAndroid Build Coastguard Worker 			if (skip == 0)
879*03f9172cSAndroid Build Coastguard Worker 				return h->str;
880*03f9172cSAndroid Build Coastguard Worker 			skip--;
881*03f9172cSAndroid Build Coastguard Worker 		}
882*03f9172cSAndroid Build Coastguard Worker 	}
883*03f9172cSAndroid Build Coastguard Worker 
884*03f9172cSAndroid Build Coastguard Worker 	search_skip = 0;
885*03f9172cSAndroid Build Coastguard Worker 	return NULL;
886*03f9172cSAndroid Build Coastguard Worker }
887*03f9172cSAndroid Build Coastguard Worker 
888*03f9172cSAndroid Build Coastguard Worker 
search_redraw(void)889*03f9172cSAndroid Build Coastguard Worker static void search_redraw(void)
890*03f9172cSAndroid Build Coastguard Worker {
891*03f9172cSAndroid Build Coastguard Worker 	char *match = search_find();
892*03f9172cSAndroid Build Coastguard Worker 	printf("\rsearch '%s': %s" CLEAR_END_LINE,
893*03f9172cSAndroid Build Coastguard Worker 	       search_buf, match ? match : "");
894*03f9172cSAndroid Build Coastguard Worker 	printf("\rsearch '%s", search_buf);
895*03f9172cSAndroid Build Coastguard Worker 	fflush(stdout);
896*03f9172cSAndroid Build Coastguard Worker }
897*03f9172cSAndroid Build Coastguard Worker 
898*03f9172cSAndroid Build Coastguard Worker 
search_start(void)899*03f9172cSAndroid Build Coastguard Worker static void search_start(void)
900*03f9172cSAndroid Build Coastguard Worker {
901*03f9172cSAndroid Build Coastguard Worker 	edit_clear_line();
902*03f9172cSAndroid Build Coastguard Worker 	search_buf[0] = '\0';
903*03f9172cSAndroid Build Coastguard Worker 	search_skip = 0;
904*03f9172cSAndroid Build Coastguard Worker 	search_redraw();
905*03f9172cSAndroid Build Coastguard Worker }
906*03f9172cSAndroid Build Coastguard Worker 
907*03f9172cSAndroid Build Coastguard Worker 
search_clear(void)908*03f9172cSAndroid Build Coastguard Worker static void search_clear(void)
909*03f9172cSAndroid Build Coastguard Worker {
910*03f9172cSAndroid Build Coastguard Worker 	search_redraw();
911*03f9172cSAndroid Build Coastguard Worker 	printf("\r" CLEAR_END_LINE);
912*03f9172cSAndroid Build Coastguard Worker }
913*03f9172cSAndroid Build Coastguard Worker 
914*03f9172cSAndroid Build Coastguard Worker 
search_stop(void)915*03f9172cSAndroid Build Coastguard Worker static void search_stop(void)
916*03f9172cSAndroid Build Coastguard Worker {
917*03f9172cSAndroid Build Coastguard Worker 	char *match = search_find();
918*03f9172cSAndroid Build Coastguard Worker 	search_buf[0] = '\0';
919*03f9172cSAndroid Build Coastguard Worker 	search_clear();
920*03f9172cSAndroid Build Coastguard Worker 	if (match) {
921*03f9172cSAndroid Build Coastguard Worker 		os_strlcpy(cmdbuf, match, CMD_BUF_LEN);
922*03f9172cSAndroid Build Coastguard Worker 		cmdbuf_len = os_strlen(cmdbuf);
923*03f9172cSAndroid Build Coastguard Worker 		cmdbuf_pos = cmdbuf_len;
924*03f9172cSAndroid Build Coastguard Worker 	}
925*03f9172cSAndroid Build Coastguard Worker 	edit_redraw();
926*03f9172cSAndroid Build Coastguard Worker }
927*03f9172cSAndroid Build Coastguard Worker 
928*03f9172cSAndroid Build Coastguard Worker 
search_cancel(void)929*03f9172cSAndroid Build Coastguard Worker static void search_cancel(void)
930*03f9172cSAndroid Build Coastguard Worker {
931*03f9172cSAndroid Build Coastguard Worker 	search_buf[0] = '\0';
932*03f9172cSAndroid Build Coastguard Worker 	search_clear();
933*03f9172cSAndroid Build Coastguard Worker 	edit_redraw();
934*03f9172cSAndroid Build Coastguard Worker }
935*03f9172cSAndroid Build Coastguard Worker 
936*03f9172cSAndroid Build Coastguard Worker 
search_backspace(void)937*03f9172cSAndroid Build Coastguard Worker static void search_backspace(void)
938*03f9172cSAndroid Build Coastguard Worker {
939*03f9172cSAndroid Build Coastguard Worker 	size_t len;
940*03f9172cSAndroid Build Coastguard Worker 	len = os_strlen(search_buf);
941*03f9172cSAndroid Build Coastguard Worker 	if (len == 0)
942*03f9172cSAndroid Build Coastguard Worker 		return;
943*03f9172cSAndroid Build Coastguard Worker 	search_buf[len - 1] = '\0';
944*03f9172cSAndroid Build Coastguard Worker 	search_skip = 0;
945*03f9172cSAndroid Build Coastguard Worker 	search_redraw();
946*03f9172cSAndroid Build Coastguard Worker }
947*03f9172cSAndroid Build Coastguard Worker 
948*03f9172cSAndroid Build Coastguard Worker 
search_next(void)949*03f9172cSAndroid Build Coastguard Worker static void search_next(void)
950*03f9172cSAndroid Build Coastguard Worker {
951*03f9172cSAndroid Build Coastguard Worker 	search_skip++;
952*03f9172cSAndroid Build Coastguard Worker 	search_find();
953*03f9172cSAndroid Build Coastguard Worker 	search_redraw();
954*03f9172cSAndroid Build Coastguard Worker }
955*03f9172cSAndroid Build Coastguard Worker 
956*03f9172cSAndroid Build Coastguard Worker 
search_char(char c)957*03f9172cSAndroid Build Coastguard Worker static void search_char(char c)
958*03f9172cSAndroid Build Coastguard Worker {
959*03f9172cSAndroid Build Coastguard Worker 	size_t len;
960*03f9172cSAndroid Build Coastguard Worker 	len = os_strlen(search_buf);
961*03f9172cSAndroid Build Coastguard Worker 	if (len == sizeof(search_buf) - 1)
962*03f9172cSAndroid Build Coastguard Worker 		return;
963*03f9172cSAndroid Build Coastguard Worker 	search_buf[len] = c;
964*03f9172cSAndroid Build Coastguard Worker 	search_buf[len + 1] = '\0';
965*03f9172cSAndroid Build Coastguard Worker 	search_skip = 0;
966*03f9172cSAndroid Build Coastguard Worker 	search_redraw();
967*03f9172cSAndroid Build Coastguard Worker }
968*03f9172cSAndroid Build Coastguard Worker 
969*03f9172cSAndroid Build Coastguard Worker 
search_key(enum edit_key_code c)970*03f9172cSAndroid Build Coastguard Worker static enum edit_key_code search_key(enum edit_key_code c)
971*03f9172cSAndroid Build Coastguard Worker {
972*03f9172cSAndroid Build Coastguard Worker 	switch (c) {
973*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_ENTER:
974*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_CTRL_J:
975*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_LEFT:
976*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_RIGHT:
977*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_HOME:
978*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_END:
979*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_CTRL_A:
980*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_CTRL_E:
981*03f9172cSAndroid Build Coastguard Worker 		search_stop();
982*03f9172cSAndroid Build Coastguard Worker 		return c;
983*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_DOWN:
984*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_UP:
985*03f9172cSAndroid Build Coastguard Worker 		search_cancel();
986*03f9172cSAndroid Build Coastguard Worker 		return EDIT_KEY_EOF;
987*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_CTRL_H:
988*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_BACKSPACE:
989*03f9172cSAndroid Build Coastguard Worker 		search_backspace();
990*03f9172cSAndroid Build Coastguard Worker 		break;
991*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_CTRL_R:
992*03f9172cSAndroid Build Coastguard Worker 		search_next();
993*03f9172cSAndroid Build Coastguard Worker 		break;
994*03f9172cSAndroid Build Coastguard Worker 	default:
995*03f9172cSAndroid Build Coastguard Worker 		if (c >= 32 && c <= 255)
996*03f9172cSAndroid Build Coastguard Worker 			search_char(c);
997*03f9172cSAndroid Build Coastguard Worker 		break;
998*03f9172cSAndroid Build Coastguard Worker 	}
999*03f9172cSAndroid Build Coastguard Worker 
1000*03f9172cSAndroid Build Coastguard Worker 	return EDIT_KEY_NONE;
1001*03f9172cSAndroid Build Coastguard Worker }
1002*03f9172cSAndroid Build Coastguard Worker 
1003*03f9172cSAndroid Build Coastguard Worker 
edit_read_char(int sock,void * eloop_ctx,void * sock_ctx)1004*03f9172cSAndroid Build Coastguard Worker static void edit_read_char(int sock, void *eloop_ctx, void *sock_ctx)
1005*03f9172cSAndroid Build Coastguard Worker {
1006*03f9172cSAndroid Build Coastguard Worker 	static int last_tab = 0;
1007*03f9172cSAndroid Build Coastguard Worker 	static int search = 0;
1008*03f9172cSAndroid Build Coastguard Worker 	enum edit_key_code c;
1009*03f9172cSAndroid Build Coastguard Worker 
1010*03f9172cSAndroid Build Coastguard Worker 	c = edit_read_key(sock);
1011*03f9172cSAndroid Build Coastguard Worker 
1012*03f9172cSAndroid Build Coastguard Worker 	if (search) {
1013*03f9172cSAndroid Build Coastguard Worker 		c = search_key(c);
1014*03f9172cSAndroid Build Coastguard Worker 		if (c == EDIT_KEY_NONE)
1015*03f9172cSAndroid Build Coastguard Worker 			return;
1016*03f9172cSAndroid Build Coastguard Worker 		search = 0;
1017*03f9172cSAndroid Build Coastguard Worker 		if (c == EDIT_KEY_EOF)
1018*03f9172cSAndroid Build Coastguard Worker 			return;
1019*03f9172cSAndroid Build Coastguard Worker 	}
1020*03f9172cSAndroid Build Coastguard Worker 
1021*03f9172cSAndroid Build Coastguard Worker 	if (c != EDIT_KEY_TAB && c != EDIT_KEY_NONE)
1022*03f9172cSAndroid Build Coastguard Worker 		last_tab = 0;
1023*03f9172cSAndroid Build Coastguard Worker 
1024*03f9172cSAndroid Build Coastguard Worker 	switch (c) {
1025*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_NONE:
1026*03f9172cSAndroid Build Coastguard Worker 		break;
1027*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_EOF:
1028*03f9172cSAndroid Build Coastguard Worker 		edit_eof_cb(edit_cb_ctx);
1029*03f9172cSAndroid Build Coastguard Worker 		break;
1030*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_TAB:
1031*03f9172cSAndroid Build Coastguard Worker 		complete(last_tab);
1032*03f9172cSAndroid Build Coastguard Worker 		last_tab = 1;
1033*03f9172cSAndroid Build Coastguard Worker 		break;
1034*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_UP:
1035*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_CTRL_P:
1036*03f9172cSAndroid Build Coastguard Worker 		history_prev();
1037*03f9172cSAndroid Build Coastguard Worker 		break;
1038*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_DOWN:
1039*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_CTRL_N:
1040*03f9172cSAndroid Build Coastguard Worker 		history_next();
1041*03f9172cSAndroid Build Coastguard Worker 		break;
1042*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_RIGHT:
1043*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_CTRL_F:
1044*03f9172cSAndroid Build Coastguard Worker 		move_right();
1045*03f9172cSAndroid Build Coastguard Worker 		break;
1046*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_LEFT:
1047*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_CTRL_B:
1048*03f9172cSAndroid Build Coastguard Worker 		move_left();
1049*03f9172cSAndroid Build Coastguard Worker 		break;
1050*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_CTRL_RIGHT:
1051*03f9172cSAndroid Build Coastguard Worker 		move_word_right();
1052*03f9172cSAndroid Build Coastguard Worker 		break;
1053*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_CTRL_LEFT:
1054*03f9172cSAndroid Build Coastguard Worker 		move_word_left();
1055*03f9172cSAndroid Build Coastguard Worker 		break;
1056*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_DELETE:
1057*03f9172cSAndroid Build Coastguard Worker 		delete_current();
1058*03f9172cSAndroid Build Coastguard Worker 		break;
1059*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_END:
1060*03f9172cSAndroid Build Coastguard Worker 		move_end();
1061*03f9172cSAndroid Build Coastguard Worker 		break;
1062*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_HOME:
1063*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_CTRL_A:
1064*03f9172cSAndroid Build Coastguard Worker 		move_start();
1065*03f9172cSAndroid Build Coastguard Worker 		break;
1066*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_F2:
1067*03f9172cSAndroid Build Coastguard Worker 		history_debug_dump();
1068*03f9172cSAndroid Build Coastguard Worker 		break;
1069*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_CTRL_D:
1070*03f9172cSAndroid Build Coastguard Worker 		if (cmdbuf_len > 0) {
1071*03f9172cSAndroid Build Coastguard Worker 			delete_current();
1072*03f9172cSAndroid Build Coastguard Worker 			return;
1073*03f9172cSAndroid Build Coastguard Worker 		}
1074*03f9172cSAndroid Build Coastguard Worker 		printf("\n");
1075*03f9172cSAndroid Build Coastguard Worker 		edit_eof_cb(edit_cb_ctx);
1076*03f9172cSAndroid Build Coastguard Worker 		break;
1077*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_CTRL_E:
1078*03f9172cSAndroid Build Coastguard Worker 		move_end();
1079*03f9172cSAndroid Build Coastguard Worker 		break;
1080*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_CTRL_H:
1081*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_BACKSPACE:
1082*03f9172cSAndroid Build Coastguard Worker 		delete_left();
1083*03f9172cSAndroid Build Coastguard Worker 		break;
1084*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_ENTER:
1085*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_CTRL_J:
1086*03f9172cSAndroid Build Coastguard Worker 		process_cmd();
1087*03f9172cSAndroid Build Coastguard Worker 		break;
1088*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_CTRL_K:
1089*03f9172cSAndroid Build Coastguard Worker 		clear_right();
1090*03f9172cSAndroid Build Coastguard Worker 		break;
1091*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_CTRL_L:
1092*03f9172cSAndroid Build Coastguard Worker 		edit_clear_line();
1093*03f9172cSAndroid Build Coastguard Worker 		edit_redraw();
1094*03f9172cSAndroid Build Coastguard Worker 		break;
1095*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_CTRL_R:
1096*03f9172cSAndroid Build Coastguard Worker 		search = 1;
1097*03f9172cSAndroid Build Coastguard Worker 		search_start();
1098*03f9172cSAndroid Build Coastguard Worker 		break;
1099*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_CTRL_U:
1100*03f9172cSAndroid Build Coastguard Worker 		clear_left();
1101*03f9172cSAndroid Build Coastguard Worker 		break;
1102*03f9172cSAndroid Build Coastguard Worker 	case EDIT_KEY_CTRL_W:
1103*03f9172cSAndroid Build Coastguard Worker 		delete_word();
1104*03f9172cSAndroid Build Coastguard Worker 		break;
1105*03f9172cSAndroid Build Coastguard Worker 	default:
1106*03f9172cSAndroid Build Coastguard Worker 		if (c >= 32 && c <= 255)
1107*03f9172cSAndroid Build Coastguard Worker 			insert_char(c);
1108*03f9172cSAndroid Build Coastguard Worker 		break;
1109*03f9172cSAndroid Build Coastguard Worker 	}
1110*03f9172cSAndroid Build Coastguard Worker }
1111*03f9172cSAndroid Build Coastguard Worker 
1112*03f9172cSAndroid Build Coastguard Worker 
edit_init(void (* cmd_cb)(void * ctx,char * cmd),void (* eof_cb)(void * ctx),char ** (* completion_cb)(void * ctx,const char * cmd,int pos),void * ctx,const char * history_file,const char * ps)1113*03f9172cSAndroid Build Coastguard Worker int edit_init(void (*cmd_cb)(void *ctx, char *cmd),
1114*03f9172cSAndroid Build Coastguard Worker 	      void (*eof_cb)(void *ctx),
1115*03f9172cSAndroid Build Coastguard Worker 	      char ** (*completion_cb)(void *ctx, const char *cmd, int pos),
1116*03f9172cSAndroid Build Coastguard Worker 	      void *ctx, const char *history_file, const char *ps)
1117*03f9172cSAndroid Build Coastguard Worker {
1118*03f9172cSAndroid Build Coastguard Worker 	currbuf[0] = '\0';
1119*03f9172cSAndroid Build Coastguard Worker 	dl_list_init(&history_list);
1120*03f9172cSAndroid Build Coastguard Worker 	history_curr = NULL;
1121*03f9172cSAndroid Build Coastguard Worker 	if (history_file)
1122*03f9172cSAndroid Build Coastguard Worker 		history_read(history_file);
1123*03f9172cSAndroid Build Coastguard Worker 
1124*03f9172cSAndroid Build Coastguard Worker 	edit_cb_ctx = ctx;
1125*03f9172cSAndroid Build Coastguard Worker 	edit_cmd_cb = cmd_cb;
1126*03f9172cSAndroid Build Coastguard Worker 	edit_eof_cb = eof_cb;
1127*03f9172cSAndroid Build Coastguard Worker 	edit_completion_cb = completion_cb;
1128*03f9172cSAndroid Build Coastguard Worker 
1129*03f9172cSAndroid Build Coastguard Worker 	tcgetattr(STDIN_FILENO, &prevt);
1130*03f9172cSAndroid Build Coastguard Worker 	newt = prevt;
1131*03f9172cSAndroid Build Coastguard Worker 	newt.c_lflag &= ~(ICANON | ECHO);
1132*03f9172cSAndroid Build Coastguard Worker 	tcsetattr(STDIN_FILENO, TCSANOW, &newt);
1133*03f9172cSAndroid Build Coastguard Worker 
1134*03f9172cSAndroid Build Coastguard Worker 	eloop_register_read_sock(STDIN_FILENO, edit_read_char, NULL, NULL);
1135*03f9172cSAndroid Build Coastguard Worker 
1136*03f9172cSAndroid Build Coastguard Worker 	ps2 = ps;
1137*03f9172cSAndroid Build Coastguard Worker 	printf("%s> ", ps2 ? ps2 : "");
1138*03f9172cSAndroid Build Coastguard Worker 	fflush(stdout);
1139*03f9172cSAndroid Build Coastguard Worker 
1140*03f9172cSAndroid Build Coastguard Worker 	return 0;
1141*03f9172cSAndroid Build Coastguard Worker }
1142*03f9172cSAndroid Build Coastguard Worker 
1143*03f9172cSAndroid Build Coastguard Worker 
edit_deinit(const char * history_file,int (* filter_cb)(void * ctx,const char * cmd))1144*03f9172cSAndroid Build Coastguard Worker void edit_deinit(const char *history_file,
1145*03f9172cSAndroid Build Coastguard Worker 		 int (*filter_cb)(void *ctx, const char *cmd))
1146*03f9172cSAndroid Build Coastguard Worker {
1147*03f9172cSAndroid Build Coastguard Worker 	struct edit_history *h;
1148*03f9172cSAndroid Build Coastguard Worker 	if (history_file)
1149*03f9172cSAndroid Build Coastguard Worker 		history_write(history_file, filter_cb);
1150*03f9172cSAndroid Build Coastguard Worker 	while ((h = dl_list_first(&history_list, struct edit_history, list))) {
1151*03f9172cSAndroid Build Coastguard Worker 		dl_list_del(&h->list);
1152*03f9172cSAndroid Build Coastguard Worker 		os_free(h);
1153*03f9172cSAndroid Build Coastguard Worker 	}
1154*03f9172cSAndroid Build Coastguard Worker 	edit_clear_line();
1155*03f9172cSAndroid Build Coastguard Worker 	putchar('\r');
1156*03f9172cSAndroid Build Coastguard Worker 	fflush(stdout);
1157*03f9172cSAndroid Build Coastguard Worker 	eloop_unregister_read_sock(STDIN_FILENO);
1158*03f9172cSAndroid Build Coastguard Worker 	tcsetattr(STDIN_FILENO, TCSANOW, &prevt);
1159*03f9172cSAndroid Build Coastguard Worker }
1160*03f9172cSAndroid Build Coastguard Worker 
1161*03f9172cSAndroid Build Coastguard Worker 
edit_redraw(void)1162*03f9172cSAndroid Build Coastguard Worker void edit_redraw(void)
1163*03f9172cSAndroid Build Coastguard Worker {
1164*03f9172cSAndroid Build Coastguard Worker 	char tmp;
1165*03f9172cSAndroid Build Coastguard Worker 	cmdbuf[cmdbuf_len] = '\0';
1166*03f9172cSAndroid Build Coastguard Worker 	printf("\r%s> %s", ps2 ? ps2 : "", cmdbuf);
1167*03f9172cSAndroid Build Coastguard Worker 	if (cmdbuf_pos != cmdbuf_len) {
1168*03f9172cSAndroid Build Coastguard Worker 		tmp = cmdbuf[cmdbuf_pos];
1169*03f9172cSAndroid Build Coastguard Worker 		cmdbuf[cmdbuf_pos] = '\0';
1170*03f9172cSAndroid Build Coastguard Worker 		printf("\r%s> %s", ps2 ? ps2 : "", cmdbuf);
1171*03f9172cSAndroid Build Coastguard Worker 		cmdbuf[cmdbuf_pos] = tmp;
1172*03f9172cSAndroid Build Coastguard Worker 	}
1173*03f9172cSAndroid Build Coastguard Worker 	fflush(stdout);
1174*03f9172cSAndroid Build Coastguard Worker }
1175