X-Git-Url: http://git.ozlabs.org/?p=petitboot;a=blobdiff_plain;f=ui%2Fncurses%2Fnc-widgets.c;h=7dc2df3f1d1fc2138c001b7511bac6bfc0e8041a;hp=e092f8bbb0df0553eca18dc03db9f1ef7bc7d6b5;hb=297d2f0cc9c0a233fadf42dacc08708ad3909f77;hpb=74ca9eaf3d0dd64560c3eaa132df2e854b51bcdd diff --git a/ui/ncurses/nc-widgets.c b/ui/ncurses/nc-widgets.c index e092f8b..7dc2df3 100644 --- a/ui/ncurses/nc-widgets.c +++ b/ui/ncurses/nc-widgets.c @@ -52,6 +52,7 @@ #include #include #include +#include #include "nc-cui.h" #include "nc-widgets.h" @@ -138,6 +139,7 @@ struct nc_widget_select { char *str; int val; FIELD *field; + int lines; } *options; int top, left, size; int n_options, selected_option; @@ -160,21 +162,6 @@ static bool key_is_select(int key) return key == ' ' || key == '\r' || key == '\n' || key == KEY_ENTER; } -static bool key_is_minus(int key) -{ - return key == 055; -} - -static bool key_is_left(int key) -{ - return key == KEY_LEFT; -} - -static bool key_is_right(int key) -{ - return key == KEY_RIGHT; -} - static bool process_key_nop(struct nc_widget *widget __attribute__((unused)), FORM *form __attribute((unused)), int key __attribute__((unused))) @@ -350,6 +337,14 @@ static bool textbox_process_key( case KEY_DC: form_driver(form, REQ_DEL_CHAR); break; + case '\t': + case KEY_BTAB: + case KEY_UP: + case KEY_DOWN: + case KEY_PPAGE: + case KEY_NPAGE: + /* Don't catch navigational keys */ + return false; default: form_driver(form, key); break; @@ -479,6 +474,7 @@ static void subset_delete_active(struct nc_widget_subset *subset, int idx) struct nc_widget *widget; size_t rem; int i, val; + uint32_t opts; /* Shift field focus to nearest active option or next visible field */ if (subset->n_active > 1) { @@ -490,8 +486,11 @@ static void subset_delete_active(struct nc_widget_subset *subset, int idx) } else { for (i = 0; i < set->n_fields; i++) if (field_visible(set->fields[i])) { - set->cur_field = set->fields[i]; - break; + opts = field_opts(set->fields[i]); + if ((opts & O_ACTIVE) == O_ACTIVE) { + set->cur_field = set->fields[i]; + break; + } } } @@ -520,7 +519,7 @@ static bool subset_process_key(struct nc_widget *w, FORM *form, int key) int i, val, opt_idx = -1; FIELD *field; - if (!key_is_minus(key) && !key_is_left(key) && !key_is_right(key)) + if (key != '-' && key != '+' && key != KEY_DC && key != KEY_BACKSPACE) return false; field = current_field(form); @@ -536,10 +535,10 @@ static bool subset_process_key(struct nc_widget *w, FORM *form, int key) if (opt_idx < 0) return false; - if (key_is_minus(key)) + if (key == KEY_DC || key == KEY_BACKSPACE) subset_delete_active(subset, opt_idx); - if (key_is_left(key)){ + if (key == '-') { if (opt_idx == 0) return true; @@ -548,7 +547,7 @@ static bool subset_process_key(struct nc_widget *w, FORM *form, int key) subset->active[opt_idx - 1] = val; } - if (key_is_right(key)){ + if (key == '+') { if (opt_idx >= subset->n_active - 1) return true; @@ -839,21 +838,25 @@ static void select_set_visible(struct nc_widget *widget, bool visible) static void select_move(struct nc_widget *widget, int y, int x) { struct nc_widget_select *select = to_select(widget); - int i; + int i, cur = 0; - for (i = 0; i < select->n_options; i++) - field_move(select->options[i].field, y + i, x); + for (i = 0; i < select->n_options; i++) { + field_move(select->options[i].field, y + cur, x); + cur += select->options[i].lines; + } } static void select_field_focus(struct nc_widget *widget, FIELD *field) { struct nc_widget_select *select = to_select(widget); - int i; + int i, cur = 0; for (i = 0; i < select->n_options; i++) { - if (field != select->options[i].field) + if (field != select->options[i].field) { + cur += select->options[i].lines; continue; - widget->focus_y = i; + } + widget->focus_y = cur; return; } } @@ -895,10 +898,47 @@ struct nc_widget_select *widget_new_select(struct nc_widgetset *set, return select; } +static int widget_select_fold_cb(void *arg, const char *buf, int len) +{ + struct nc_widget_select *select = arg; + char *line, *newstr, *padbuf = NULL; + int i, pad; + + if (!len) + return 0; + + line = talloc_strndup(select->options, buf, len); + + i = select->n_options - 1; + pad = max(0, select->widget.width - strncols(line)); + + if (pad) { + padbuf = talloc_array(select->options, char, pad + 1); + memset(padbuf, ' ', pad); + padbuf[pad] = '\0'; + } + + if (select->options[i].str) + newstr = talloc_asprintf_append(select->options[i].str, + "%s%s", line, + pad ? padbuf : ""); + else + newstr = talloc_asprintf(select->options, "%s%s", line, + pad ? padbuf : ""); + + select->options[i].str = newstr; + select->options[i].lines++; + + talloc_free(padbuf); + talloc_free(line); + return 0; +} + void widget_select_add_option(struct nc_widget_select *select, int value, const char *text, bool selected) { const char *str; + char *full_text; FIELD *f; int i; @@ -917,23 +957,29 @@ void widget_select_add_option(struct nc_widget_select *select, int value, str = select_unselected_str; i = select->n_options++; - select->widget.height = select->n_options; - select->options = talloc_realloc(select, select->options, struct select_option, i + 2); select->options[i].val = value; - select->options[i].str = talloc_asprintf(select->options, - "%s %s", str, text); + select->options[i].lines = 0; + select->options[i].str = NULL; - select->options[i].field = f = new_field(1, select->size, - select->top + i, - select->left, 0, 0); + full_text = talloc_asprintf(select->options, "%s %s", str, text); + fold_text(full_text, select->widget.width, + widget_select_fold_cb, select); - field_opts_off(f, O_WRAP | O_EDIT); + select->options[i].field = f = new_field(select->options[i].lines, + select->size, + select->top + select->widget.height, + select->left, 0, 0); + + select->widget.height += select->options[i].lines; + + field_opts_off(f, O_EDIT); set_field_userptr(f, &select->widget); set_field_buffer(f, 0, select->options[i].str); widgetset_add_field(select->set, f); + talloc_free(full_text); } int widget_select_get_value(struct nc_widget_select *select) @@ -945,7 +991,7 @@ int widget_select_get_value(struct nc_widget_select *select) int widget_select_height(struct nc_widget_select *select) { - return select->n_options; + return select->widget.height; } void widget_select_on_change(struct nc_widget_select *select, @@ -1072,6 +1118,12 @@ bool widgetset_process_key(struct nc_widgetset *set, int key) field = current_field(set->form); assert(field); + widget = field_userptr(field); + + if (widget->process_key) + if (widget->process_key(widget, set->form, key)) + return true; + tab = false; /* handle field change events */ @@ -1080,12 +1132,14 @@ bool widgetset_process_key(struct nc_widgetset *set, int key) tab = true; /* fall through */ case KEY_UP: + case KEY_LEFT: req = REQ_SPREV_FIELD; break; case '\t': tab = true; /* fall through */ case KEY_DOWN: + case KEY_RIGHT: req = REQ_SNEXT_FIELD; break; case KEY_PPAGE: @@ -1096,7 +1150,6 @@ bool widgetset_process_key(struct nc_widgetset *set, int key) break; } - widget = field_userptr(field); if (req) { widget_focus_change(widget, field, false); form_driver(set->form, req); @@ -1121,10 +1174,7 @@ bool widgetset_process_key(struct nc_widgetset *set, int key) return true; } - if (!widget->process_key) - return false; - - return widget->process_key(widget, set->form, key); + return false; } static int widgetset_destructor(void *ptr) @@ -1175,10 +1225,8 @@ void widgetset_post(struct nc_widgetset *set) post_form(set->form); form_driver(set->form, REQ_END_FIELD); - if (set->cur_field) { + if (set->cur_field) set_current_field(set->form, set->cur_field); - field = set->cur_field; - } field = current_field(set->form); widget = field_userptr(field);