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