]> granicus.if.org Git - nethack/commitdiff
X11 fancy status coloring cleanup
authorPatR <rankin@nethack.org>
Tue, 26 Jan 2021 21:54:43 +0000 (13:54 -0800)
committerPatR <rankin@nethack.org>
Tue, 26 Jan 2021 21:54:43 +0000 (13:54 -0800)
Fix a couple of warnings and do some reformatting.

Also tracks current color and attributes for each status field
and only updates them if they're being changed instead of every
time the value changes.  Not very thoroughly tested so far.

The only attribute being supported is inverse but tty-style
status supports the full set.  Also, changed values are always
highlighted in inverse even if there is no highlight rule.
That should probably only apply when 'statushilites' is 0,
giving the old fancy status highlighting when regular hilites
are turned off.

win/X11/winstat.c

index bb82c91f4ec7a68f225bf4c42bf51acc6736ffff..c652804fc225d1d69fdb31ed638ee4fe8ac44aea 100644 (file)
@@ -107,8 +107,7 @@ static void FDECL(tt_reset_color, (int, int, unsigned long *));
 static void NDECL(tt_status_fixup);
 static Widget FDECL(create_tty_status_field, (int, int, Widget, Widget));
 static Widget FDECL(create_tty_status, (Widget, Widget));
-static void FDECL(update_fancy_status_field_with_hilites, (int, int, int));
-static void FDECL(update_fancy_status_field, (int));
+static void FDECL(update_fancy_status_field, (int, int, int));
 static void FDECL(update_fancy_status, (BOOLEAN_P));
 static Widget FDECL(create_fancy_status, (Widget, Widget));
 static void FDECL(destroy_fancy_status, (struct xwindow *));
@@ -173,31 +172,31 @@ static struct tt_condinfo {
     { BL_MASK_RIDE, "Ride" },
 };
 
+static const char *fancy_status_hilite_colors[] = {
+    "grey15",
+    "red3",
+    "dark green",
+    "saddle brown",
+    "blue",
+    "magenta3",
+    "dark cyan",
+    "web gray",
+    "",        /* NO_COLOR */
+    "orange",
+    "green3",
+    "goldenrod",
+    "royal blue",
+    "magenta",
+    "cyan",
+    "white",
+};
+
 static Widget X11_status_widget;
 static Widget X11_status_labels[MAXBLSTATS];
 static Widget X11_cond_labels[32]; /* Ugh */
 static XFontStruct *X11_status_font;
 static Pixel X11_status_fg, X11_status_bg;
 
-static const char* fancy_status_hilite_colors[] = {
-       "grey15",
-       "red3",
-       "dark green",
-       "saddle brown",
-       "blue",
-       "magenta3",
-       "dark cyan",
-       "web gray",
-       "",     /* NO_COLOR */
-       "orange",
-       "green3",
-       "goldenrod",
-       "royal blue",
-       "magenta",
-       "cyan",
-       "white"
-};
-
 struct xwindow *xw_status_win;
 
 static int
@@ -831,8 +830,8 @@ unsigned long *colormasks; /* bitmask of highlights for conditions */
 
 /*ARGSUSED*/
 static void
-X11_status_update_fancy(fld, ptr, chg, percent, color, colormasks)
-int fld, chg UNUSED, percent UNUSED, color;
+X11_status_update_fancy(fld, ptr, chg, percent, colrattr, colormasks)
+int fld, chg UNUSED, percent UNUSED, colrattr;
 genericptr_t ptr;
 unsigned long *colormasks;
 {
@@ -903,16 +902,25 @@ unsigned long *colormasks;
         if (changed_bits) {
             for (i = 0; i < SIZE(mask_to_fancyfield); i++)
                 if ((changed_bits & mask_to_fancyfield[i].mask) != 0L)
-                     update_fancy_status_field_with_hilites(mask_to_fancyfield[i].ff,
-                         condcolor(mask_to_fancyfield[i].mask, colormasks),
-                         condattr(mask_to_fancyfield[i].mask, colormasks));
+                    update_fancy_status_field(mask_to_fancyfield[i].ff,
+                            condcolor(mask_to_fancyfield[i].mask, colormasks),
+                            condattr(mask_to_fancyfield[i].mask, colormasks));
             old_condition_bits = X11_condition_bits; /* remember 'On' bits */
         }
     } else {
+        int colr, attr;
+
+#ifdef TEXTCOLOR
+        if ((colrattr & 0x00ff) >= CLR_MAX)
+            /* for !TEXTCOLOR, the following line is unconditional */
+#endif
+            colrattr = (colrattr & ~0x00ff) | NO_COLOR;
+        colr = colrattr & 0x00ff; /* guaranteed to be >= 0 and < CLR_MAX */
+        attr = (colrattr >> 8) & 0x00ff;
+
         for (i = 0; i < SIZE(bl_to_fancyfield); i++)
             if (bl_to_fancyfield[i].bl == fld) {
-                update_fancy_status_field_with_hilites(bl_to_fancyfield[i].ff,
-                    color & 0xf, color >> 8 & 0xff);
+                update_fancy_status_field(bl_to_fancyfield[i].ff, colr, attr);
                 break;
             }
     }
@@ -1216,9 +1224,9 @@ struct xwindow *wp;
 
 /*
  * This assumes several things:
- *     + Status has only 2 lines
- *     + That both lines are updated in succession in line order.
- *     + We didn't set stringInPlace on the widget.
+ *      + Status has only 2 lines
+ *      + That both lines are updated in succession in line order.
+ *      + We didn't set stringInPlace on the widget.
  */
 void
 adjust_status_fancy(wp, str)
@@ -1260,8 +1268,9 @@ struct X_status_value {
     int turn_count;     /* last time the value changed */
     boolean set;        /* if highlighted */
     boolean after_init; /* don't highlight on first change (init) */
-    boolean inverted_hilite; /* if highlighted due to hilite_status inverse rule */
+    boolean inverted_hilite; /* if highlit due to hilite_status inverse rule */
     Pixel default_fg;   /* what FG color it initialized with */
+    int colr, attr;     /* color and attribute */
 };
 
 /* valid type values */
@@ -1285,6 +1294,9 @@ static const struct f_overload *FDECL(ff_ovld_from_indx, (int));
 static void FDECL(hilight_label, (Widget));
 static void FDECL(update_val, (struct X_status_value *, long));
 static void FDECL(skip_cond_val, (struct X_status_value *));
+static void FDECL(update_color, (struct X_status_value *, int));
+static boolean FDECL(name_widget_has_label, (struct X_status_value *));
+static void FDECL(apply_hilite_attributes, (struct X_status_value *, int));
 static const char *FDECL(width_string, (int));
 static void FDECL(create_widget, (Widget, struct X_status_value *, int));
 static void FDECL(get_widths, (struct X_status_value *, int *, int *));
@@ -1303,53 +1315,67 @@ static Widget FDECL(init_info_form, (Widget, Widget, Widget));
  * - These must be in the same order as the F_foo numbers.
  */
 static struct X_status_value shown_stats[NUM_STATS] = {
-    { "",             SV_NAME,  (Widget) 0,  -1L, 0, FALSE, FALSE, FALSE, 0 }, /* 0 */
-
-    { "Strength",     SV_VALUE, (Widget) 0,  -1L, 0, FALSE, FALSE, FALSE, 0 }, /* 1*/
+    /* 0 */
+    { "",             SV_NAME,  (Widget) 0,  -1L, 0, FALSE, FALSE, FALSE, 0 },
+    /* 1 */
+    { "Strength",     SV_VALUE, (Widget) 0,  -1L, 0, FALSE, FALSE, FALSE, 0 },
     { "Dexterity",    SV_VALUE, (Widget) 0,  -1L, 0, FALSE, FALSE, FALSE, 0 },
     { "Constitution", SV_VALUE, (Widget) 0,  -1L, 0, FALSE, FALSE, FALSE, 0 },
     { "Intelligence", SV_VALUE, (Widget) 0,  -1L, 0, FALSE, FALSE, FALSE, 0 },
-    { "Wisdom",       SV_VALUE, (Widget) 0,  -1L, 0, FALSE, FALSE, FALSE, 0 }, /* 5*/
+    /* 5 */
+    { "Wisdom",       SV_VALUE, (Widget) 0,  -1L, 0, FALSE, FALSE, FALSE, 0 },
     { "Charisma",     SV_VALUE, (Widget) 0,  -1L, 0, FALSE, FALSE, FALSE, 0 },
-
-    { "",             SV_LABEL, (Widget) 0,  -1L, 0, FALSE, FALSE, FALSE, 0 }, /*NAME*/
-    { "",             SV_LABEL, (Widget) 0,  -1L, 0, FALSE, FALSE, FALSE, 0 }, /*DLEVEL*/
+    /* F_NAME: 7 */
+    { "",             SV_LABEL, (Widget) 0,  -1L, 0, FALSE, FALSE, FALSE, 0 },
+    /* F_DLEVEL: 8 */
+    { "",             SV_LABEL, (Widget) 0,  -1L, 0, FALSE, FALSE, FALSE, 0 },
     { "Gold",         SV_VALUE, (Widget) 0,  -1L, 0, FALSE, FALSE, FALSE, 0 },
-    { "Hit Points",   SV_VALUE, (Widget) 0,  -1L, 0, FALSE, FALSE, FALSE, 0 }, /*10*/
+    /* F_HP: 10 */
+    { "Hit Points",   SV_VALUE, (Widget) 0,  -1L, 0, FALSE, FALSE, FALSE, 0 },
     { "Max HP",       SV_VALUE, (Widget) 0,  -1L, 0, FALSE, FALSE, FALSE, 0 },
     { "Power",        SV_VALUE, (Widget) 0,  -1L, 0, FALSE, FALSE, FALSE, 0 },
     { "Max Power",    SV_VALUE, (Widget) 0,  -1L, 0, FALSE, FALSE, FALSE, 0 },
     { "Armor Class",  SV_VALUE, (Widget) 0, 256L, 0, FALSE, FALSE, FALSE, 0 },
-    { "Xp Level",     SV_VALUE, (Widget) 0,  -1L, 0, FALSE, FALSE, FALSE, 0 }, /*15*/
-    /*{ "Hit Dice",   SV_VALUE, (Widget) 0,  -1L, 0, FALSE, FALSE, FALSE, 0 }, ==15*/
+    /* F_XP_LEVL: 15 */
+    { "Xp Level",     SV_VALUE, (Widget) 0,  -1L, 0, FALSE, FALSE, FALSE, 0 },
+    /* also 15 (overloaded field) */
+    /*{ "Hit Dice",   SV_VALUE, (Widget) 0,  -1L, 0, FALSE, FALSE, FALSE, 0},*/
+    /* F_EXP_PTS: 16 (optionally displayed) */
     { "Exp Points",   SV_VALUE, (Widget) 0,  -1L, 0, FALSE, FALSE, FALSE, 0 },
     { "Alignment",    SV_VALUE, (Widget) 0,  -2L, 0, FALSE, FALSE, FALSE, 0 },
+    /* 18, optionally displayed */
     { "Time",         SV_VALUE, (Widget) 0,  -1L, 0, FALSE, FALSE, FALSE, 0 },
-    { "Score",        SV_VALUE, (Widget) 0,  -1L, 0, FALSE, FALSE, FALSE, 0 }, /*19*/
-
-    { "",             SV_NAME,  (Widget) 0,  -1L, 0, FALSE, TRUE, FALSE, 0 }, /*20 */
-    { "",             SV_NAME,  (Widget) 0,   0L, 0, FALSE, TRUE, FALSE, 0 }, /*ENCMBR*/
+    /* 19, condtionally present, optionally displayed when present */
+    { "Score",        SV_VALUE, (Widget) 0,  -1L, 0, FALSE, FALSE, FALSE, 0 },
+    /* F_HUNGER: 20 (blank if 'normal') */
+    { "",             SV_NAME,  (Widget) 0,  -1L, 0, FALSE, TRUE, FALSE, 0 },
+    /* F_ENCUMBER: 21 (blank if unencumbered) */
+    { "",             SV_NAME,  (Widget) 0,   0L, 0, FALSE, TRUE, FALSE, 0 },
     { "Trapped",      SV_NAME,  (Widget) 0,   0L, 0, FALSE, TRUE, FALSE, 0 },
     { "Tethered",     SV_NAME,  (Widget) 0,   0L, 0, FALSE, TRUE, FALSE, 0 },
     { "Levitating",   SV_NAME,  (Widget) 0,   0L, 0, FALSE, TRUE, FALSE, 0 },
-    { "Flying",       SV_NAME,  (Widget) 0,   0L, 0, FALSE, TRUE, FALSE, 0 }, /*25*/
+    /* 25 */
+    { "Flying",       SV_NAME,  (Widget) 0,   0L, 0, FALSE, TRUE, FALSE, 0 },
     { "Riding",       SV_NAME,  (Widget) 0,   0L, 0, FALSE, TRUE, FALSE, 0 },
-
-    { "Grabbed!",     SV_NAME,  (Widget) 0,   0L, 0, FALSE, TRUE, FALSE, 0 }, /*27*/
-    { "Petrifying",   SV_NAME,  (Widget) 0,   0L, 0, FALSE, TRUE, FALSE, 0 }, /*STONE*/
+    { "Grabbed!",     SV_NAME,  (Widget) 0,   0L, 0, FALSE, TRUE, FALSE, 0 },
+    /* F_STONE: 28 */
+    { "Petrifying",   SV_NAME,  (Widget) 0,   0L, 0, FALSE, TRUE, FALSE, 0 },
     { "Slimed",       SV_NAME,  (Widget) 0,   0L, 0, FALSE, TRUE, FALSE, 0 },
-    { "Strangled",    SV_NAME,  (Widget) 0,   0L, 0, FALSE, TRUE, FALSE, 0 }, /*30*/
+    /* 30 */
+    { "Strangled",    SV_NAME,  (Widget) 0,   0L, 0, FALSE, TRUE, FALSE, 0 },
     { "Food Pois",    SV_NAME,  (Widget) 0,   0L, 0, FALSE, TRUE, FALSE, 0 },
     { "Term Ill",     SV_NAME,  (Widget) 0,   0L, 0, FALSE, TRUE, FALSE, 0 },
-    { "Sinking",      SV_NAME,  (Widget) 0,   0L, 0, FALSE, TRUE, FALSE, 0 }, /*LAVA*/
-
-    { "Held",         SV_NAME,  (Widget) 0,   0L, 0, FALSE, TRUE, FALSE, 0 }, /*34*/
-    { "Holding",      SV_NAME,  (Widget) 0,   0L, 0, FALSE, TRUE, FALSE, 0 }, /*35*/
+    /* F_IN_LAVA: 33 */
+    { "Sinking",      SV_NAME,  (Widget) 0,   0L, 0, FALSE, TRUE, FALSE, 0 },
+    { "Held",         SV_NAME,  (Widget) 0,   0L, 0, FALSE, TRUE, FALSE, 0 },
+    /* 35 */
+    { "Holding",      SV_NAME,  (Widget) 0,   0L, 0, FALSE, TRUE, FALSE, 0 },
     { "Blind",        SV_NAME,  (Widget) 0,   0L, 0, FALSE, TRUE, FALSE, 0 },
     { "Deaf",         SV_NAME,  (Widget) 0,   0L, 0, FALSE, TRUE, FALSE, 0 },
     { "Stunned",      SV_NAME,  (Widget) 0,   0L, 0, FALSE, TRUE, FALSE, 0 },
     { "Confused",     SV_NAME,  (Widget) 0,   0L, 0, FALSE, TRUE, FALSE, 0 },
-    { "Hallucinat",   SV_NAME,  (Widget) 0,   0L, 0, FALSE, TRUE, FALSE, 0 }, /*40*/
+    /* F_HALLU: 40 (full spelling truncated due to space limitations) */
+    { "Hallucinat",   SV_NAME,  (Widget) 0,   0L, 0, FALSE, TRUE, FALSE, 0 },
 };
 /*
  * The following are supported by the core but not yet handled here:
@@ -1594,7 +1620,7 @@ long new_value;
             /* core won't call status_update() for Exp when it hasn't changed
                so do so ourselves (to get Exp_shown flag to match display) */
             if (force_update)
-                update_fancy_status_field(F_EXP_PTS);
+                update_fancy_status_field(F_EXP_PTS, NO_COLOR, HL_UNDEF);
         }
 
         if (attr_rec->last_value == new_value && !force_update) /* same */
@@ -1648,26 +1674,26 @@ long new_value;
      * or changing to not-hungry or not-encumbered, there's nothing to
      * highlight because the field becomes blank.
      */
-       if (attr_rec->after_init) {
-               /* toggle if not highlighted and just set to nonblank or if
-                  already highlighted and just set to blank */
-               if (attr_rec != &shown_stats[F_TIME] && !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);
-                       }
-                       attr_rec->set = !attr_rec->set;
-               }
-               attr_rec->turn_count = 0;
-       } else {
-               XtSetArg(args[0], XtNforeground, &attr_rec->default_fg);
-               XtGetValues(attr_rec->w, args, ONE);
-               attr_rec->after_init = TRUE;
-       }
+    if (attr_rec->after_init) {
+        /* toggle if not highlighted and just set to nonblank or if
+           already highlighted and just set to blank */
+        if (attr_rec != &shown_stats[F_TIME] && !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);
+            }
+            attr_rec->set = !attr_rec->set;
+        }
+        attr_rec->turn_count = 0;
+    } else {
+        XtSetArg(args[0], XtNforeground, &attr_rec->default_fg);
+        XtGetValues(attr_rec->w, args, ONE);
+        attr_rec->after_init = TRUE;
+    }
 }
 
 /* overloaded condition is being cleared without going through update_val()
@@ -1692,32 +1718,35 @@ update_color(sv, color)
 struct X_status_value *sv;
 int color;
 {
-    Pixel pixel;
+    Pixel pixel = 0;
     Arg args[1];
     XrmValue source;
     XrmValue dest;
+    Widget w = (sv->type == SV_LABEL || sv->type == SV_NAME) ? sv->w
+               : get_value_widget(sv->w);
 
-    Widget w = (sv->type == SV_LABEL || sv->type == SV_NAME ? sv->w : get_value_widget(sv->w));
     if (color == NO_COLOR) {
         if (sv->after_init)
             pixel = sv->default_fg;
-    }
-    else {
-        source.size = strlen(fancy_status_hilite_colors[color]) + 1;
-        source.addr = (char *)fancy_status_hilite_colors[color];
-        dest.size = sizeof(Pixel);
-        dest.addr = (XPointer)&pixel;
-        if (!XtConvertAndStore(w, XtRString, &source, XtRPixel, &dest))
-            pixel = 0;
+        sv->colr = NO_COLOR;
+    else {
+        source.addr = (XPointer) fancy_status_hilite_colors[color];
+        source.size = (unsigned int) strlen((const char *) source.addr) + 1;
+        dest.size = (unsigned int) sizeof (Pixel);
+        dest.addr = (XPointer) &pixel;
+        if (XtConvertAndStore(w, XtRString, &source, XtRPixel, &dest))
+            sv->colr = color;
     }
     if (pixel != 0) {
-        char *arg_name = (sv->set || sv->inverted_hilite ? XtNbackground : XtNforeground);
+        char *arg_name = (sv->set || sv->inverted_hilite) ? XtNbackground
+                         : XtNforeground;
+
         XtSetArg(args[0], arg_name, pixel);
         XtSetValues(w, args, ONE);
     }
 }
 
-boolean
+static boolean
 name_widget_has_label(sv)
 struct X_status_value *sv;
 {
@@ -1734,11 +1763,9 @@ apply_hilite_attributes(sv, attributes)
 struct X_status_value *sv;
 int attributes;
 {
-    boolean attr_inversion
-        = HL_INVERSE & attributes
-        && (sv->type != SV_NAME || name_widget_has_label(sv))
-        ? TRUE
-        : FALSE;
+    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;
@@ -1749,6 +1776,7 @@ int attributes;
                 hilight_label(sv->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()
@@ -1773,7 +1801,7 @@ int attributes;
  * [**] HD is shown instead of level and exp if Upolyd.
  */
 static void
-update_fancy_status_field_with_hilites(i, color, attributes)
+update_fancy_status_field(i, color, attributes)
 int i, color, attributes;
 {
     struct X_status_value *sv = &shown_stats[i];
@@ -1954,17 +1982,10 @@ int i, color, attributes;
         }
     }
     update_val(sv, val);
-    if (color >= 0 )
+    if (color != sv->colr)
         update_color(sv, color);
-    if (attributes >=0 )
-           apply_hilite_attributes(sv, attributes);
-}
-
-static void
-update_fancy_status_field(i)
-int i;
-{
-    update_fancy_status_field_with_hilites(i, -1, -1);
+    if (attributes != sv->attr)
+        apply_hilite_attributes(sv, attributes);
 }
 
 /* fully update status after bl_flush or window resize */
@@ -1988,7 +2009,7 @@ boolean force_update;
            the no longer displayed field; we're a bit more conservative
            than that and do this when toggling on as well as off */
         for (i = 0; i < NUM_STATS; i++)
-            update_fancy_status_field(i);
+            update_fancy_status_field(i, NO_COLOR, HL_UNDEF);
         old_condition_bits = X11_condition_bits;
 
         old_upolyd = Upolyd;