static void buttons_width(struct widget_data *widget_data, int n, int *minwidth, int *maxwidth) #endif /* CONFIG_UTF8 */ { int maxw = -BUTTON_HSPACING; #ifdef CONFIG_UTF8 int button_lr_len = utf8_ptr2cells(BUTTON_LEFT, NULL) + utf8_ptr2cells(BUTTON_RIGHT, NULL); #endif /* CONFIG_UTF8 */ assert(n > 0); if_assert_failed return; while (n--) { int minw; #ifdef CONFIG_UTF8 if (utf8) minw = utf8_ptr2cells((widget_data++)->widget->text, NULL) + BUTTON_HSPACING + button_lr_len; else #endif /* CONFIG_UTF8 */ minw = (widget_data++)->widget->info.button.textlen + BUTTON_HSPACING + BUTTON_LR_LEN; maxw += minw; if (minwidth) int_lower_bound(minwidth, minw); } if (maxwidth) int_lower_bound(maxwidth, maxw); }
int area_cursor(struct form_control *fc, struct form_state *fs, int utf8) { struct line_info *line; int x, y; assert(fc && fs); if_assert_failed return 0; if (utf8) line = format_textutf8(fs->value, fc->cols, fc->wrap, 0); else line = format_text(fs->value, fc->cols, fc->wrap, 0); if (!line) return 0; if (fs->state_cell) y = get_textarea_line_number(line, fs->state_cell); else y = get_textarea_line_number(line, fs->state); if (y == -1) { mem_free(line); return 0; } if (utf8) { if (fs->state_cell) { x = utf8_ptr2cells(fs->value + line[y].start, fs->value + fs->state_cell); x += line[y].last_char_width; } else x = utf8_ptr2cells(fs->value + line[y].start, fs->value + fs->state); } else { x = fs->state - line[y].start; if (fc->wrap && x == fc->cols) x--; } mem_free(line); int_bounds(&fs->vpos, x - fc->cols + 1, x); int_bounds(&fs->vypos, y - fc->rows + 1, y); x -= fs->vpos; y -= fs->vypos; return y * fc->cols + x; }
void group_layouter(struct dialog_data *dlg_data) { struct terminal *term = dlg_data->win->term; int w = dialog_max_width(term); int rw; int y = 0; int n = dlg_data->number_of_widgets - 2; #ifdef CONFIG_UTF8 if (term->utf8_cp) rw = int_min(w, utf8_ptr2cells(dlg_data->dlg->title, NULL)); else #endif /* CONFIG_UTF8 */ rw = int_min(w, strlen(dlg_data->dlg->title)); dlg_format_group(dlg_data, dlg_data->widgets_data, n, 0, &y, w, &rw, 1); y++; dlg_format_buttons(dlg_data, dlg_data->widgets_data + n, 2, 0, &y, w, &rw, ALIGN_CENTER, 1); w = rw; draw_dialog(dlg_data, w, y); y = dlg_data->box.y + DIALOG_TB + 1; dlg_format_group(dlg_data, dlg_data->widgets_data, n, dlg_data->box.x + DIALOG_LB, &y, w, NULL, 0); y++; dlg_format_buttons(dlg_data, dlg_data->widgets_data + n, 2, dlg_data->box.x + DIALOG_LB, &y, w, &rw, ALIGN_CENTER, 0); }
static int do_op_up(struct form_state *fs, struct line_info *line, int current, int utf8) { int old_state; if (current == -1) return 0; if (!(current - !!fs->state_cell)) return 1; if (!utf8) { fs->state -= line[current].start - line[current-1].start; int_upper_bound(&fs->state, line[current-1].end); return 0; } old_state = fs->state; if (fs->state_cell) { int len = utf8_ptr2cells(fs->value + line[current - 1].start, fs->value + fs->state_cell); new_pos(fs, line, current - 2, len + line[current - 1].last_char_width); } else { int len = utf8_ptr2cells(fs->value + line[current].start, fs->value + fs->state); new_pos(fs, line, current - 1, len); } if (old_state != fs->state ) { if (fs->state_cell && fs->state == line[current - 1].start) { unsigned char *new_value; new_value = utf8_prevchar(fs->value + fs->state, 1, fs->value); fs->state_cell = new_value - fs->value; } else fs->state_cell = 0; } return 0; }
void dlg_format_group(struct dialog_data *dlg_data, struct widget_data *widget_data, int n, int x, int *y, int w, int *rw, int format_only) { struct terminal *term = dlg_data->win->term; int space_between_widgets = 1; int line_width = 0; int xpos; struct color_pair *color = get_bfu_color(term, "dialog.text"); assert(n > 0); if_assert_failed return; while (n--) { int widget_width; int width; unsigned char *text = widget_data->widget->text; int label_length; int label_padding; #ifdef CONFIG_UTF8 if (term->utf8_cp) { if (text && *text) label_length = utf8_ptr2cells(text, NULL); else label_length = 0; } else #endif /* CONFIG_UTF8 */ label_length = (text && *text) ? strlen(text) : 0; label_padding = (label_length > 0); if (widget_data->widget->type == WIDGET_CHECKBOX) { width = CHECKBOX_LEN; } else if (widget_is_textfield(widget_data)) { #ifdef CONFIG_UTF8 if (term->utf8_cp) { width = utf8_ptr2cells(widget_data->widget->data, NULL); } else #endif /* CONFIG_UTF8 */ width = widget_data->widget->datalen; } else { /* TODO: handle all widget types. */ widget_data++; continue; } int_bounds(&label_length, 0, w - width - label_padding); widget_width = width + label_padding + label_length; if (line_width + widget_width > w) { line_width = 0; (*y) += 2; /* Next line */ } xpos = x + line_width; if (!format_only) { if (widget_data->widget->type == WIDGET_CHECKBOX) { /* Draw text at right of checkbox. */ if (label_length) { #ifdef CONFIG_UTF8 if (term->utf8_cp) { int lb = utf8_cells2bytes( text, label_length, NULL); draw_dlg_text(dlg_data, xpos + width + label_padding, *y, text, lb, 0, color); } else #endif /* CONFIG_UTF8 */ { draw_dlg_text(dlg_data, xpos + width + label_padding, *y, text, label_length, 0, color); } } set_box(&widget_data->box, xpos, *y, width, 1); } else if (widget_is_textfield(widget_data)) { /* Draw label at left of widget. */ if (label_length) { #ifdef CONFIG_UTF8 if (term->utf8_cp) { int lb = utf8_cells2bytes( text, label_length, NULL); draw_dlg_text(dlg_data, xpos, *y, text, lb, 0, color); } else #endif /* CONFIG_UTF8 */ { draw_dlg_text(dlg_data, xpos, *y, text, label_length, 0, color); } } set_box(&widget_data->box, xpos + label_padding + label_length, *y, width, 1); } } line_width += widget_width; if (rw) int_bounds(rw, line_width, w); line_width += space_between_widgets; widget_data++; } (*y)++; }
static widget_handler_status_T display_button(struct dialog_data *dlg_data, struct widget_data *widget_data) { struct terminal *term = dlg_data->win->term; struct color_pair *color, *shortcut_color; struct el_box *pos = &widget_data->box; int len, x; int sel = is_selected_widget(dlg_data, widget_data); if (sel) { shortcut_color = get_bfu_color(term, "dialog.button-shortcut-selected"); color = get_bfu_color(term, "dialog.button-selected"); } else { shortcut_color = get_bfu_color(term, "dialog.button-shortcut"); color = get_bfu_color(term, "dialog.button"); } if (!color || !shortcut_color) return EVENT_PROCESSED; #ifdef CONFIG_UTF8 if (term->utf8_cp) { int button_left_len = utf8_ptr2cells(BUTTON_LEFT, NULL); int button_right_len = utf8_ptr2cells(BUTTON_RIGHT, NULL); x = pos->x + button_left_len; len = widget_data->box.width - (button_left_len + button_right_len); } else #endif /* CONFIG_UTF8 */ { x = pos->x + BUTTON_LEFT_LEN; len = widget_data->box.width - BUTTON_LR_LEN; } draw_dlg_text(dlg_data, pos->x, pos->y, BUTTON_LEFT, BUTTON_LEFT_LEN, 0, color); if (len > 0) { unsigned char *text = widget_data->widget->text; int hk_pos = widget_data->widget->info.button.hotkey_pos; int attr; attr = get_opt_bool("ui.dialogs.underline_button_shortcuts", NULL) ? SCREEN_ATTR_UNDERLINE : 0; #ifdef CONFIG_UTF8 if (term->utf8_cp) { if (hk_pos >= 0) { int hk_bytes = utf8charlen(&text[hk_pos+1]); int cells_to_hk = utf8_ptr2cells(text, &text[hk_pos]); int right = widget_data->widget->info.button.truetextlen - hk_pos - hk_bytes; int hk_cells = utf8_char2cells(&text[hk_pos + 1], NULL); if (hk_pos) draw_dlg_text(dlg_data, x, pos->y, text, hk_pos, 0, color); draw_dlg_text(dlg_data, x + cells_to_hk, pos->y, &text[hk_pos + 1], hk_bytes, attr, shortcut_color); if (right > 1) draw_dlg_text(dlg_data, x+cells_to_hk+hk_cells, pos->y, &text[hk_pos + hk_bytes + 1], right - 1, 0, color); } else { int hk_width = utf8_char2cells(text, NULL); int hk_len = utf8charlen(text); int len_to_display = utf8_cells2bytes(&text[hk_len], len - hk_width, NULL); draw_dlg_text(dlg_data, x, pos->y, text, hk_len, attr, shortcut_color); draw_dlg_text(dlg_data, x + hk_width, pos->y, &text[hk_len], len_to_display, 0, color); } } else #endif /* CONFIG_UTF8 */ if (hk_pos >= 0) { int right = widget_data->widget->info.button.truetextlen - hk_pos - 1; if (hk_pos) { draw_dlg_text(dlg_data, x, pos->y, text, hk_pos, 0, color); } draw_dlg_text(dlg_data, x + hk_pos, pos->y, &text[hk_pos + 1], 1, attr, shortcut_color); if (right > 1) { draw_dlg_text(dlg_data, x + hk_pos + 1, pos->y, &text[hk_pos + 2], right - 1, 0, color); } } else { draw_dlg_text(dlg_data, x, pos->y, text, 1, attr, shortcut_color); draw_dlg_text(dlg_data, x + 1, pos->y, &text[1], len - 1, 0, color); } } #ifdef CONFIG_UTF8 if (term->utf8_cp) { int text_cells = utf8_ptr2cells(widget_data->widget->text, NULL); int hk = (widget_data->widget->info.button.hotkey_pos >= 0); draw_dlg_text(dlg_data, x + text_cells - hk, pos->y, BUTTON_RIGHT, BUTTON_RIGHT_LEN, 0, color); } else #endif /* CONFIG_UTF8 */ draw_dlg_text(dlg_data, x + len, pos->y, BUTTON_RIGHT, BUTTON_RIGHT_LEN, 0, color); if (sel) { set_dlg_cursor(term, dlg_data, x, pos->y, 1); set_dlg_window_ptr(dlg_data, dlg_data->win, pos->x, pos->y); } return EVENT_PROCESSED; }
void dlg_format_buttons(struct dialog_data *dlg_data, struct widget_data *widget_data, int n, int x, int *y, int w, int *rw, enum format_align align, int format_only) { #ifdef CONFIG_UTF8 struct terminal *term = dlg_data->win->term; #endif int i1 = 0; while (i1 < n) { struct widget_data *widget_data1 = widget_data + i1; int i2 = i1 + 1; int mw; while (i2 < n) { mw = 0; #ifdef CONFIG_UTF8 buttons_width(widget_data1, i2 - i1 + 1, NULL, &mw, term->utf8_cp); #else buttons_width(widget_data1, i2 - i1 + 1, NULL, &mw); #endif /* CONFIG_UTF8 */ if (mw <= w) i2++; else break; } mw = 0; #ifdef CONFIG_UTF8 buttons_width(widget_data1, i2 - i1, NULL, &mw, term->utf8_cp); #else buttons_width(widget_data1, i2 - i1, NULL, &mw); #endif /* CONFIG_UTF8 */ if (rw) int_bounds(rw, mw, w); if (!format_only) { int i; int p = x + (align == ALIGN_CENTER ? (w - mw) / 2 : 0); #ifdef CONFIG_UTF8 int button_lr_len = utf8_ptr2cells(BUTTON_LEFT, NULL) + utf8_ptr2cells(BUTTON_RIGHT, NULL); #endif /* CONFIG_UTF8 */ for (i = i1; i < i2; i++) { #ifdef CONFIG_UTF8 if (term->utf8_cp) set_box(&widget_data[i].box, p, *y, utf8_ptr2cells(widget_data[i].widget->text, NULL) + button_lr_len, BUTTON_HEIGHT); else #endif /* CONFIG_UTF8 */ set_box(&widget_data[i].box, p, *y, widget_data[i].widget->info.button.textlen + BUTTON_LR_LEN, BUTTON_HEIGHT); p += widget_data[i].box.width + BUTTON_HSPACING; } } *y += BUTTON_VSPACING + BUTTON_HEIGHT; i1 = i2; } }
static void do_html_select(unsigned char *attr, unsigned char *html, unsigned char *eof, unsigned char **end, struct html_context *html_context) { struct conv_table *ct = (struct conv_table *)html_context->special_f(html_context, SP_TABLE, NULL); struct form_control *fc; struct string lbl = NULL_STRING, orig_lbl = NULL_STRING; unsigned char **values = NULL; unsigned char **labels; unsigned char *name, *t_attr, *en; int namelen; int nnmi = 0; int order = 0; int preselect = -1; int group = 0; int i, max_width; int closing_tag; html_focusable(html_context, attr); init_menu(&lnk_menu); se: en = html; see: html = en; while (html < eof && *html != '<') html++; if (html >= eof) { abort: *end = html; if (lbl.source) done_string(&lbl); if (orig_lbl.source) done_string(&orig_lbl); if (values) { int j; for (j = 0; j < order; j++) mem_free_if(values[j]); mem_free(values); } destroy_menu(&lnk_menu); *end = en; return; } if (lbl.source) { unsigned char *q, *s = en; int l = html - en; while (l && isspace(s[0])) s++, l--; while (l && isspace(s[l-1])) l--; q = convert_string(ct, s, l, html_context->options->cp, CSM_DEFAULT, NULL, NULL, NULL); if (q) add_to_string(&lbl, q), mem_free(q); add_bytes_to_string(&orig_lbl, s, l); } if (html + 2 <= eof && (html[1] == '!' || html[1] == '?')) { html = skip_comment(html, eof); goto se; } if (parse_element(html, eof, &name, &namelen, &t_attr, &en)) { html++; goto se; } if (!namelen) goto see; if (name[0] == '/') { namelen--; if (!namelen) goto see; name++; closing_tag = 1; } else { closing_tag = 0; } if (closing_tag && !c_strlcasecmp(name, namelen, (const unsigned char *)"SELECT", 6)) { add_select_item(&lnk_menu, &lbl, &orig_lbl, values, order, nnmi); goto end_parse; } if (!c_strlcasecmp(name, namelen, (const unsigned char *)"OPTION", 6)) { add_select_item(&lnk_menu, &lbl, &orig_lbl, values, order, nnmi); if (!closing_tag) { unsigned char *value, *label; if (has_attr(t_attr, (unsigned char *)"disabled", html_context->doc_cp)) goto see; if (preselect == -1 && has_attr(t_attr, (unsigned char *)"selected", html_context->doc_cp)) preselect = order; value = get_attr_val(t_attr, (unsigned char *)"value", html_context->doc_cp); if (!mem_align_alloc(&values, order, order + 1, 0xFF)) goto abort; values[order++] = value; label = get_attr_val(t_attr, (unsigned char *)"label", html_context->doc_cp); if (label) new_menu_item(&lnk_menu, label, order - 1, 0); if (!value || !label) { init_string(&lbl); init_string(&orig_lbl); nnmi = !!label; } } goto see; } if (!c_strlcasecmp(name, namelen, (const unsigned char *)"OPTGROUP", 8)) { add_select_item(&lnk_menu, &lbl, &orig_lbl, values, order, nnmi); if (group) new_menu_item(&lnk_menu, NULL, -1, 0), group = 0; if (!closing_tag) { unsigned char *label; label = get_attr_val(t_attr, (unsigned char *)"label", html_context->doc_cp); if (!label) { label = stracpy((const unsigned char *)""); if (!label) goto see; } new_menu_item(&lnk_menu, label, -1, 0); group = 1; } } goto see; end_parse: *end = en; if (!order) goto abort; labels = (unsigned char **)mem_calloc(order, sizeof(unsigned char *)); if (!labels) goto abort; fc = init_form_control(FC_SELECT, attr, html_context); if (!fc) { mem_free(labels); goto abort; } fc->id = get_attr_val(attr, (unsigned char *)"id", html_context->doc_cp); fc->name = get_attr_val(attr, (unsigned char *)"name", html_context->doc_cp); fc->default_state = preselect < 0 ? 0 : preselect; fc->default_value = order ? stracpy(values[fc->default_state]) : stracpy((const unsigned char *)""); fc->nvalues = order; fc->values = values; fc->menu = detach_menu(&lnk_menu); fc->labels = labels; menu_labels(fc->menu, (unsigned char *)"", labels); put_chrs(html_context, (unsigned char *)"[", 1); html_stack_dup(html_context, ELEMENT_KILLABLE); format.form = fc; format.style.attr |= AT_BOLD; max_width = 0; for (i = 0; i < order; i++) { if (!labels[i]) continue; #ifdef CONFIG_UTF8 if (html_context->options->utf8) int_lower_bound(&max_width, utf8_ptr2cells(labels[i], NULL)); else #endif /* CONFIG_UTF8 */ int_lower_bound(&max_width, strlen((const char *)labels[i])); } for (i = 0; i < max_width; i++) put_chrs(html_context, (unsigned char *)"_", 1); pop_html_element(html_context); put_chrs(html_context, (unsigned char *)"]", 1); html_context->special_f(html_context, SP_CONTROL, fc); }