X-Git-Url: https://git.ozlabs.org/?p=petitboot;a=blobdiff_plain;f=ui%2Fncurses%2Fnc-widgets.c;h=f82192939dd968d1dfd4ce2f889cbb382b1d6d8b;hp=60f91007ce94f280be21d01f59503cdfb3868d09;hb=cd94ab94766ae863467195324fb84b3d020c96cf;hpb=66bf929fa97fabb70198455f9eec2e9ccf0661fa diff --git a/ui/ncurses/nc-widgets.c b/ui/ncurses/nc-widgets.c index 60f9100..f821929 100644 --- a/ui/ncurses/nc-widgets.c +++ b/ui/ncurses/nc-widgets.c @@ -77,6 +77,9 @@ struct nc_widgetset { void (*widget_focus)(struct nc_widget *, void *); void *widget_focus_arg; FIELD *cur_field; + + /* custom validators */ + FIELDTYPE *ipv4_multi_type; }; struct nc_widget { @@ -105,6 +108,7 @@ struct nc_widget_checkbox { }; struct nc_widget_textbox { + struct nc_widgetset *set; struct nc_widget widget; }; @@ -328,6 +332,7 @@ struct nc_widget_textbox *widget_new_textbox(struct nc_widgetset *set, FIELD *f; textbox = talloc_zero(set, struct nc_widget_textbox); + textbox->set = set; textbox->widget.height = 1; textbox->widget.width = len; textbox->widget.x = x; @@ -348,6 +353,67 @@ struct nc_widget_textbox *widget_new_textbox(struct nc_widgetset *set, return textbox; } +void widget_textbox_set_fixed_size(struct nc_widget_textbox *textbox) +{ + field_opts_on(textbox->widget.field, O_STATIC); +} + +void widget_textbox_set_validator_integer(struct nc_widget_textbox *textbox, + long min, long max) +{ + set_field_type(textbox->widget.field, TYPE_INTEGER, 1, min, max); +} + +void widget_textbox_set_validator_ipv4(struct nc_widget_textbox *textbox) +{ + set_field_type(textbox->widget.field, TYPE_IPV4); +} + +static bool check_ipv4_multi_char(int c, + const void *arg __attribute__((unused))) +{ + return isdigit(c) || c == '.' || c == ' '; +} + +static bool check_ipv4_multi_field(FIELD *field, + const void *arg __attribute__((unused))) +{ + char *buf = field_buffer(field, 0); + unsigned int ip[4]; + int n, len; + + while (*buf != '\0') { + n = sscanf(buf, "%u.%u.%u.%u%n", + &ip[0], &ip[1], &ip[2], &ip[3], &len); + if (n != 4) + return false; + + if (ip[0] > 255 || ip[1] > 255 || ip[2] > 255 || ip[3] > 255) + return false; + + for (buf += len; *buf != '\0'; buf++) { + if (isspace(*buf)) + continue; + else if (isdigit(*buf)) + break; + else + return false; + } + } + + return true; +} + +void widget_textbox_set_validator_ipv4_multi(struct nc_widget_textbox *textbox) +{ + if (!textbox->set->ipv4_multi_type) { + textbox->set->ipv4_multi_type = new_fieldtype( + check_ipv4_multi_field, + check_ipv4_multi_char); + } + set_field_type(textbox->widget.field, textbox->set->ipv4_multi_type); +} + static void select_option_change(struct select_option *opt, bool selected) { const char *str; @@ -623,19 +689,26 @@ static void widget_focus_change(struct nc_widget *widget, FIELD *field, bool widgetset_process_key(struct nc_widgetset *set, int key) { struct nc_widget *widget; - FIELD *field; + FIELD *field, *tmp; int req = 0; + bool tab; field = current_field(set->form); assert(field); + tab = false; + /* handle field change events */ switch (key) { case KEY_BTAB: + tab = true; + /* fall through */ case KEY_UP: req = REQ_PREV_FIELD; break; case '\t': + tab = true; + /* fall through */ case KEY_DOWN: req = REQ_NEXT_FIELD; break; @@ -651,8 +724,18 @@ bool widgetset_process_key(struct nc_widgetset *set, int key) if (req) { widget_focus_change(widget, field, false); form_driver(set->form, req); - form_driver(set->form, REQ_END_FIELD); + + /* if we're doing a tabbed-field-change, skip until we + * see the next widget */ + tmp = field; field = current_field(set->form); + + for (; tab && tmp != field && field_userptr(field) == widget;) { + form_driver(set->form, req); + field = current_field(set->form); + } + + form_driver(set->form, REQ_END_FIELD); widget = field_userptr(field); widget_focus_change(widget, field, true); if (widget->field_focus) @@ -672,6 +755,8 @@ static int widgetset_destructor(void *ptr) { struct nc_widgetset *set = ptr; free_form(set->form); + if (set->ipv4_multi_type) + free_fieldtype(set->ipv4_multi_type); return 0; } @@ -792,6 +877,10 @@ void widget_move(struct nc_widget *widget, int y, int x) widget->x = x; widget->y = y; + + if (x + widget->width > COLS) + pb_debug("%s: Widget at %d,%d runs over pad! (%d)", __func__, + y, x, x + widget->width); } int widget_height(struct nc_widget *widget)