From cd094b28a3b17793d689f1fd7ea66e6b82c9f413 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sat, 7 May 2022 08:23:38 +0100 Subject: [PATCH] Allow CTRL_TEXT controls to be non-wrapping. This is for cases where they're presenting information to the user that wouldn't wrap sensibly anyway (such as an SSH key fingerprint which is mostly all one word), and in which newlines might be significant. On GTK, the implementing widget is still a GtkLabel, but without the wrap flag set, and wrapped in a GtkScrolledWindow in case the text is too wide to fit. On Windows, I've switched to using an edit box instead of a static text control, making it readonly, and borderless via my existing MakeDlgItemBorderless helper function. This doesn't get you an actual scrollbar, but it does mean you can scroll left and right by dragging with the mouse. --- dialog.c | 1 + dialog.h | 8 ++++++++ unix/dialog.c | 12 +++++++++++- windows/controls.c | 34 ++++++++++++++++++++-------------- windows/platform.h | 2 +- 5 files changed, 41 insertions(+), 16 deletions(-) diff --git a/dialog.c b/dialog.c index 13317833..04bc0d3c 100644 --- a/dialog.c +++ b/dialog.c @@ -427,6 +427,7 @@ dlgcontrol *ctrl_text(struct controlset *s, const char *text, { dlgcontrol *c = ctrl_new(s, CTRL_TEXT, helpctx, NULL, P(NULL)); c->label = dupstr(text); + c->text.wrap = true; return c; } diff --git a/dialog.h b/dialog.h index 45b4cde7..cc483328 100644 --- a/dialog.h +++ b/dialog.h @@ -426,6 +426,14 @@ struct dlgcontrol { struct { /* for CTRL_FONTSELECT */ char shortcut; } fontselect; + struct { /* for CTRL_TEXT */ + /* + * If this is true (the default), the text will wrap on to + * multiple lines. If false, it will stay on the same + * line, with a horizontal scrollbar if necessary. + */ + bool wrap; + } text; }; }; diff --git a/unix/dialog.c b/unix/dialog.c index aa547aa7..9f1d061d 100644 --- a/unix/dialog.c +++ b/unix/dialog.c @@ -2509,7 +2509,17 @@ GtkWidget *layout_ctrls( gtk_label_set_selectable(GTK_LABEL(w), true); gtk_widget_set_can_focus(w, false); align_label_left(GTK_LABEL(w)); - gtk_label_set_line_wrap(GTK_LABEL(w), true); + gtk_label_set_line_wrap(GTK_LABEL(w), ctrl->text.wrap); + if (!ctrl->text.wrap) { + gtk_widget_show(uc->text); + w = gtk_scrolled_window_new(NULL, NULL); + gtk_container_set_border_width(GTK_CONTAINER(w), 0); + gtk_container_add(GTK_CONTAINER(w), uc->text); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(w), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_NEVER); + gtk_widget_set_can_focus(w, false); + } break; } diff --git a/windows/controls.c b/windows/controls.c index d0de4674..c0159510 100644 --- a/windows/controls.c +++ b/windows/controls.c @@ -165,7 +165,7 @@ void endbox(struct ctlpos *cp) /* * A static line, followed by a full-width edit box. */ -void editboxfw(struct ctlpos *cp, bool password, char *text, +void editboxfw(struct ctlpos *cp, bool password, bool readonly, char *text, int staticid, int editid) { RECT r; @@ -183,7 +183,8 @@ void editboxfw(struct ctlpos *cp, bool password, char *text, r.bottom = EDITHEIGHT; doctl(cp, r, "EDIT", WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL | - (password ? ES_PASSWORD : 0), + (password ? ES_PASSWORD : 0) | + (readonly ? ES_READONLY : 0), WS_EX_CLIENTEDGE, "", editid); cp->ypos += EDITHEIGHT + GAPBETWEEN; } @@ -1525,18 +1526,23 @@ void winctrl_layout(struct dlgparam *dp, struct winctrls *wc, * switching on its type. */ switch (ctrl->type) { - case CTRL_TEXT: { - char *wrapped, *escaped; - int lines; - num_ids = 1; - wrapped = staticwrap(&pos, cp->hwnd, - ctrl->label, &lines); - escaped = shortcut_escape(wrapped, NO_SHORTCUT); - statictext(&pos, escaped, lines, base_id); - sfree(escaped); - sfree(wrapped); + case CTRL_TEXT: + if (ctrl->text.wrap) { + char *wrapped, *escaped; + int lines; + num_ids = 1; + wrapped = staticwrap(&pos, cp->hwnd, + ctrl->label, &lines); + escaped = shortcut_escape(wrapped, NO_SHORTCUT); + statictext(&pos, escaped, lines, base_id); + sfree(escaped); + sfree(wrapped); + } else { + editboxfw(&pos, false, true, NULL, 0, base_id); + SetDlgItemText(pos.hwnd, base_id, ctrl->label); + MakeDlgItemBorderless(pos.hwnd, base_id); + } break; - } case CTRL_EDITBOX: num_ids = 2; /* static, edit */ escaped = shortcut_escape(ctrl->label, @@ -1547,7 +1553,7 @@ void winctrl_layout(struct dlgparam *dp, struct winctrls *wc, combobox(&pos, escaped, base_id, base_id+1); else - editboxfw(&pos, ctrl->editbox.password, escaped, + editboxfw(&pos, ctrl->editbox.password, false, escaped, base_id, base_id+1); } else { if (ctrl->editbox.has_list) { diff --git a/windows/platform.h b/windows/platform.h index 11103511..4e3b63f1 100644 --- a/windows/platform.h +++ b/windows/platform.h @@ -437,7 +437,7 @@ HWND doctl(struct ctlpos *cp, RECT r, void bartitle(struct ctlpos *cp, char *name, int id); void beginbox(struct ctlpos *cp, char *name, int idbox); void endbox(struct ctlpos *cp); -void editboxfw(struct ctlpos *cp, bool password, char *text, +void editboxfw(struct ctlpos *cp, bool password, bool readonly, char *text, int staticid, int editid); void radioline(struct ctlpos *cp, char *text, int id, int nacross, ...); void bareradioline(struct ctlpos *cp, int nacross, ...);