aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2009-08-13 22:37:37 -0700
committerH. Peter Anvin <hpa@zytor.com>2009-08-13 22:37:37 -0700
commit4672b07a84060fa42e8034d99a4900849787128a (patch)
tree22b0f3e45715d8e2c516a17c9efb0e52a540229e
parent0f43a3e07f91d3b58ceda7d7aa27aaaaaad6b873 (diff)
downloadbak.git-4672b07a84060fa42e8034d99a4900849787128a.tar.gz
bak.git-4672b07a84060fa42e8034d99a4900849787128a.tar.xz
bak.git-4672b07a84060fa42e8034d99a4900849787128a.zip
cli: edit_cmdline() that actually works
Fix a number of issues with edit_cmdline when used in a scrolling-screen context. Here we are forced to keep track of coordinates within our chunk of the screen; unfortunately this is not generic w.r.t. window width on the serial console, but it should at least behave properly within the given width. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r--core/elflink/cli.c103
1 files changed, 89 insertions, 14 deletions
diff --git a/core/elflink/cli.c b/core/elflink/cli.c
index 78076b64..bc681837 100644
--- a/core/elflink/cli.c
+++ b/core/elflink/cli.c
@@ -49,19 +49,33 @@ int mygetkey(clock_t timeout)
}
}
-const char *edit_cmdline(const char *input, int top)
+const char *edit_cmdline(const char *input, int top /*, int width */)
{
static char cmdline[MAX_CMDLINE_LEN];
int key, len, prev_len, cursor;
int redraw = 1; /* We enter with the menu already drawn */
+ int x, y;
+ bool done = false;
+ const char *ret;
+
+ int width = 0;
+
+ if (!width) {
+ int height;
+ if (getscreensize(1, &height, &width))
+ width = 80;
+ }
+
+ printf("width = %d\n", width);
strncpy(cmdline, input, MAX_CMDLINE_LEN);
cmdline[MAX_CMDLINE_LEN - 1] = '\0';
len = cursor = strlen(cmdline);
prev_len = 0;
+ x = y = 0;
- for (;;) {
+ while (!done) {
if (redraw > 1) {
/* Clear and redraw whole screen */
/* Enable ASCII on G0 and DEC VT on G1; do it in this order
@@ -69,16 +83,47 @@ const char *edit_cmdline(const char *input, int top)
/* clear_screen();
draw_menu(-1, top, 1);
prev_len = 0;*/
+ printf("\033[0m\033[2J\033[H");
}
if (redraw > 0) {
+ int dy, at;
+
+ prev_len = max(len, prev_len);
+
/* Redraw the command line */
- /* printf("\033[?25l\033[%d;1H\1#9> \2#10%s",
- CMDLINE_ROW, pad_line(cmdline, 0, max(len, prev_len)));
- printf("\2#10\033[%d;3H%s\033[?25h",
- CMDLINE_ROW, pad_line(cmdline, 0, cursor));
+ printf("\033[?7l\033[?25l");
+ if (y)
+ printf("\033[%dA", y);
+ printf("\033[1G\033[1;36m> \033[0m");
+
+ x = 2;
+ y = 0;
+ at = 0;
+ while (at < prev_len) {
+ putchar(at >= len ? ' ' : cmdline[at]);
+ at++;
+ x++;
+ if (x >= width) {
+ printf("\r\n");
+ x = 0;
+ y++;
+ }
+ }
+ printf("\033[K\r");
+
+ dy = y - (cursor+2) / width;
+ x = (cursor+2) % width;
+
+ if (dy) {
+ printf("\033[%dA", dy);
+ y -= dy;
+ }
+ if (x)
+ printf("\033[%dC", x);
+ printf("\033[?25h");
prev_len = len;
- redraw = 0;*/
+ redraw = 0;
}
key = mygetkey(0);
@@ -90,11 +135,15 @@ const char *edit_cmdline(const char *input, int top)
case KEY_ENTER:
case KEY_CTRL('J'):
- return cmdline;
+ ret = cmdline;
+ done = true;
+ break;
case KEY_ESC:
case KEY_CTRL('C'):
- return NULL;
+ ret = NULL;
+ done = true;
+ break;
case KEY_BACKSPACE:
case KEY_DEL:
@@ -134,9 +183,19 @@ const char *edit_cmdline(const char *input, int top)
while (cursor && !my_isspace(cmdline[cursor - 1]))
cursor--;
+#if 0
memmove(cmdline + cursor, cmdline + prevcursor,
len - prevcursor + 1);
- len -= (cursor - prevcursor);
+#else
+ {
+ int i;
+ char *q = cmdline + cursor;
+ char *p = cmdline + prevcursor;
+ for (i = 0; i < len - prevcursor + 1; i++)
+ *q++ = *p++;
+ }
+#endif
+ len -= (prevcursor - cursor);
redraw = 1;
}
break;
@@ -152,7 +211,14 @@ const char *edit_cmdline(const char *input, int top)
case KEY_RIGHT:
case KEY_CTRL('F'):
if (cursor < len) {
- putchar(cmdline[cursor++]);
+ putchar(cmdline[cursor]);
+ cursor++;
+ x++;
+ if (x >= width) {
+ printf("\r\n");
+ y++;
+ x = 0;
+ }
}
break;
@@ -198,10 +264,16 @@ const char *edit_cmdline(const char *input, int top)
default:
if (key >= ' ' && key <= 0xFF && len < MAX_CMDLINE_LEN - 1) {
if (cursor == len) {
- cmdline[len] = key;
- cmdline[++len] = '\0';
- cursor++;
+ cmdline[len++] = key;
+ cmdline[len] = '\0';
putchar(key);
+ cursor++;
+ x++;
+ if (x >= width) {
+ printf("\r\n\033[K");
+ y++;
+ x = 0;
+ }
prev_len++;
} else {
memmove(cmdline + cursor + 1, cmdline + cursor,
@@ -214,5 +286,8 @@ const char *edit_cmdline(const char *input, int top)
break;
}
}
+
+ printf("\033[?7h");
+ return ret;
}