efi_loader: efi_console: support editable input fields
When editing eficonfig "optional data" (typically cmdline arguments) it's useful to be able to edit the string rather than having to re-type the entire thing. Implement support for editing buffers to make this a whole lot nicer. Specifically, add support for moving the cursor with the arrow keys and End key as well as deleting backwards with the delete key. Signed-off-by: Casey Connolly <casey.connolly@linaro.org> Acked-by: Ilias Apalodimas <ilias.apalodimas@linaro.org> Tested-by: Ilias Apalodimas <ilias.apalodimas@linaro.org> Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
This commit is contained in:
committed by
Heinrich Schuchardt
parent
3cb97f9293
commit
419cc25aa1
@@ -974,6 +974,8 @@ static efi_status_t handle_user_input(u16 *buf, int buf_size,
|
||||
if (!tmp)
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
|
||||
/* Populate tmp so user can edit existing string */
|
||||
u16_strcpy(tmp, buf);
|
||||
ret = efi_console_get_u16_string(cin, tmp, buf_size, NULL, 4, cursor_col);
|
||||
if (ret == EFI_SUCCESS)
|
||||
u16_strcpy(buf, tmp);
|
||||
|
||||
@@ -1384,7 +1384,9 @@ efi_status_t efi_console_get_u16_string(struct efi_simple_text_input_protocol *c
|
||||
int row, int col)
|
||||
{
|
||||
efi_status_t ret;
|
||||
efi_uintn_t len = 0;
|
||||
efi_uintn_t len;
|
||||
efi_uintn_t cursor;
|
||||
efi_uintn_t i;
|
||||
struct efi_input_key key;
|
||||
|
||||
printf(ANSI_CURSOR_POSITION
|
||||
@@ -1393,25 +1395,51 @@ efi_status_t efi_console_get_u16_string(struct efi_simple_text_input_protocol *c
|
||||
|
||||
efi_cin_empty_buffer();
|
||||
|
||||
len = u16_strlen(buf);
|
||||
cursor = len;
|
||||
for (;;) {
|
||||
printf(ANSI_CURSOR_POSITION "%ls"
|
||||
ANSI_CLEAR_LINE_TO_END ANSI_CURSOR_POSITION,
|
||||
row, col, buf, row, col + (int)cursor);
|
||||
do {
|
||||
ret = EFI_CALL(cin->read_key_stroke(cin, &key));
|
||||
mdelay(10);
|
||||
} while (ret == EFI_NOT_READY);
|
||||
|
||||
if (key.unicode_char == u'\b') {
|
||||
if (len > 0)
|
||||
buf[--len] = u'\0';
|
||||
|
||||
printf(ANSI_CURSOR_POSITION
|
||||
"%ls"
|
||||
ANSI_CLEAR_LINE_TO_END, row, col, buf);
|
||||
if (cursor > 0) {
|
||||
if (cursor == len) {
|
||||
buf[--cursor] = u'\0';
|
||||
} else {
|
||||
for (i = cursor - 1; i < len; i++)
|
||||
buf[i] = buf[i + 1];
|
||||
cursor--;
|
||||
}
|
||||
len--;
|
||||
}
|
||||
continue;
|
||||
} else if (key.scan_code == 8) { /* delete */
|
||||
for (i = cursor; i <= len; i++)
|
||||
buf[i] = buf[i + 1];
|
||||
len--;
|
||||
continue;
|
||||
} else if (key.unicode_char == u'\r') {
|
||||
buf[len] = u'\0';
|
||||
return EFI_SUCCESS;
|
||||
} else if (key.unicode_char == 0x3 || key.scan_code == 23) {
|
||||
return EFI_ABORTED;
|
||||
} else if (key.scan_code == 3) { /* Right arrow */
|
||||
cursor += (cursor < len) ? 1 : 0;
|
||||
continue;
|
||||
} else if (key.scan_code == 4) { /* Left arrow */
|
||||
cursor -= (cursor > 0) ? 1 : 0;
|
||||
continue;
|
||||
} else if (key.scan_code == 5) { /* Home */
|
||||
cursor = 0;
|
||||
continue;
|
||||
} else if (key.scan_code == 6) { /* End */
|
||||
cursor = len;
|
||||
continue;
|
||||
} else if (key.unicode_char < 0x20) {
|
||||
/* ignore control codes other than Ctrl+C, '\r' and '\b' */
|
||||
continue;
|
||||
@@ -1428,8 +1456,17 @@ efi_status_t efi_console_get_u16_string(struct efi_simple_text_input_protocol *c
|
||||
if (len >= (count - 1))
|
||||
continue;
|
||||
|
||||
buf[len] = key.unicode_char;
|
||||
/*
|
||||
* Insert the character into the middle of the buffer, shift the
|
||||
* characters after the cursor along. The check above ensures we
|
||||
* will never overflow the buffer.
|
||||
* If the cursor is at the end of the string then this will
|
||||
* do nothing.
|
||||
*/
|
||||
for (i = len + 1; i > cursor; i--)
|
||||
buf[i] = buf[i - 1];
|
||||
buf[cursor] = key.unicode_char;
|
||||
cursor++;
|
||||
len++;
|
||||
printf(ANSI_CURSOR_POSITION "%ls", row, col, buf);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user