25
#include "qemu/osdep.h"
26
#include "qemu/readline.h"
27
#include "qemu/ctype.h"
28
#include "qemu/cutils.h"
35
void readline_show_prompt(ReadLineState *rs)
37
rs->printf_func(rs->opaque, "%s", rs->prompt);
38
rs->flush_func(rs->opaque);
39
rs->last_cmd_buf_index = 0;
40
rs->last_cmd_buf_size = 0;
41
rs->esc_state = IS_NORM;
45
static void readline_update(ReadLineState *rs)
49
if (rs->cmd_buf_size != rs->last_cmd_buf_size ||
50
memcmp(rs->cmd_buf, rs->last_cmd_buf, rs->cmd_buf_size) != 0) {
51
for (i = 0; i < rs->last_cmd_buf_index; i++) {
52
rs->printf_func(rs->opaque, "\033[D");
54
rs->cmd_buf[rs->cmd_buf_size] = '\0';
55
if (rs->read_password) {
56
len = strlen(rs->cmd_buf);
57
for (i = 0; i < len; i++) {
58
rs->printf_func(rs->opaque, "*");
61
rs->printf_func(rs->opaque, "%s", rs->cmd_buf);
63
rs->printf_func(rs->opaque, "\033[K");
64
memcpy(rs->last_cmd_buf, rs->cmd_buf, rs->cmd_buf_size);
65
rs->last_cmd_buf_size = rs->cmd_buf_size;
66
rs->last_cmd_buf_index = rs->cmd_buf_size;
68
if (rs->cmd_buf_index != rs->last_cmd_buf_index) {
69
delta = rs->cmd_buf_index - rs->last_cmd_buf_index;
71
for (i = 0; i < delta; i++) {
72
rs->printf_func(rs->opaque, "\033[C");
76
for (i = 0; i < delta; i++) {
77
rs->printf_func(rs->opaque, "\033[D");
80
rs->last_cmd_buf_index = rs->cmd_buf_index;
82
rs->flush_func(rs->opaque);
85
static void readline_insert_char(ReadLineState *rs, int ch)
87
if (rs->cmd_buf_index < READLINE_CMD_BUF_SIZE) {
88
memmove(rs->cmd_buf + rs->cmd_buf_index + 1,
89
rs->cmd_buf + rs->cmd_buf_index,
90
rs->cmd_buf_size - rs->cmd_buf_index);
91
rs->cmd_buf[rs->cmd_buf_index] = ch;
97
static void readline_backward_char(ReadLineState *rs)
99
if (rs->cmd_buf_index > 0) {
104
static void readline_forward_char(ReadLineState *rs)
106
if (rs->cmd_buf_index < rs->cmd_buf_size) {
111
static void readline_delete_char(ReadLineState *rs)
113
if (rs->cmd_buf_index < rs->cmd_buf_size) {
114
memmove(rs->cmd_buf + rs->cmd_buf_index,
115
rs->cmd_buf + rs->cmd_buf_index + 1,
116
rs->cmd_buf_size - rs->cmd_buf_index - 1);
121
static void readline_backspace(ReadLineState *rs)
123
if (rs->cmd_buf_index > 0) {
124
readline_backward_char(rs);
125
readline_delete_char(rs);
129
static void readline_backword(ReadLineState *rs)
133
if (rs->cmd_buf_index == 0 || rs->cmd_buf_index > rs->cmd_buf_size) {
137
start = rs->cmd_buf_index - 1;
141
if (!qemu_isspace(rs->cmd_buf[start])) {
150
if (qemu_isspace(rs->cmd_buf[start])) {
159
if (start < rs->cmd_buf_index) {
160
memmove(rs->cmd_buf + start,
161
rs->cmd_buf + rs->cmd_buf_index,
162
rs->cmd_buf_size - rs->cmd_buf_index);
163
rs->cmd_buf_size -= rs->cmd_buf_index - start;
164
rs->cmd_buf_index = start;
168
static void readline_bol(ReadLineState *rs)
170
rs->cmd_buf_index = 0;
173
static void readline_eol(ReadLineState *rs)
175
rs->cmd_buf_index = rs->cmd_buf_size;
178
static void readline_up_char(ReadLineState *rs)
182
if (rs->hist_entry == 0) {
185
if (rs->hist_entry == -1) {
187
for (idx = 0; idx < READLINE_MAX_CMDS; idx++) {
188
if (rs->history[idx] == NULL) {
192
rs->hist_entry = idx;
195
if (rs->hist_entry >= 0) {
196
pstrcpy(rs->cmd_buf, sizeof(rs->cmd_buf),
197
rs->history[rs->hist_entry]);
198
rs->cmd_buf_index = rs->cmd_buf_size = strlen(rs->cmd_buf);
202
static void readline_down_char(ReadLineState *rs)
204
if (rs->hist_entry == -1) {
207
if (rs->hist_entry < READLINE_MAX_CMDS - 1 &&
208
rs->history[++rs->hist_entry] != NULL) {
209
pstrcpy(rs->cmd_buf, sizeof(rs->cmd_buf),
210
rs->history[rs->hist_entry]);
215
rs->cmd_buf_index = rs->cmd_buf_size = strlen(rs->cmd_buf);
218
static void readline_hist_add(ReadLineState *rs, const char *cmdline)
220
char *hist_entry, *new_entry;
223
if (cmdline[0] == '\0') {
227
if (rs->hist_entry != -1) {
229
hist_entry = rs->history[rs->hist_entry];
230
idx = rs->hist_entry;
231
if (strcmp(hist_entry, cmdline) == 0) {
236
for (idx = 0; idx < READLINE_MAX_CMDS; idx++) {
237
hist_entry = rs->history[idx];
238
if (hist_entry == NULL) {
241
if (strcmp(hist_entry, cmdline) == 0) {
243
if (idx == READLINE_MAX_CMDS - 1) {
246
new_entry = hist_entry;
248
memmove(&rs->history[idx], &rs->history[idx + 1],
249
(READLINE_MAX_CMDS - (idx + 1)) * sizeof(char *));
250
rs->history[READLINE_MAX_CMDS - 1] = NULL;
251
for (; idx < READLINE_MAX_CMDS; idx++) {
252
if (rs->history[idx] == NULL) {
259
if (idx == READLINE_MAX_CMDS) {
261
g_free(rs->history[0]);
262
memmove(rs->history, &rs->history[1],
263
(READLINE_MAX_CMDS - 1) * sizeof(char *));
264
rs->history[READLINE_MAX_CMDS - 1] = NULL;
265
idx = READLINE_MAX_CMDS - 1;
267
if (new_entry == NULL) {
268
new_entry = g_strdup(cmdline);
270
rs->history[idx] = new_entry;
274
static void readline_kill_line(ReadLineState *rs)
276
while (rs->cmd_buf_index > 0) {
277
readline_backward_char(rs);
278
readline_delete_char(rs);
284
void readline_add_completion(ReadLineState *rs, const char *str)
286
if (rs->nb_completions < READLINE_MAX_COMPLETIONS) {
288
for (i = 0; i < rs->nb_completions; i++) {
289
if (!strcmp(rs->completions[i], str)) {
293
rs->completions[rs->nb_completions++] = g_strdup(str);
297
void readline_add_completion_of(ReadLineState *rs,
298
const char *pfx, const char *str)
300
if (!strncmp(str, pfx, strlen(pfx))) {
301
readline_add_completion(rs, str);
305
void readline_set_completion_index(ReadLineState *rs, int index)
307
rs->completion_index = index;
310
static int completion_comp(const void *a, const void *b)
312
return strcmp(*(const char **) a, *(const char **) b);
315
static void readline_completion(ReadLineState *rs)
317
int len, i, j, max_width, nb_cols, max_prefix;
320
rs->nb_completions = 0;
322
cmdline = g_strndup(rs->cmd_buf, rs->cmd_buf_index);
323
rs->completion_finder(rs->opaque, cmdline);
327
if (rs->nb_completions <= 0) {
330
if (rs->nb_completions == 1) {
331
len = strlen(rs->completions[0]);
332
for (i = rs->completion_index; i < len; i++) {
333
readline_insert_char(rs, rs->completions[0][i]);
336
if (len > 0 && rs->completions[0][len - 1] != '/') {
337
readline_insert_char(rs, ' ');
340
qsort(rs->completions, rs->nb_completions, sizeof(char *),
342
rs->printf_func(rs->opaque, "\n");
345
for (i = 0; i < rs->nb_completions; i++) {
346
len = strlen(rs->completions[i]);
350
if (len < max_prefix) {
353
for (j = 0; j < max_prefix; j++) {
354
if (rs->completions[i][j] != rs->completions[0][j]) {
359
if (len > max_width) {
364
for (i = rs->completion_index; i < max_prefix; i++) {
365
readline_insert_char(rs, rs->completions[0][i]);
368
if (max_width < 10) {
370
} else if (max_width > 80) {
373
nb_cols = 80 / max_width;
375
for (i = 0; i < rs->nb_completions; i++) {
376
rs->printf_func(rs->opaque, "%-*s", max_width, rs->completions[i]);
377
if (++j == nb_cols || i == (rs->nb_completions - 1)) {
378
rs->printf_func(rs->opaque, "\n");
382
readline_show_prompt(rs);
384
for (i = 0; i < rs->nb_completions; i++) {
385
g_free(rs->completions[i]);
389
static void readline_clear_screen(ReadLineState *rs)
391
rs->printf_func(rs->opaque, "\033[2J\033[1;1H");
392
readline_show_prompt(rs);
396
void readline_handle_byte(ReadLineState *rs, int ch)
398
switch (rs->esc_state) {
405
readline_delete_char(rs);
411
readline_completion(rs);
414
readline_clear_screen(rs);
418
rs->cmd_buf[rs->cmd_buf_size] = '\0';
419
if (!rs->read_password) {
420
readline_hist_add(rs, rs->cmd_buf);
422
rs->printf_func(rs->opaque, "\n");
423
rs->cmd_buf_index = 0;
424
rs->cmd_buf_size = 0;
425
rs->last_cmd_buf_index = 0;
426
rs->last_cmd_buf_size = 0;
427
rs->readline_func(rs->opaque, rs->cmd_buf, rs->readline_opaque);
431
readline_down_char(rs);
435
readline_up_char(rs);
439
readline_kill_line(rs);
443
readline_backword(rs);
446
rs->esc_state = IS_ESC;
450
readline_backspace(rs);
453
rs->esc_state = IS_CSI;
457
readline_insert_char(rs, ch);
464
rs->esc_state = IS_CSI;
466
} else if (ch == 'O') {
467
rs->esc_state = IS_SS3;
470
rs->esc_state = IS_NORM;
477
readline_up_char(rs);
481
readline_down_char(rs);
484
readline_backward_char(rs);
487
readline_forward_char(rs);
490
rs->esc_param = rs->esc_param * 10 + (ch - '0');
493
switch (rs->esc_param) {
498
readline_delete_char(rs);
510
rs->esc_state = IS_NORM;
525
rs->esc_state = IS_NORM;
533
void readline_start(ReadLineState *rs, const char *prompt, int read_password,
534
ReadLineFunc *readline_func, void *opaque)
536
pstrcpy(rs->prompt, sizeof(rs->prompt), prompt);
537
rs->readline_func = readline_func;
538
rs->readline_opaque = opaque;
539
rs->read_password = read_password;
540
readline_restart(rs);
543
void readline_restart(ReadLineState *rs)
545
rs->cmd_buf_index = 0;
546
rs->cmd_buf_size = 0;
549
const char *readline_get_history(ReadLineState *rs, unsigned int index)
551
if (index >= READLINE_MAX_CMDS) {
554
return rs->history[index];
557
void readline_free(ReadLineState *rs)
564
for (i = 0; i < READLINE_MAX_CMDS; i++) {
565
g_free(rs->history[i]);
570
ReadLineState *readline_init(ReadLinePrintfFunc *printf_func,
571
ReadLineFlushFunc *flush_func,
573
ReadLineCompletionFunc *completion_finder)
575
ReadLineState *rs = g_new0(ReadLineState, 1);
579
rs->printf_func = printf_func;
580
rs->flush_func = flush_func;
581
rs->completion_finder = completion_finder;