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 */
92 while (!list_is_last(&last_found
->list
, &cli_history_head
)) {
93 p
= strstr(last_found
->command
, buf
);
96 last_found
= list_entry(last_found
->list
.next
, typeof(*last_found
), list
);
99 if (!p
&& !last_good
) {
104 last_good
= last_found
;
105 *cursor
= p
- last_good
->command
;
108 printf("\033[?7l\033[?25l");
109 /* Didn't handle the line wrap case here */
110 printf("\033[1G\033[1;36m(reverse-i-search)\033[0m`%s': %s",
111 buf
, last_good
->command
? : "");
115 return last_good
? last_good
->command
: NULL
;
120 const char *edit_cmdline(const char *input
, int top
/*, int width */ ,
121 int (*pDraw_Menu
) (int, int, int),
122 void (*show_fkey
) (int), bool *timedout
)
124 char cmdline
[MAX_CMDLINE_LEN
] = { };
125 int key
, len
, prev_len
, cursor
;
131 struct cli_command
*comm_counter
= NULL
;
132 clock_t kbd_to
= kbdtimeout
;
133 clock_t tto
= totaltimeout
;
137 if (getscreensize(1, &height
, &width
))
146 * Before we start messing with the x,y coordinates print 'input'
147 * so that it follows whatever text has been written to the screen
150 printf("%s ", input
);
154 /* Clear and redraw whole screen */
155 /* Enable ASCII on G0 and DEC VT on G1; do it in this order
156 to avoid confusing the Linux console */
159 (*pDraw_Menu
) (-1, top
, 1);
161 printf("\033[2J\033[H");
162 // printf("\033[0m\033[2J\033[H");
168 prev_len
= max(len
, prev_len
);
170 /* Redraw the command line */
171 printf("\033[?7l\033[?25l");
172 printf("\033[1G%s ", input
);
177 while (at
< prev_len
) {
178 putchar(at
>= len
? ' ' : cmdline
[at
]);
189 dy
= y
- (cursor
+ strlen(input
) + 1) / width
;
190 x
= (cursor
+ strlen(input
) + 1) % width
;
193 printf("\033[%dA", dy
);
197 printf("\033[%dC", x
);
203 key
= mygetkey_timeout(&kbd_to
, &tto
);
224 memmove(cmdline
+ cursor
- 1, cmdline
+ cursor
,
235 memmove(cmdline
+ cursor
, cmdline
+ cursor
+ 1, len
- cursor
);
251 int prevcursor
= cursor
;
253 while (cursor
&& my_isspace(cmdline
[cursor
- 1]))
256 while (cursor
&& !my_isspace(cmdline
[cursor
- 1]))
260 memmove(cmdline
+ cursor
, cmdline
+ prevcursor
,
261 len
- prevcursor
+ 1);
265 char *q
= cmdline
+ cursor
;
266 char *p
= cmdline
+ prevcursor
;
267 for (i
= 0; i
< len
- prevcursor
+ 1; i
++)
271 len
-= (prevcursor
- cursor
);
287 putchar(cmdline
[cursor
]);
300 cmdline
[len
= cursor
] = '\0';
333 if (show_fkey
!= NULL
) {
341 if (!list_empty(&cli_history_head
)) {
342 struct list_head
*next
;
345 next
= cli_history_head
.next
;
347 next
= comm_counter
->list
.next
;
350 list_entry(next
, typeof(*comm_counter
), list
);
352 if (&comm_counter
->list
!= &cli_history_head
)
353 strcpy(cmdline
, comm_counter
->command
);
355 cursor
= len
= strlen(cmdline
);
363 if (!list_empty(&cli_history_head
)) {
364 struct list_head
*prev
;
367 prev
= cli_history_head
.prev
;
369 prev
= comm_counter
->list
.prev
;
372 list_entry(prev
, typeof(*comm_counter
), list
);
374 if (&comm_counter
->list
!= &cli_history_head
)
375 strcpy(cmdline
, comm_counter
->command
);
377 cursor
= len
= strlen(cmdline
);
385 * Handle this case in another function, since it's
388 const char *p
= cmd_reverse_search(&cursor
, &kbd_to
, &tto
);
391 len
= strlen(cmdline
);
404 /* Label completion enabled? */
410 while(*p
&& !my_isspace(*p
)) {
415 print_labels(cmdline
, len
);
421 printf("%s%s%s", syslinux_banner
,
422 (char *)MK_PTR(0, BIOSName
), copyright_str
);
424 printf("%s%s", syslinux_banner
, copyright_str
);
430 if (key
>= ' ' && key
<= 0xFF && len
< MAX_CMDLINE_LEN
- 1) {
432 cmdline
[len
++] = key
;
438 printf("\r\n\033[K");
444 memmove(cmdline
+ cursor
+ 1, cmdline
+ cursor
,
446 cmdline
[cursor
++] = key
;
457 /* Add the command to the history */
458 comm_counter
= malloc(sizeof(struct cli_command
));
459 comm_counter
->command
= malloc(sizeof(char) * (strlen(ret
) + 1));
460 strcpy(comm_counter
->command
, ret
);
461 list_add(&(comm_counter
->list
), &cli_history_head
);
463 return len
? ret
: NULL
;
466 static int __constructor
cli_init(void)
468 INIT_LIST_HEAD(&cli_history_head
);
473 static void __destructor
cli_exit(void)