From 5e0ac5e316a3d33610b4681f0d4f246281a90bce Mon Sep 17 00:00:00 2001 From: Joursoir Date: Sat, 11 Dec 2021 15:04:13 +0300 Subject: implement the input widget --- .../UefiShellUfmCommandLib.inf | 1 + Library/UefiShellUfmCommandLib/widget/input.c | 114 +++++++++++++++++++++ Library/UefiShellUfmCommandLib/widget/input.h | 74 +++++++++++++ 3 files changed, 189 insertions(+) create mode 100644 Library/UefiShellUfmCommandLib/widget/input.c create mode 100644 Library/UefiShellUfmCommandLib/widget/input.h diff --git a/Library/UefiShellUfmCommandLib/UefiShellUfmCommandLib.inf b/Library/UefiShellUfmCommandLib/UefiShellUfmCommandLib.inf index a80d2cf..c3d623e 100644 --- a/Library/UefiShellUfmCommandLib/UefiShellUfmCommandLib.inf +++ b/Library/UefiShellUfmCommandLib/UefiShellUfmCommandLib.inf @@ -14,6 +14,7 @@ tbi/win.c menu-bar.c command-bar.c + widget/input.c panel.c dir.c fs.c diff --git a/Library/UefiShellUfmCommandLib/widget/input.c b/Library/UefiShellUfmCommandLib/widget/input.c new file mode 100644 index 0000000..7531321 --- /dev/null +++ b/Library/UefiShellUfmCommandLib/widget/input.c @@ -0,0 +1,114 @@ +#include +#include +#include + +#include "input.h" + +struct widget_input *input_alloc(struct screen *scr, INT32 x, INT32 y, + INT32 width, INT32 attr, CONST CHAR16 *def_text) +{ + struct widget_input *in; + + ASSERT(scr != NULL); + + in = AllocateZeroPool(sizeof(struct widget_input)); + if(!in) + return NULL; + + in->win = newwin(scr, width, 1, x, y); + if(!in->win) { + input_release(in); + return NULL; + } + wattrset(in->win, attr); + whline(in->win, 0, 0, 0, attr, 0); + mvwprintf(in->win, 0, 0, def_text); + + in->point = 0; + in->max_size = width; + in->buf_len = 0; + in->buffer = AllocateZeroPool((in->max_size + 1) * sizeof(CHAR16)); + if(!in->buffer) { + input_release(in); + return NULL; + } + + return in; +} + +VOID input_release(struct widget_input *in) +{ + ASSERT(in != NULL); + + if(in->win) + delwin(in->win); + if(in->buffer) + FreePool(in->buffer); + + FreePool(in); +} + +VOID input_set_point(struct widget_input *in, INTN pos) +{ + in->point = pos; + if(pos < 0) + in->point = 0; + else if(pos > in->buf_len) + in->point = in->buf_len; + + wmove(in->win, in->point, 0); + input_update(in); +} + +VOID input_handle_char(struct widget_input *in, EFI_INPUT_KEY key) +{ + UINTN i; + + if(key.ScanCode == SCAN_LEFT) + input_set_point(in, in->point - 1); + else if(key.ScanCode == SCAN_RIGHT) + input_set_point(in, in->point + 1); + else { + switch(key.UnicodeChar) { + + case 0x0: + break; + case CHAR_BACKSPACE: { + if(in->buf_len == 0) + break; + + for(i = in->point; i < in->buf_len; i++) + in->buffer[i - 1] = in->buffer[i]; + in->buffer[i - 1] = CHAR_NULL; + mvwaddch(in->win, i - 1, 0, L' ', -1); + mvwprintf(in->win, in->point - 1, 0, in->buffer + in->point - 1); + + in->buf_len--; + input_set_point(in, in->point - 1); + } + case CHAR_TAB: + case CHAR_LINEFEED: + case CHAR_CARRIAGE_RETURN: + break; + default: { + if(in->buf_len >= (in->max_size-1)) + break; + + for(i = in->max_size-1; i > in->point; i--) + in->buffer[i] = in->buffer[i - 1]; + in->buffer[in->point] = key.UnicodeChar; + wprintf(in->win, in->buffer + in->point); + + in->buf_len++; + input_set_point(in, in->point + 1); + } + + } + } +} + +VOID input_update(struct widget_input *in) +{ + wrefresh(in->win); +} + diff --git a/Library/UefiShellUfmCommandLib/widget/input.h b/Library/UefiShellUfmCommandLib/widget/input.h new file mode 100644 index 0000000..cc917df --- /dev/null +++ b/Library/UefiShellUfmCommandLib/widget/input.h @@ -0,0 +1,74 @@ +#ifndef UFM_WIDGET_INPUT_H +#define UFM_WIDGET_INPUT_H + +#include +#include "tbi/screen.h" +#include "tbi/win.h" + +struct widget_input { + struct window *win; + INTN point; // cursor position in the input line in chars + UINTN max_size; // maximum length of input line + UINTN buf_len; // current length of input line + CHAR16 *buffer; +}; + +/* + * Creates a input widget (single line of text and lets the user edit it) with + * given parameters. + * + * scr: the information of the screen + * x: the column coordinate (starts from 0) of upper left corner of the window + * y: the line coordinate (starts from 0) of upper left corner of the window + * width: the length and the maximum number of characters in the line + * attr: attributes of the line + * def_text: the pointer to initial string in the input line + * + * return: A pointer to the allocated structure or NULL if allocation fails +*/ +struct widget_input *input_alloc(struct screen *scr, INT32 x, INT32 y, + INT32 width, INT32 attr, CONST CHAR16 *def_text); + +/* + * Deletes the input widget, frees the structure + * + * in: the input widget on which to operate + * + * return: VOID +*/ +VOID input_release(struct widget_input *in); + +/* + * Moves the cursor to the specified position from 0 to current length of + * the input line. If the position is not in this limit, then extreme + * points will be used + * + * in: the input widget on which to operate + * pos: the coordinate (starts from 0) + * + * return: VOID +*/ +VOID input_set_point(struct widget_input *in, INTN pos); + +/* + * Handles the given key and print it (if it's character). + * Supports next control characters: Backspace, left arrow, right arrow. + * Ignores others. + * + * in: the input widget on which to operate + * key: the key to handle + * + * return: VOID +*/ +VOID input_handle_char(struct widget_input *in, EFI_INPUT_KEY key); + +/* + * Does the output of input widget to the terminal + * + * in: the input widget on which to operate + * + * return: VOID +*/ +VOID input_update(struct widget_input *in); + +#endif /* UFM_WIDGET_INPUT_H */ -- cgit v1.2.3-18-g5258