6 #include <syslinux/adv.h>
7 #include <syslinux/config.h>
9 #include <netinet/in.h>
12 #include <linux/list.h>
14 #include <sys/module.h>
23 static struct list_head cli_history_head
;
25 void clear_screen(void)
28 fputs("\033e\033%@\033)0\033(B\1#0\033[?25l\033[2J", stdout
);
31 static int mygetkey_timeout(clock_t *kbd_to
, clock_t *tto
)
37 key
= get_key(stdin
, *kbd_to
? *kbd_to
: *tto
);
39 /* kbdtimeout only applies to the first character */
43 t1
= times(NULL
) - t0
;
46 if (*tto
<= (long long)t1
)
50 if (*tto
> totaltimeout
)
60 static const char * cmd_reverse_search(int *cursor
, clock_t *kbd_to
,
65 char buf
[MAX_CMDLINE_LEN
];
67 struct cli_command
*last_found
;
68 struct cli_command
*last_good
= NULL
;
70 last_found
= list_entry(cli_history_head
.next
, typeof(*last_found
), list
);
72 memset(buf
, 0, MAX_CMDLINE_LEN
);
74 printf("\033[1G\033[1;36m(reverse-i-search)`': \033[0m");
76 key
= mygetkey_timeout(kbd_to
, tto
);
78 if (key
== KEY_CTRL('C')) {
80 } else if (key
== KEY_CTRL('R')) {
82 continue; /* User typed nothing yet */
83 /* User typed 'CTRL-R' again, so try the next */
84 last_found
= list_entry(last_found
->list
.next
, typeof(*last_found
), list
);
85 } else if (key
>= ' ' && key
<= 'z') {
88 /* Treat other input chars as terminal */
93 p
= strstr(last_found
->command
, buf
);
97 if (list_is_last(&last_found
->list
, &cli_history_head
))
100 last_found
= list_entry(last_found
->list
.next
, typeof(*last_found
), list
);
103 if (!p
&& !last_good
) {
108 last_good
= last_found
;
109 *cursor
= p
- last_good
->command
;
112 printf("\033[?7l\033[?25l");
113 /* Didn't handle the line wrap case here */
114 printf("\033[1G\033[1;36m(reverse-i-search)\033[0m`%s': %s",
115 buf
, last_good
->command
? : "");
119 return last_good
? last_good
->command
: NULL
;
124 const char *edit_cmdline(const char *input
, int top
/*, int width */ ,
125 int (*pDraw_Menu
) (int, int, int),
126 void (*show_fkey
) (int), bool *timedout
)
128 char cmdline
[MAX_CMDLINE_LEN
] = { };
129 int key
, len
, prev_len
, cursor
;
135 struct cli_command
*comm_counter
= NULL
;
136 clock_t kbd_to
= kbdtimeout
;
137 clock_t tto
= totaltimeout
;
141 if (getscreensize(1, &height
, &width
))
150 * Before we start messing with the x,y coordinates print 'input'
151 * so that it follows whatever text has been written to the screen
154 printf("%s ", input
);
158 /* Clear and redraw whole screen */
159 /* Enable ASCII on G0 and DEC VT on G1; do it in this order
160 to avoid confusing the Linux console */
163 (*pDraw_Menu
) (-1, top
, 1);
165 printf("\033[2J\033[H");
166 // printf("\033[0m\033[2J\033[H");
172 prev_len
= max(len
, prev_len
);
174 /* Redraw the command line */
176 printf("\033[1G%s ", input
);
181 while (at
< prev_len
) {
182 putchar(at
>= len
? ' ' : cmdline
[at
]);
193 dy
= y
- (cursor
+ strlen(input
) + 1) / width
;
194 x
= (cursor
+ strlen(input
) + 1) % width
;
197 printf("\033[%dA", dy
);
201 printf("\033[%dC", x
);
207 key
= mygetkey_timeout(&kbd_to
, &tto
);
228 memmove(cmdline
+ cursor
- 1, cmdline
+ cursor
,
239 memmove(cmdline
+ cursor
, cmdline
+ cursor
+ 1, len
- cursor
);
255 int prevcursor
= cursor
;
257 while (cursor
&& my_isspace(cmdline
[cursor
- 1]))
260 while (cursor
&& !my_isspace(cmdline
[cursor
- 1]))
264 memmove(cmdline
+ cursor
, cmdline
+ prevcursor
,
265 len
- prevcursor
+ 1);
269 char *q
= cmdline
+ cursor
;
270 char *p
= cmdline
+ prevcursor
;
271 for (i
= 0; i
< len
- prevcursor
+ 1; i
++)
275 len
-= (prevcursor
- cursor
);
291 putchar(cmdline
[cursor
]);
304 cmdline
[len
= cursor
] = '\0';
337 if (show_fkey
!= NULL
) {
345 if (!list_empty(&cli_history_head
)) {
346 struct list_head
*next
;
349 next
= cli_history_head
.next
;
351 next
= comm_counter
->list
.next
;
354 list_entry(next
, typeof(*comm_counter
), list
);
356 if (&comm_counter
->list
!= &cli_history_head
)
357 strcpy(cmdline
, comm_counter
->command
);
359 cursor
= len
= strlen(cmdline
);
367 if (!list_empty(&cli_history_head
)) {
368 struct list_head
*prev
;
371 prev
= cli_history_head
.prev
;
373 prev
= comm_counter
->list
.prev
;
376 list_entry(prev
, typeof(*comm_counter
), list
);
378 if (&comm_counter
->list
!= &cli_history_head
)
379 strcpy(cmdline
, comm_counter
->command
);
381 cursor
= len
= strlen(cmdline
);
389 * Handle this case in another function, since it's
392 const char *p
= cmd_reverse_search(&cursor
, &kbd_to
, &tto
);
395 len
= strlen(cmdline
);
408 /* Label completion enabled? */
414 while(*p
&& !my_isspace(*p
)) {
419 print_labels(cmdline
, len
);
425 printf("%s%s%s", syslinux_banner
,
426 (char *)MK_PTR(0, BIOSName
), copyright_str
);
428 printf("%s%s", syslinux_banner
, copyright_str
);
434 if (key
>= ' ' && key
<= 0xFF && len
< MAX_CMDLINE_LEN
- 1) {
436 cmdline
[len
++] = key
;
442 printf("\r\n\033[K");
451 memmove(cmdline
+ cursor
+ 1, cmdline
+ cursor
,
453 cmdline
[cursor
++] = key
;
464 /* Add the command to the history if its length is larger than 0 */
467 comm_counter
= malloc(sizeof(struct cli_command
));
468 comm_counter
->command
= malloc(sizeof(char) * (len
+ 1));
469 strcpy(comm_counter
->command
, ret
);
470 list_add(&(comm_counter
->list
), &cli_history_head
);
473 return len
? ret
: NULL
;
476 static int __constructor
cli_init(void)
478 INIT_LIST_HEAD(&cli_history_head
);
483 static void __destructor
cli_exit(void)