From 514669823bfc22daa23e6fe3559803bf6c78458c Mon Sep 17 00:00:00 2001 From: Ray Chason Date: Tue, 11 Aug 2026 15:28:34 -0400 Subject: [PATCH] Implement bold, dim, italic, inverse, underline Didn't get everything the last time. --- win/X11/winlabel.c | 56 ++++++++++++++++++++++++++------- win/X11/winstat.c | 77 +++++++++------------------------------------- win/X11/winval.c | 8 ----- 3 files changed, 59 insertions(+), 82 deletions(-) diff --git a/win/X11/winlabel.c b/win/X11/winlabel.c index a9e56d915..e94bb7cc8 100644 --- a/win/X11/winlabel.c +++ b/win/X11/winlabel.c @@ -25,6 +25,7 @@ typedef struct WidgetData { /* Attributes */ unsigned attrs; + boolean highlight; /* Fonts for italic, bold and bold-italic */ XFontStruct *font[4]; /* To use the fonts */ @@ -138,6 +139,16 @@ X11_set_attrs(Widget w, unsigned attrs) } } +void +X11_set_highlight(Widget w, boolean highlight) +{ + WidgetData *data = get_widget_data(w); + if (data != NULL) { + data->highlight = highlight; + update_label(w, data); + } +} + void X11_set_percent(Widget w, unsigned percent, Pixel color) { @@ -232,16 +243,23 @@ update_label(Widget w, WidgetData *data) XtSetArg(args[num_args], XtNheight, &height); num_args++; XtGetValues(w, args, num_args); } - width = max(width, 1); - height = max(height, 1); + if (width < 2 || height < 2) { + /* Pixmap must not have zero size, or a crash will ensue; + minimum size 2 simplifies border logic */ + width = max(width, 2); + height = max(height, 2); + fgpixel = bgpixel; + } - /* Use the full width of the widget if a percentage bar is set */ - if (data->percent != 0) { - Dimension wwidth; + /* Use the full width of the widget if a percentage bar is set or inverse + is in effect */ + if (data->percent != 0 || (attrs & HL_INVERSE) != 0 || data->highlight) { + Dimension wwidth, iwidth; num_args = 0; XtSetArg(args[num_args], XtNwidth, &wwidth); num_args++; + XtSetArg(args[num_args], XtNinternalWidth, &iwidth); num_args++; XtGetValues(w, args, num_args); - width = max(width, wwidth); + width = max(width, wwidth - iwidth*2); } /* Create the pixmap */ @@ -253,7 +271,7 @@ update_label(Widget w, WidgetData *data) for (unsigned pass = 0; pass < 2; ++pass) { XGCValues values; - if (attrs & HL_INVERSE) { + if (!!(attrs & HL_INVERSE) ^ !!data->highlight) { values.foreground = bgpixel; values.background = fgpixel; } else { @@ -280,7 +298,11 @@ update_label(Widget w, WidgetData *data) XSetClipRectangles(display, ggc, 0, 0, &clip, 1, Unsorted); } - XSetForeground(display, ggc, values.background); + /* Draw a border for inverse and highlight together */ + /* Otherwise, fill with the background color */ + if (!((attrs & HL_INVERSE) && data->highlight)) { + XSetForeground(display, ggc, values.background); + } XFillRectangle(display, new_pixmap, ggc, 0, 0, width, height); XSetForeground(display, ggc, values.foreground); @@ -314,9 +336,16 @@ update_label(Widget w, WidgetData *data) } /* Render the line */ - XDrawString(display, new_pixmap, ggc, - x, y, - label + i, line2); + XDrawImageString(display, new_pixmap, ggc, + x, y, + label + i, line2); + + /* Draw the underline if requested */ + if (attrs & HL_ULINE) { + XDrawLine(display, new_pixmap, ggc, + x, y, + x + lwidth - 1, y); + } y += font->ascent + font->descent; @@ -327,6 +356,11 @@ update_label(Widget w, WidgetData *data) } } + /* Ensure a one-pixel border if both inverse and highlight */ + if ((attrs & HL_INVERSE) && data->highlight) { + XDrawRectangle(display, new_pixmap, ggc, 0, 0, width-1, height-1); + } + XtReleaseGC(w, ggc); /* Set up to display the percent bar on the second pass */ diff --git a/win/X11/winstat.c b/win/X11/winstat.c index 64ca38a02..e08e968f5 100644 --- a/win/X11/winstat.c +++ b/win/X11/winstat.c @@ -1223,12 +1223,10 @@ struct f_overload { static const struct f_overload *ff_ovld_from_mask(unsigned long); static const struct f_overload *ff_ovld_from_indx(int); -static void hilight_label(Widget); static void update_val(struct X_status_value *, long); static void skip_cond_val(struct X_status_value *); static void update_color(struct X_status_value *, int); static Pixel color_to_pixel(Widget, int); -static boolean name_widget_has_label(struct X_status_value *); static void apply_hilite_attributes(struct X_status_value *, int); static const char *width_string(int); static void create_widget(Widget, struct X_status_value *, int); @@ -1415,18 +1413,6 @@ null_out_status(void) } } -/* this is almost an exact duplicate of hilight_value() */ -static void -hilight_label(Widget w) /* label widget */ -{ - /* - * This predates STATUS_HILITES. - * It is used to show any changed item in inverse and gets - * reset on the next turn. - */ - swap_fg_bg(w); -} - DISABLE_WARNING_FORMAT_NONLITERAL static void @@ -1631,14 +1617,10 @@ update_val(struct X_status_value *attr_rec, long new_value) if (attr_rec != &shown_stats[F_TIME] && attr_rec != &shown_stats[F_VERS] && !attr_rec->set ^ !*buf) { - /* But don't hilite if inverted from status_hilite since - it will already be hilited by apply_hilite_attributes(). */ - if (!attr_rec->inverted_hilite) { - if (attr_rec->type == SV_VALUE) - hilight_value(attr_rec->w); - else - hilight_label(attr_rec->w); - } + if (attr_rec->type == SV_VALUE) + X11_set_highlight(get_value_widget(attr_rec->w), TRUE); + else + X11_set_highlight(attr_rec->w, TRUE); attr_rec->set = !attr_rec->set; } attr_rec->turn_count = 0; @@ -1664,7 +1646,7 @@ skip_cond_val(struct X_status_value *sv) also requested to be highlighted, it used its own copy of 'set' but the same widget so the highlighting got toggled off; this will turn in back on in that exceptional case */ - hilight_label(sv->w); + X11_set_highlight(sv->w, FALSE); sv->set = FALSE; } } @@ -1686,10 +1668,7 @@ update_color(struct X_status_value *sv, int color) sv->colr = color; } if (pixel != 0) { - char *arg_name = (sv->set || sv->inverted_hilite) ? XtNbackground - : XtNforeground; - - XtSetArg(args[0], arg_name, pixel); + XtSetArg(args[0], XtNforeground, pixel); XtSetValues(w, args, ONE); X11_update_label(w); } @@ -1719,38 +1698,14 @@ color_to_pixel(Widget w, int color) return pixel; } -static boolean -name_widget_has_label(struct X_status_value *sv) -{ - Arg args[1]; - const char *label; - - XtSetArg(args[0], XtNlabel, &label); - XtGetValues(sv->w, args, ONE); - return (*label != '\0'); -} - static void apply_hilite_attributes(struct X_status_value *sv, int attributes) { - boolean attr_inversion = ((HL_INVERSE & attributes) - && (sv->type != SV_NAME - || name_widget_has_label(sv))); - - if (sv->inverted_hilite != attr_inversion) { - sv->inverted_hilite = attr_inversion; - if (!sv->set) { - if (sv->type == SV_VALUE) - hilight_value(sv->w); - else - hilight_label(sv->w); - } + Widget w = sv->w; + if (sv->type == SV_VALUE) { + w = get_value_widget(w); } - sv->attr = attributes; - /* Could possibly add more attributes here: HL_ATTCLR_DIM, - HL_ATTCLR_BLINK, HL_ATTCLR_ULINE, and HL_ATTCLR_BOLD. If so, - extract the above into its own function apply_hilite_inverse() - and each other attribute into its own to keep the code clean. */ + X11_set_attrs(w, attributes); } static void @@ -2021,14 +1976,10 @@ check_turn_events(void) continue; if (sv->turn_count++ >= hilight_time) { - /* unhighlights by toggling a highlighted item back off again, - unless forced inverted by a status_hilite rule */ - if (!sv->inverted_hilite) { - if (sv->type == SV_VALUE) - hilight_value(sv->w); - else - hilight_label(sv->w); - } + if (sv->type == SV_VALUE) + X11_set_highlight(get_value_widget(sv->w), FALSE); + else + X11_set_highlight(sv->w, FALSE); sv->set = FALSE; } } diff --git a/win/X11/winval.c b/win/X11/winval.c index daea9812d..59a2c3a5b 100644 --- a/win/X11/winval.c +++ b/win/X11/winval.c @@ -152,14 +152,6 @@ get_value_width(Widget w) return (int) width; } -/* Swap foreground and background colors (this is the best I can do with */ -/* a label widget, unless I can get some init hook in there). */ -void -hilight_value(Widget w) -{ - swap_fg_bg(get_value_widget(w)); -} - /* Swap the foreground and background colors of the given widget */ void swap_fg_bg(Widget w)