]> granicus.if.org Git - nethack/commitdiff
Hilite Status: Improved
authorPasi Kallinen <paxed@alt.org>
Tue, 26 Sep 2017 07:04:19 +0000 (10:04 +0300)
committerPasi Kallinen <paxed@alt.org>
Tue, 26 Sep 2017 07:04:25 +0000 (10:04 +0300)
Allow defining multiple stops per field. Add hitpointbar.

37 files changed:
doc/Guidebook.mn
doc/Guidebook.tex
doc/fixes36.1
doc/window.doc
include/botl.h
include/config.h
include/decl.h
include/extern.h
include/flag.h
include/winprocs.h
include/wintty.h
src/allmain.c
src/botl.c
src/decl.c
src/end.c
src/files.c
src/hacklib.c
src/options.c
src/polyself.c
src/save.c
src/windows.c
sys/amiga/winami.c
sys/wince/mswproc.c
sys/winnt/nttty.c
util/makedefs.c
win/Qt/qt_win.cpp
win/X11/winX.c
win/chain/wc_chainin.c
win/chain/wc_chainout.c
win/chain/wc_trace.c
win/gem/wingem.c
win/gnome/gnbind.c
win/tty/wintty.c
win/win32/mhmsg.h
win/win32/mhstatus.c
win/win32/mswproc.c
win/win32/winMS.h

index 5dd00e1e0a5523bef26d53c1eec5cab0e86b4dfc..c61d0c05f8d1e3bda7e9640b50f777f53e2f761e 100644 (file)
@@ -2567,6 +2567,9 @@ The behavior of this option depends on the type of windowing you use.
 In text windowing, text highlighting or inverse video is often used;
 with tiles, generally displays a small plus-symbol beside the object
 on the top of the pile.
+.lp hitpointbar
+Show a hit point bar graph behind your name and title.
+Only available for TTY, and only when statushilites is on.
 .lp horsename
 Name your starting horse (ex. ``horsename:Trigger'').
 Cannot be set with the `O' command.
@@ -2910,7 +2913,8 @@ attack to which it is resistant (default on).  Persistent.
 .lp standout
 Boldface monsters and ``\fB--More--\fP'' (default off).  Persistent.
 .lp statushilites
-Enable coloring of status fields (default off).
+Controls how many turns status hilite behaviors highlight
+the field. If negated or set to zero, disables status hiliting.
 See ``Configuring Status Hilites'' for further information.
 .lp status_updates
 Allow updates to the status lines at the bottom of the screen (default true).
@@ -3479,17 +3483,22 @@ Your copy of NetHack may have been compiled with support for ``Status Hilites''.
 If so, you can customize your game display by setting thresholds to
 change the color or appearance of fields in the status display.
 .pg
+The format for defining status colors is:
+.si
+.lp "OPTION=hilite_status: field-name/behavior/color&attributes"
+.ei
+.pg
 For example, the following line in your config file will cause
 the hitpoints field to display in the color red if your hitpoints
 drop to or below a threshold of 30%:
 .si
-.lp "OPTION=hilite_status: hitpoints/30%/red/normal"
+.lp "OPTION=hilite_status: hitpoints/<30%/red/normal"
 .ei
 .pg
 For another example, the following line in your config file will cause
 wisdom to be displayed red if it drops and green if it rises.
 .si
-.lp "OPTION=hilite_status: wisdom/updown/red/green"
+.lp "OPTION=hilite_status: wisdom/down/red/up/green"
 .ei
 .pg
 You can adjust the display of the following status fields:
@@ -3508,18 +3517,73 @@ experience      condition
 .\"TABLE_END  Do not delete this line.
 .TE
 .lp ""
+The pseudo-field `characteristics' can be used to set all six
+of Str, Dex, Con, Int, Wis, and Cha at once.  `HD' is `hit dice',
+an approximation of experience level displayed when polymorphed.
+`experience', `time', and `score' are conditionally displayed
+depending upon your other option settings.
+.lp ""
+Instead of a behavior, `condition' takes the following condition flags:
+stone, slime, strngl, foodpois, termill, blind, deaf, stun, conf, hallu,
+lev, fly, and ride.  You can use `major_troubles' as an alias
+for stone through termill, `minor_troubles' for blind through hallu,
+`movement' for lev, fly, and ride, and `all' for every condition.
+.lp ""
+Allowed behaviors are "always", "up", "down", "changed", a
+percentage or absolute number threshold, or a text to match against.
+.si
+.lp "*"
+"always" will set the default attributes for that field.
+.lp "*"
+"up" and "down" set the field attributes for when the field
+value changes upwards or downwards. This attribute times out after
+statushilites turns.
+.lp "*"
+"changed" sets the field attribute for when the field value
+changes. This attribute times out after statushilites turns.
+.lp "*"
+percentage sets the field attribute when the field value
+matches the percentage. If the percentage is prefixed with '<'
+or '>', it also matches when value is below or above the percentage.
+Only valid for `power' and `hitpoints' fields.
+.lp "*"
+absolute value sets the attribute when the field value
+matches that number. If the number is prefixed with '<'
+or '>', it also matches when value is below or above.
+.lp "*"
+text match sets the attribute when the field value
+matches the text. Text matches can only be used for `alignment',
+`carrying-capacity', and `dungeon-level'.
+.ei
+.lp ""
 Allowed colors are black, red, green, brown, blue, magenta, cyan, gray,
 orange, lightgreen, yellow, lightblue, lightmagenta, lightcyan, and white.
 .lp ""
-Allowed attributes are bold, inverse, normal.
+Allowed attributes are bold, inverse, underline, blink, dim, and normal.
 Note that the platform used may interpret the attributes any way it
 wants.
 .lp ""
-Behaviours can occur based on percentage thresholds, updown, or absolute values.
 The in-game options menu can help you determine the correct syntax for a
 config file.
 .lp ""
-The whole feature can be disabled by setting option statushilites off.
+The whole feature  can  be  disabled  by  setting  option
+statushilites to 0.
+.lp ""
+Example hilites:
+.sd
+.si
+OPTION=hilite_status: gold/up/yellow/down/brown
+OPTION=hilite_status: characteristics/up/green/down/red
+OPTION=hilite_status: hitpoints/100%/gray&normal
+OPTION=hilite_status: hitpoints/<100%/green&normal
+OPTION=hilite_status: hitpoints/<66%/yellow&normal
+OPTION=hilite_status: hitpoints/<50%/orange&normal
+OPTION=hilite_status: hitpoints/<33%/red&bold
+OPTION=hilite_status: hitpoints/<15%/red&inverse
+OPTION=hilite_status: condition/major/orange&inverse
+OPTION=hilite_status: condition/lev+fly/red&inverse
+.ei
+.ed
 .pg
 .hn 2
 Modifying NetHack Symbols
index edd7f999557493b7f023f9262a4b82d53d2ea258..8c778da64ecc67e04c68e0fd4cd80dfd9fbc5ab3 100644 (file)
@@ -3141,6 +3141,10 @@ on the top of the pile.
 Name your starting horse (ex.\ ``{\tt horsename:Trigger}'').
 Cannot be set with the `{\tt O}' command.
 %.lp
+\item[\ib{hitpointbar}]
+Show a hit point bar graph behind your name and title.
+Only available for TTY, and only when statushilites is on.
+%.lp
 \item[\ib{ignintr}]
 Ignore interrupt signals, including breaks (default off).  Persistent.
 %.lp
@@ -3535,7 +3539,8 @@ attack to which it is resistant (default on).  Persistent.
 Boldface monsters and ``{\tt --More--}'' (default off).  Persistent.
 %.lp
 \item[\ib{statushilites}]
-Enable coloring of status fields (default off).
+Controls how many turns status hilite behaviors highlight
+the field. If negated or set to zero, disables status hiliting.
 See ``{\it Configuring Status Hilites\/}'' for further information.
 %.lp
 \item[\ib{status\verb+_+updates}]
@@ -4271,18 +4276,23 @@ The pattern should be a regular expression.
 Your copy of NetHack may have been compiled with support for {\it Status Hilites}.
 If so, you can customize your game display by setting thresholds to 
 change the color or appearance of fields in the status display.
-
+%.pg
+The format for defining status colors is:
+\begin{verbatim}
+    OPTION=hilite_status: field-name/behavior/color&attributes
+\end{verbatim}
+%.pg
 For example, the following line in your config file will cause
 the hitpoints field to display in the color red if your hitpoints
 drop to or below a threshold of 30%:
 \begin{verbatim}
-    OPTION=hilite_status: hitpoints/30%/red/normal
+    OPTION=hilite_status: hitpoints/<30%/red/normal
 \end{verbatim}
 %.pg
 For another example, the following line in your config file will cause
 wisdom to be displayed red if it drops and green if it rises.
 \begin{verbatim}
-    OPTION=hilite_status: wisdom/updown/red/green
+    OPTION=hilite_status: wisdom/down/red/up/green
 \end{verbatim}
 You can adjust the display of the following status fields:
 %.sd
@@ -4301,6 +4311,56 @@ experience & condition\\
 \end{tabular}
 \end{center}
 %.ed
+%.lp ""
+The pseudo-field `characteristics' can be used to set all six
+of Str, Dex, Con, Int, Wis, and Cha at once.  `HD' is `hit dice',
+an approximation of experience level displayed when polymorphed.
+`experience', `time', and `score' are conditionally displayed
+depending upon your other option settings.
+
+%.lp ""
+Instead of a behavior, `condition' takes the following condition flags:
+{\it stone}, {\it slime}, {\it strngl}, {\it foodpois}, {\it termill},
+{\it blind}, {\it deaf}, {\it stun}, {\it conf}, {\it hallu},
+{\it lev}, {\it fly}, and {\it ride}.  You can use `major\_troubles' as an alias
+for stone through termill, `minor\_troubles' for blind through hallu,
+`movement' for lev, fly, and ride, and `all' for every condition.
+
+%.lp ""
+Allowed behaviors are "always", "up", "down", "changed", a
+percentage or absolute number threshold, or a text to match against.
+
+\blist{}
+%.lp "*"
+\item{\bb{}}
+"always" will set the default attributes for that field.
+%.lp "*"
+\item{\bb{}}
+"up" and "down" set the field attributes for when the field
+value changes upwards or downwards. This attribute times out after
+statushilites turns.
+%.lp "*"
+\item{\bb{}}
+"changed" sets the field attribute for when the field value
+changes. This attribute times out after statushilites turns.
+%.lp "*"
+\item{\bb{}}
+percentage sets the field attribute when the field value
+matches the percentage. If the percentage is prefixed with `{\tt <}'
+or `{\tt >}', it also matches when value is below or above the percentage.
+Only valid for `power' and `hitpoints' fields.
+%.lp "*"
+\item{\bb{}}
+absolute value sets the attribute when the field value
+matches that number. If the number is prefixed with `{\tt <}'
+or `{\tt >}', it also matches when value is below or above.
+%.lp "*"
+\item{\bb{}}
+text match sets the attribute when the field value
+matches the text. Text matches can only be used for `alignment',
+`carrying-capacity', and `dungeon-level'.
+%.ei
+\elist
 
 %.lp ""
 Allowed colors are {\it black}, {\it red}, {\it green}, {\it brown},
@@ -4309,12 +4369,32 @@ Allowed colors are {\it black}, {\it red}, {\it green}, {\it brown},
 {\it lightcyan}, and {\it white}.
 
 %.lp ""
-Behaviours can occur based on percentage thresholds, updown, or absolute values.
+Allowed attributes are {\it bold}, {\it inverse}, {\it underline},
+{\it blink}, {\it dim}, and {\it normal}.
+Note that the platform used may interpret the attributes any way it
+wants.
+
+%.lp ""
 The in-game options menu can help you determine the correct syntax for a 
 config file.
 
 %.lp ""
-The whole feature can be disable by setting option {\it statushilites} off.
+The whole feature can be disable by setting option {\it statushilites} to 0.
+
+%.lp ""
+Example hilites:
+\begin{verbatim}
+    OPTION=hilite_status: gold/up/yellow/down/brown
+    OPTION=hilite_status: characteristics/up/green/down/red
+    OPTION=hilite_status: hitpoints/100%/gray&normal
+    OPTION=hilite_status: hitpoints/<100%/green&normal
+    OPTION=hilite_status: hitpoints/<66%/yellow&normal
+    OPTION=hilite_status: hitpoints/<50%/orange&normal
+    OPTION=hilite_status: hitpoints/<33%/red&bold
+    OPTION=hilite_status: hitpoints/<15%/red&inverse
+    OPTION=hilite_status: condition/major/orange&inverse
+    OPTION=hilite_status: condition/lev+fly/red&inverse
+\end{verbatim}
 
 %.lp
 %.hn 2
index 799450eeaca7d6d81d8fcafd58e895acd54b4d46..a31001731dc392897318dcfc0efb75349ff6179e 100644 (file)
@@ -450,6 +450,8 @@ if a potion on the floor survived a land mine explosion and got propelled at
 adjust candelabrum's weight when candles are attached
 when lit candelabrum burned out, persistent inventory window showed that it
        was no longer lit but still showed phantom candles attached
+improve hilite_status, allowing multiple stops per field, and temporarily or
+       permanently hilited fields
 
 
 Fixes to Post-3.6.0 Problems that Were Exposed Via git Repository
@@ -671,6 +673,7 @@ new paranoid_confirm settings: wand-break to require "yes" rather than 'y'
        than 'y' when hero inflicted with lycanthropy has polymorph control
 option force_invmenu to make commands asking for inventory items always
        use a menu instead of a text line query
+option hitpointbar to show a bar graph of hit points behind title field
 
 
 Platform- and/or Interface-Specific New Features
index 2ebf9f8b5e4c850dfb5ff9884ecc6a70c93f670b..e648b23a42d852bca1f33ef0c95ee271e5588f27 100644 (file)
@@ -401,7 +401,7 @@ status_enablefield(int fldindex, char fldname, char fieldfmt, boolean enable)
                   BL_XP, BL_AC, BL_HD, BL_TIME, BL_HUNGER, BL_HP, BL_HPMAX, 
                   BL_LEVELDESC, BL_EXP, BL_CONDITION
                -- There are MAXBLSTATS status fields (from botl.h)
-status_update(int fldindex, genericptr_t ptr, int chg, int percentage)
+status_update(int fldindex, genericptr_t ptr, int chg, int percentage, int color, long *colormasks)
                -- update the value of a status field.
                -- the fldindex identifies which field is changing and
                   is an integer index value from botl.h
@@ -417,58 +417,124 @@ status_update(int fldindex, genericptr_t ptr, int chg, int percentage)
                -- ptr is usually a "char *", unless fldindex is BL_CONDITION.
                   If fldindex is BL_CONDITION, then ptr is a long value with
                   any or none of the following bits set (from botl.h):
-                       BL_MASK_BLIND           0x00000001L
-                       BL_MASK_CONF            0x00000002L
-                       BL_MASK_FOODPOIS        0x00000004L
-                       BL_MASK_ILL             0x00000008L
-                       BL_MASK_HALLU           0x00000010L
-                       BL_MASK_STUNNED         0x00000020L
-                       BL_MASK_SLIMED          0x00000040L
+                        BL_MASK_STONE           0x00000001L
+                        BL_MASK_SLIME           0x00000002L
+                        BL_MASK_STRNGL          0x00000004L
+                        BL_MASK_FOODPOIS        0x00000008L
+                        BL_MASK_TERMILL         0x00000010L
+                        BL_MASK_BLIND           0x00000020L
+                        BL_MASK_DEAF            0x00000040L
+                        BL_MASK_STUN            0x00000080L
+                        BL_MASK_CONF            0x00000100L
+                        BL_MASK_HALLU           0x00000200L
+                        BL_MASK_LEV             0x00000400L
+                        BL_MASK_FLY             0x00000800L
+                        BL_MASK_RIDE            0x00001000L
                -- The value passed for BL_GOLD includes a leading
                   symbol for GOLD "$:nnn". If the window port needs to use 
                   the textual gold amount without the leading "$:" the port 
                   will have to add 2 to the passed "ptr" for the BL_GOLD case.
+                -- color is an unsigned int.
+                   int & 0x00FF = color CLR_*
+                   int >> 8 = attribute (if any)
+
+                   This contains the color and attribute that the field should
+                   be displayed in.
+
+                   This is relevant for everything except BL_CONDITION fldindex.
+                   If fldindex is BL_CONDITION, this parameter should be ignored,
+                   as condition hilighting is done via the next colormasks
+                   parameter instead.
+
+                -- colormasks - pointer to cond_hilites[] array of colormasks.
+
+                   Only relevant for BL_CONDITION fldindex. The window port
+                   should ignore this parameter for other fldindex values.
+
+                   Each condition bit must only ever appear in one of the
+                   CLR_ array members, but can appear in multiple HL_ATTCLR_
+                   offsets (because more than one attribute can co-exist).
+
+                   For the user's chosen set of BL_MASK_ condition bits,
+                   They are stored internally in the cond_hilites[] array,
+                   at the array offset aligned to the color those condtion
+                   bits should display in.
+
+                   For example, if the user has chosen to display strngl
+                   and stone and termill in red and inverse,
+
+                        BL_MASK_SLIME           0x00000002
+                        BL_MASK_STRNGL          0x00000004
+                        BL_MASK_TERMILL         0x00000010
+
+                   The bitmask corresponding to those conditions is
+                   0x00000016 (or 00010110 in binary) and the color
+                   is at offset 1 (CLR_RED).
+
+                   Here is how that is stored in the cond_hilites[] array:
+
+                   +------+----------------------+--------------------+
+                   |array |                      |                    |
+                   |offset| macro for indexing   |   bitmask          |
+                   |------+----------------------+--------------------+
+                   |   0  |   CLR_BLACK          |                    |
+                   +------+----------------------+--------------------+
+                   |   1  |   CLR_RED            |   00010110         |
+                   +------+----------------------+--------------------+
+                   |   2  |   CLR_GREEN          |                    |
+                   +------+----------------------+--------------------+
+                   |   3  |   CLR_BROWN          |                    |
+                   +------+----------------------+--------------------+
+                   |   4  |   CLR_BLUE           |                    |
+                   +------+----------------------+--------------------+
+                   |   5  |   CLR_MAGENTA        |                    |
+                   +------+----------------------+--------------------+
+                   |   6  |   CLR_CYAN           |                    |
+                   +------+----------------------+--------------------+
+                   |   7  |   CLR_GRAY           |                    |
+                   +------+----------------------+--------------------+
+                   |   8  |   NO_COLOR           |                    |
+                   +------+----------------------+--------------------+
+                   |   9  |   CLR_ORANGE         |                    |
+                   +------+----------------------+--------------------+
+                   |  10  |   CLR_BRIGHT_GREEN   |                    |
+                   +------+----------------------+--------------------+
+                   |  11  |   CLR_BRIGHT_YELLOW  |                    |
+                   +------+----------------------+--------------------+
+                   |  12  |   CLR_BRIGHT_BLUE    |                    |
+                   +------+----------------------+--------------------+
+                   |  13  |   CLR_BRIGHT_MAGENTA |                    |
+                   +------+----------------------+--------------------+
+                   |  14  |   CLR_BRIGHT_CYAN    |                    |
+                   +------+----------------------+--------------------+
+                   |  15  |   CLR_WHITE          |                    |
+                   +------+----------------------+--------------------+
+                   |  16  |   HL_ATTCLR_DIM      |                    | CLR_MAX
+                   +------+----------------------+--------------------+
+                   |  17  |   HL_ATTCLR_BLINK    |                    |
+                   +------+----------------------+--------------------+
+                   |  18  |   HL_ATTCLR_ULINE    |                    |
+                   +------+----------------------+--------------------+
+                   |  19  |   HL_ATTCLR_INVERSE  |   00010110         |
+                   +------+----------------------+--------------------+
+                   |  20  |   HL_ATTCLR_BOLD     |                    |
+                   +------+----------------------+--------------------+
+                   |  21  |  beyond array boundary                    | BL_ATTCLR_MAX
+
+                   The window port can AND (&) the bits passed in the
+                   ptr argument to status_update() with any non-zero
+                   entries in the cond_hilites[] array to determine
+                   the color and attributes for displaying the
+                   condition on the screen for the user.
+
+                   If the bit for a particular condition does not
+                   appear in any of the cond_hilites[] array offsets,
+                   that condition should be displayed in the default
+                   color and attributes.
 
 status_finish() -- called when it is time for the window port to tear down
                   the status display and free allocated memory, etc.
 
-status_threshold(int fldidx, int threshholdtype, anything threshold, 
-                                       int behavior, int under, int over)
-               -- called when a hiliting preference is added, changed, or
-                  removed.
-               -- the fldindex identifies which field is having its hiliting
-                  preference set. It is an integer index value from botl.h
-               -- fldindex could be any one of the following from botl.h:
-                  BL_TITLE, BL_STR, BL_DX, BL_CO, BL_IN, BL_WI, BL_CH, 
-                  BL_ALIGN, BL_SCORE, BL_CAP, BL_GOLD, BL_ENE, BL_ENEMAX, 
-                  BL_XP, BL_AC, BL_HD, BL_TIME, BL_HUNGER, BL_HP, BL_HPMAX, 
-                  BL_LEVELDESC, BL_EXP, BL_CONDITION
-               -- datatype is P_INT, P_UINT, P_LONG, or P_MASK.
-               -- threshold is an "anything" union which can contain the 
-                  datatype value.
-               -- behavior is used to define how threshold is used and can
-                  be BL_TH_NONE, BL_TH_VAL_PERCENTAGE, BL_TH_VAL_ABSOLUTE,
-                  or BL_TH_UPDOWN. BL_TH_NONE means don't do anything above
-                  or below the threshold.  BL_TH_VAL_PERCENTAGE treats the
-                  threshold value as a precentage of the maximum possible
-                  value. BL_TH_VAL_ABSOLUTE means that the threshold is an
-                  actual value. BL_TH_UPDOWN means that threshold is not
-                  used, and the two below/above hilite values indicate how
-                  to display something going down (under) or rising (over).                
-               -- under is the hilite attribute used if value is below the 
-                  threshold. The attribute can be BL_HILITE_NONE, 
-                  BL_HILITE_INVERSE, BL_HILITE_BOLD (-1, -2, or -3), or one 
-                  of the color indexes of CLR_BLACK, CLR_RED, CLR_GREEN, 
-                  CLR_BROWN, CLR_BLUE, CLR_MAGENTA, CLR_CYAN, CLR_GRAY, 
-                  CLR_ORANGE, CLR_BRIGHT_GREEN, CLR_YELLOW, CLR_BRIGHT_BLUE, 
-                  CLR_BRIGHT_MAGENTA, CLR_BRIGHT_CYAN, or CLR_WHITE (0 - 15).
-               -- over is the hilite attribute used if value is at or above 
-                  the threshold. The attribute can be BL_HILITE_NONE, 
-                  BL_HILITE_INVERSE, BL_HILITE_BOLD (-1, -2, or -3), or one 
-                  of the color indexes of CLR_BLACK, CLR_RED, CLR_GREEN, 
-                  CLR_BROWN, CLR_BLUE, CLR_MAGENTA, CLR_CYAN, CLR_GRAY, 
-                  CLR_ORANGE, CLR_BRIGHT_GREEN, CLR_YELLOW, CLR_BRIGHT_BLUE, 
-                  CLR_BRIGHT_MAGENTA, CLR_BRIGHT_CYAN, or CLR_WHITE (0 - 15).
 
 E.  Misc. Routines
 
@@ -703,6 +769,7 @@ to support:
   |  softkeyboard      | WC2_SOFTKEYBOARD   | wc2_softkeyboard   |boolean |
   |  wraptext          | WC2_WRAPTEXT       | wc2_wraptext       |boolean |
   |  selectsaved       | WC2_SELECTSAVED    | wc2_selectsaved    |boolean |
+  |  hitpointbar       | WC2_HITPOINTBAR    | wc2_hitpointbar    |boolean |
   +--------------------+--------------------+--------------------+--------+
 
 align_message  -- where to place message window (top, bottom, left, right)
@@ -723,6 +790,7 @@ font_status -- port should use a font by this name for status display.
 font_text      -- port should use a font by this name for text windows.
 fullscreen      -- port should try to use the whole screen.
 hilite_pet     -- port should mark pets in some special way on the map.
+hitpointbar    -- port should show a graphical bar representing hit points
 map_mode       -- port should display the map in the manner specified.
 player_selection
                -- dialog or prompts for choosing character.
index 061d6c716a61f8ef74d4b57aaff467951d35f9fb..ce2a944964de3ea574b3e7f05d239dce3764696d 100644 (file)
@@ -27,42 +27,18 @@ Astral Plane \GXXXXNNNN:123456 HP:1234(1234) Pw:1234(1234) AC:-127
 #define MAXCO (COLNO + 40)
 #endif
 
-#ifdef STATUS_VIA_WINDOWPORT
-#if 0
-/* clang-format off */
-#define BL_FLUSH        -1
-#define BL_TITLE        0
-#define BL_STR          1
-#define BL_DX           2
-#define BL_CO           3
-#define BL_IN           4
-#define BL_WI           5
-#define BL_CH           6
-#define BL_ALIGN        7
-#define BL_SCORE        8
-#define BL_CAP          9
-#define BL_GOLD         10
-#define BL_ENE          11
-#define BL_ENEMAX       12
-#define BL_XP           13
-#define BL_AC           14
-#define BL_HD           15
-#define BL_TIME         16
-#define BL_HUNGER       17
-#define BL_HP           18
-#define BL_HPMAX        19
-#define BL_LEVELDESC    20
-#define BL_EXP          21
-#define BL_CONDITION    22
-/* clang-format on */
+enum statusfields {
+    BL_CHARACTERISTICS = -2, /* alias for BL_STR..BL_CH */
+    BL_FLUSH = -1, BL_TITLE = 0,
+    BL_STR, BL_DX, BL_CO, BL_IN, BL_WI, BL_CH,  /* 1..6 */
+    BL_ALIGN, BL_SCORE, BL_CAP, BL_GOLD, BL_ENE, BL_ENEMAX, /* 7..12 */
+    BL_XP, BL_AC, BL_HD, BL_TIME, BL_HUNGER, BL_HP, BL_HPMAX, BL_LEVELDESC, /* 13..20 */
+    BL_EXP, BL_CONDITION
+};
 
-#else
-enum statusfields { BL_FLUSH = -1, BL_TITLE = 0, BL_STR, BL_DX, BL_CO, BL_IN,
-BL_WI, BL_CH, BL_ALIGN, BL_SCORE, BL_CAP, BL_GOLD, BL_ENE, BL_ENEMAX,
-BL_XP, BL_AC, BL_HD, BL_TIME, BL_HUNGER, BL_HP, BL_HPMAX, BL_LEVELDESC,
-BL_EXP, BL_CONDITION };
-#endif
-#define MAXBLSTATS      BL_CONDITION+1
+enum relationships { LT_VALUE = -1, EQ_VALUE, GT_VALUE, TXT_VALUE };
+
+#define MAXBLSTATS      (BL_CONDITION + 1)
 
 #define BEFORE  0
 #define NOW     1
@@ -87,7 +63,7 @@ BL_EXP, BL_CONDITION };
 
 #define REASSESS_ONLY TRUE
 
-#ifdef STATUS_HILITES
+/* #ifdef STATUS_HILITES */
 /* hilite status field behavior - coloridx values */
 #define BL_HILITE_NONE -1    /* no hilite of this field */
 #define BL_HILITE_INVERSE -2 /* inverse hilite */
@@ -98,9 +74,26 @@ BL_EXP, BL_CONDITION };
 #define BL_TH_VAL_ABSOLUTE 101   /* threshold is particular value */
 #define BL_TH_UPDOWN 102         /* threshold is up or down change */
 #define BL_TH_CONDITION 103      /* threshold is bitmask of conditions */
-#endif
+#define BL_TH_TEXTMATCH 104      /* threshold text value to match against */
+#define BL_TH_ALWAYS_HILITE 105  /* highlight regardless of value */
+
+
+#define HL_ATTCLR_DIM     CLR_MAX + 0
+#define HL_ATTCLR_BLINK   CLR_MAX + 1
+#define HL_ATTCLR_ULINE   CLR_MAX + 2
+#define HL_ATTCLR_INVERSE CLR_MAX + 3
+#define HL_ATTCLR_BOLD    CLR_MAX + 4
+#define BL_ATTCLR_MAX     CLR_MAX + 5
+
+enum hlattribs { HL_UNDEF   = 0x00,
+                 HL_NONE    = 0x01,
+                 HL_BOLD    = 0x02,
+                 HL_INVERSE = 0x04,
+                 HL_ULINE   = 0x08,
+                 HL_BLINK   = 0x10,
+                 HL_DIM     = 0x20 };
+/* #endif STATUS_HILITES */
 
 extern const char *status_fieldnames[]; /* in botl.c */
-#endif
 
 #endif /* BOTL_H */
index a8d10c67be37928ef6e38d14d640d013576f820c..5cae0fa9f6169caa7bc8693e6fa00e159eab3a3a 100644 (file)
@@ -498,9 +498,7 @@ typedef unsigned char uchar;
  * Only available with POSIX_TYPES or GNU C */
 /* #define MSGHANDLER */
 
-/* #define STATUS_VIA_WINDOWPORT */ /* re-work of the status line
-                                       updating process */
-/* #define STATUS_HILITES */        /* support hilites of status fields */
+#define STATUS_HILITES         /* support hilites of status fields */
 
 /* #define WINCHAIN */              /* stacked window systems */
 
index d26b75dd00266c4e15a991a00b9eaded65c1fae8..f6d5764cb1b4f15ca9e3a5aae60ca18e6d5d51ac 100644 (file)
@@ -325,9 +325,7 @@ E NEARDATA char **viz_array;           /* could see/in sight row pointers */
 
 /* Window system stuff */
 E NEARDATA winid WIN_MESSAGE;
-#ifndef STATUS_VIA_WINDOWPORT
 E NEARDATA winid WIN_STATUS;
-#endif
 E NEARDATA winid WIN_MAP, WIN_INVEN;
 
 /* pline (et al) for a single string argument (suppress compiler warning) */
index d571acac55f953eefd246486b22119a2842557df..57011ffbb00ea3bdb5dfe9dc8548bd378787a24a 100644 (file)
@@ -153,17 +153,17 @@ E long NDECL(botl_score);
 E int FDECL(describe_level, (char *));
 E const char *FDECL(rank_of, (int, SHORT_P, BOOLEAN_P));
 E void NDECL(bot);
-#ifdef STATUS_VIA_WINDOWPORT
 E void FDECL(status_initialize, (BOOLEAN_P));
 E void NDECL(status_finish);
 E void FDECL(status_notify_windowport, (BOOLEAN_P));
+E void NDECL(status_eval_next_unhilite);
 #ifdef STATUS_HILITES
-E boolean FDECL(set_status_hilites, (char *op, BOOLEAN_P));
-E void FDECL(clear_status_hilites, (BOOLEAN_P));
-E char *FDECL(get_status_hilites, (char *, int));
+E boolean FDECL(parse_status_hl1, (char *op, BOOLEAN_P));
+E void NDECL(clear_status_hilites);
+E void NDECL(reset_status_hilites);
+E int NDECL(count_status_hilites);
 E boolean NDECL(status_hilite_menu);
 #endif
-#endif
 
 /* ### cmd.c ### */
 
@@ -869,6 +869,7 @@ E char *FDECL(upstart, (char *));
 E char *FDECL(mungspaces, (char *));
 E char *FDECL(trimspaces, (char *));
 E char *FDECL(strip_newline, (char *));
+E char *FDECL(stripchars, (char *, const char *, const char *));
 E char *FDECL(eos, (char *));
 E boolean FDECL(str_end_is, (const char *, const char *));
 E char *FDECL(strkitten, (char *, CHAR_P));
@@ -1711,8 +1712,11 @@ E boolean FDECL(parsesymbols, (char *));
 E struct symparse *FDECL(match_sym, (char *));
 E void NDECL(set_playmode);
 E int FDECL(sym_val, (const char *));
+E int FDECL(query_color, (const char *));
+E int FDECL(query_attr, (const char *));
 E const char *FDECL(clr2colorname, (int));
 E int FDECL(match_str2clr, (char *));
+E int FDECL(match_str2attr, (const char *, BOOLEAN_P));
 E boolean FDECL(add_menu_coloring, (char *));
 E boolean FDECL(get_menu_coloring, (char *, int *, int *));
 E void NDECL(free_menu_coloring);
@@ -2736,16 +2740,11 @@ E void FDECL(genl_putmsghistory, (const char *, BOOLEAN_P));
 #ifdef HANGUPHANDLING
 E void NDECL(nhwindows_hangup);
 #endif
-#ifdef STATUS_VIA_WINDOWPORT
 E void NDECL(genl_status_init);
 E void NDECL(genl_status_finish);
 E void FDECL(genl_status_enablefield,
              (int, const char *, const char *, BOOLEAN_P));
-E void FDECL(genl_status_update, (int, genericptr_t, int, int));
-#ifdef STATUS_HILITES
-E void FDECL(genl_status_threshold, (int, int, anything, int, int, int));
-#endif
-#endif
+E void FDECL(genl_status_update, (int, genericptr_t, int, int, int, unsigned long *));
 
 E void FDECL(dump_open_log, (time_t));
 E void NDECL(dump_close_log);
index 9cd6b3533485e4973ff9d9d6f59533f06dcddc52..415688a9201a1efd0d45e74899f8631db670c7c0 100644 (file)
@@ -251,7 +251,10 @@ struct instance_flags {
     boolean toptenwin;        /* ending list in window instead of stdout */
     boolean use_background_glyph; /* use background glyph when appropriate */
     boolean use_menu_color;   /* use color in menus; only if wc_color */
-    boolean use_status_hilites; /* use color in status line */
+#ifdef STATUS_HILITES
+    long hilite_delta;     /* number of moves to leave a temp hilite lit */
+    long unhilite_deadline; /* time when oldest temp hilite should be unlit */
+#endif
     boolean zerocomp;         /* write zero-compressed save files */
     boolean rlecomp;          /* alternative to zerocomp; run-length encoding
                                * compression of levels when writing savefile */
@@ -360,6 +363,7 @@ struct instance_flags {
     boolean wc2_wraptext;       /* wrap text */
     boolean wc2_selectsaved;    /* display a menu of user's saved games */
     boolean wc2_darkgray; /* try to use dark-gray color for black glyphs */
+    boolean wc2_hitpointbar;    /* show graphical bar representing hit points */
     boolean cmdassist;    /* provide detailed assistance for some commands */
     boolean clicklook;    /* allow right-clicking for look */
     boolean obsolete; /* obsolete options can point at this, it isn't used */
index f3f4e870f66ca5fcda427229b80843e6c6f85ce6..4d0d395a1e3ad6e192122271ed7679d622f7cb89 100644 (file)
@@ -73,16 +73,11 @@ struct window_procs {
     void FDECL((*win_preference_update), (const char *));
     char *FDECL((*win_getmsghistory), (BOOLEAN_P));
     void FDECL((*win_putmsghistory), (const char *, BOOLEAN_P));
-#ifdef STATUS_VIA_WINDOWPORT
     void NDECL((*win_status_init));
     void NDECL((*win_status_finish));
     void FDECL((*win_status_enablefield),
                (int, const char *, const char *, BOOLEAN_P));
-    void FDECL((*win_status_update), (int, genericptr_t, int, int));
-#ifdef STATUS_HILITES
-    void FDECL((*win_status_threshold), (int, int, anything, int, int, int));
-#endif
-#endif
+    void FDECL((*win_status_update), (int, genericptr_t, int, int, int, unsigned long *));
     boolean NDECL((*win_can_suspend));
 };
 
@@ -160,16 +155,11 @@ extern
 #define preference_update (*windowprocs.win_preference_update)
 #define getmsghistory (*windowprocs.win_getmsghistory)
 #define putmsghistory (*windowprocs.win_putmsghistory)
-#ifdef STATUS_VIA_WINDOWPORT
 /* there is a status_initialize() in botl.c,
  * which calls win_status_init() directly; same with status_finish.
  */
 #define status_enablefield (*windowprocs.win_status_enablefield)
 #define status_update (*windowprocs.win_status_update)
-#ifdef STATUS_HILITES
-#define status_threshold (*windowprocs.win_status_threshold)
-#endif
-#endif
 
 /*
  * WINCAP
@@ -221,7 +211,10 @@ extern
 #define WC2_HILITE_STATUS 0x0008L /* 04 hilite fields in status         */
 #define WC2_SELECTSAVED   0x0010L /* 05 saved game selection menu       */
 #define WC2_DARKGRAY      0x0020L /* 06 use bold black for black glyphs */
-                                  /* 26 free bits */
+#define WC2_HITPOINTBAR   0x0040L /* 07 show bar representing hit points */
+#define WC2_FLUSH_STATUS  0x0080L /* 08 call status_update(BL_FLUSH)
+                                        after updating status window fields */
+                                  /* 24 free bits */
 
 #define ALIGN_LEFT   1
 #define ALIGN_RIGHT  2
@@ -362,17 +355,11 @@ struct chain_procs {
     void FDECL((*win_preference_update), (CARGS, const char *));
     char *FDECL((*win_getmsghistory), (CARGS, BOOLEAN_P));
     void FDECL((*win_putmsghistory), (CARGS, const char *, BOOLEAN_P));
-#ifdef STATUS_VIA_WINDOWPORT
     void FDECL((*win_status_init), (CARGS));
     void FDECL((*win_status_finish), (CARGS));
     void FDECL((*win_status_enablefield),
                (CARGS, int, const char *, const char *, BOOLEAN_P));
-    void FDECL((*win_status_update), (CARGS, int, genericptr_t, int, int));
-#ifdef STATUS_HILITES
-    void FDECL((*win_status_threshold),
-               (CARGS, int, int, anything, int, int, int));
-#endif
-#endif
+    void FDECL((*win_status_update), (CARGS, int, genericptr_t, int, int, int, unsigned long));
     boolean FDECL((*win_can_suspend), (CARGS));
 };
 #endif /* WINCHAIN */
index 4191cf34965d25bfdaa973cef6fb750d418ce6c4..1f270128fa108b3ebd2ec364c9910e3b80cfd24c 100644 (file)
@@ -215,13 +215,8 @@ E short FDECL(set_tty_font_name, (winid, char *));
 #endif
 E char *NDECL(tty_get_color_string);
 #endif
-#ifdef STATUS_VIA_WINDOWPORT
 E void NDECL(tty_status_init);
-E void FDECL(tty_status_update, (int, genericptr_t, int, int));
-#ifdef STATUS_HILITES
-E void FDECL(tty_status_threshold, (int, int, anything, int, int, int));
-#endif
-#endif
+E void FDECL(tty_status_update, (int, genericptr_t, int, int, int, unsigned long *));
 
 /* other defs that really should go away (they're tty specific) */
 E void NDECL(tty_start_screen);
index fa9e03ac69a0963714bc23e57a0ae2163e96188b..170f8b1df86975b145d5e4b0a7900102213c40f5 100644 (file)
@@ -59,15 +59,12 @@ boolean resuming;
         context.rndencode = rnd(9000);
         set_wear((struct obj *) 0); /* for side-effects of starting gear */
         (void) pickup(1);      /* autopickup at initial location */
-    } else {                   /* restore old game */
-#ifndef WIN32
-        update_inventory(); /* for perm_invent */
-#endif
-        read_engr_at(u.ux, u.uy); /* subset of pickup() */
     }
-#ifdef WIN32
+    context.botlx = TRUE; /* for STATUS_HILITES */
     update_inventory(); /* for perm_invent */
-#endif
+    if (resuming) { /* restoring old game */
+        read_engr_at(u.ux, u.uy); /* subset of pickup() */
+    }
 
     (void) encumber_msg(); /* in case they auto-picked up something */
     if (defer_see_monsters) {
@@ -317,6 +314,7 @@ boolean resuming;
             /* once-per-hero-took-time things go here */
             /******************************************/
 
+            status_eval_next_unhilite();
             if (context.bypasses)
                 clear_bypasses();
             if ((u.uhave.amulet || Clairvoyant) && !In_endgame(&u.uz)
@@ -529,7 +527,7 @@ void
 display_gamewindows()
 {
     WIN_MESSAGE = create_nhwindow(NHW_MESSAGE);
-#ifdef STATUS_VIA_WINDOWPORT
+#ifdef STATUS_HILITES
     status_initialize(0);
 #else
     WIN_STATUS = create_nhwindow(NHW_STATUS);
@@ -553,7 +551,7 @@ display_gamewindows()
      * The mac port is not DEPENDENT on the order of these
      * displays, but it looks a lot better this way...
      */
-#ifndef STATUS_VIA_WINDOWPORT
+#ifndef STATUS_HILITES
     display_nhwindow(WIN_STATUS, FALSE);
 #endif
     display_nhwindow(WIN_MESSAGE, FALSE);
index d1d0a53e8d730daefe753f9a9c7ff5af0b8857ef..03f2aea119492f123f508820c78150b6b97f15b2 100644 (file)
@@ -12,6 +12,7 @@ const char *const enc_stat[] = { "",         "Burdened",  "Stressed",
 
 STATIC_OVL NEARDATA int mrank_sz = 0; /* loaded by max_rank_sz (from u_init) */
 STATIC_DCL const char *NDECL(rank);
+STATIC_DCL void NDECL(bot_via_windowport);
 
 static char *
 get_strength_str()
@@ -32,8 +33,6 @@ get_strength_str()
     return buf;
 }
 
-#if !defined(STATUS_VIA_WINDOWPORT) || defined(DUMPLOG)
-
 char *
 do_statusline1()
 {
@@ -228,21 +227,21 @@ do_statusline2()
     return newbot2;
 }
 
-#ifndef STATUS_VIA_WINDOWPORT
 void
 bot()
 {
     if (youmonst.data && iflags.status_updates) {
+#ifdef STATUS_HILITES
+        bot_via_windowport();
+#else
         curs(WIN_STATUS, 1, 0);
         putstr(WIN_STATUS, 0, do_statusline1());
         curs(WIN_STATUS, 1, 1);
         putmixed(WIN_STATUS, 0, do_statusline2());
+#endif
     }
     context.botl = context.botlx = 0;
 }
-#endif /* !STATUS_VIA_WINDOWPORT */
-
-#endif /* !STATUS_VIA_WINDOWPORT || DUMPLOG */
 
 /* convert experience level (1..30) to rank index (0..8) */
 int
@@ -387,18 +386,45 @@ char *buf;
     return ret;
 }
 
-#ifdef STATUS_VIA_WINDOWPORT
+/* =======================================================================*/
+/*  statusnew routines                                                    */
 /* =======================================================================*/
 
 /* structure that tracks the status details in the core */
+
+#ifdef STATUS_HILITES
+struct hilite_s {
+    enum statusfields fld;
+    boolean set;
+    unsigned anytype;
+    anything value;
+    int behavior;
+    char textmatch[QBUFSZ];
+    enum relationships rel;
+    int coloridx;
+    struct hilite_s *next;
+};
+
+struct condmap {
+    const char *id;
+    unsigned long bitmask;
+};
+#endif /* STATUS_HILITES */
+
 struct istat_s {
-    long time;
+    const char *fldname;
+    const char *fldfmt;
+    long time;  /* moves when this field hilite times out */
+    boolean chg; /* need to recalc time? */
     unsigned anytype;
     anything a;
     char *val;
     int valwidth;
     enum statusfields idxmax;
     enum statusfields fld;
+#ifdef STATUS_HILITES
+    struct hilite_s *thresholds;
+#endif
 };
 
 
@@ -406,63 +432,98 @@ STATIC_DCL void NDECL(init_blstats);
 STATIC_DCL char *FDECL(anything_to_s, (char *, anything *, int));
 STATIC_OVL int FDECL(percentage, (struct istat_s *, struct istat_s *));
 STATIC_OVL int FDECL(compare_blstats, (struct istat_s *, struct istat_s *));
+STATIC_DCL boolean FDECL(evaluate_and_notify_windowport_field,
+                         (int, boolean *, int, int));
+STATIC_DCL void FDECL(evaluate_and_notify_windowport, (boolean *, int, int));
+
 #ifdef STATUS_HILITES
+STATIC_DCL boolean FDECL(hilite_reset_needed, (struct istat_s *, long));
 STATIC_DCL void FDECL(s_to_anything, (anything *, char *, int));
-STATIC_DCL boolean FDECL(assign_hilite, (char *, char *, char *, char *,
-                                         BOOLEAN_P));
-STATIC_DCL const char *FDECL(clridx_to_s, (char *, int));
+STATIC_DCL boolean FDECL(is_ltgt_percentnumber, (const char *));
+STATIC_DCL boolean FDECL(has_ltgt_percentnumber, (const char *));
+STATIC_DCL boolean FDECL(parse_status_hl2, (char (*)[QBUFSZ],BOOLEAN_P));
+STATIC_DCL boolean FDECL(parse_condition, (char (*)[QBUFSZ], int));
+STATIC_DCL void FDECL(merge_bestcolor, (int *, int));
+STATIC_DCL void FDECL(get_hilite_color, (int, int, genericptr_t, int,
+                                                int, int *));
+STATIC_DCL unsigned long FDECL(match_str2conditionbitmask, (const char *));
+STATIC_DCL unsigned long FDECL(str2conditionbitmask, (char *));
+STATIC_DCL void FDECL(split_clridx, (int, int *, int *));
+STATIC_DCL char *FDECL(hlattr2attrname, (int, char *, int));
+STATIC_DCL void FDECL(status_hilite_linestr_add, (int, struct hilite_s *,
+                                            unsigned long, const char *));
+
+STATIC_DCL void NDECL(status_hilite_linestr_done);
+STATIC_DCL int FDECL(status_hilite_linestr_countfield, (int));
+STATIC_DCL void NDECL(status_hilite_linestr_gather_conditions);
+STATIC_DCL void NDECL(status_hilite_linestr_gather);
+STATIC_DCL char *FDECL(status_hilite2str, (struct hilite_s *));
+STATIC_DCL boolean FDECL(status_hilite_menu_add, (int));
+#define has_hilite(i) (blstats[0][(i)].thresholds)
 #endif
 
+#define INIT_BLSTAT(name, fmtstr, anytyp, wid, fld)                     \
+    { name, fmtstr, 0L, FALSE, anytyp,  { (genericptr_t) 0 }, (char *) 0, \
+      wid,  -1, fld }
+#define INIT_BLSTATP(name, fmtstr, anytyp, wid, maxfld, fld)            \
+    { name, fmtstr, 0L, FALSE, anytyp,  { (genericptr_t) 0 }, (char *) 0, \
+      wid,  maxfld, fld }
+
 /* If entries are added to this, botl.h will require updating too */
 STATIC_DCL struct istat_s initblstats[MAXBLSTATS] = {
-    { 0L, ANY_STR,  { (genericptr_t) 0 }, (char *) 0, 80,  0, BL_TITLE},
-    { 0L, ANY_INT,  { (genericptr_t) 0 }, (char *) 0, 10,  0, BL_STR},
-    { 0L, ANY_INT,  { (genericptr_t) 0 }, (char *) 0, 10,  0, BL_DX},
-    { 0L, ANY_INT,  { (genericptr_t) 0 }, (char *) 0, 10,  0, BL_CO},
-    { 0L, ANY_INT,  { (genericptr_t) 0 }, (char *) 0, 10,  0, BL_IN},
-    { 0L, ANY_INT,  { (genericptr_t) 0 }, (char *) 0, 10,  0, BL_WI},
-    { 0L, ANY_INT,  { (genericptr_t) 0 }, (char *) 0, 10,  0, BL_CH},
-    { 0L, ANY_STR,  { (genericptr_t) 0 }, (char *) 0, 40,  0, BL_ALIGN},
-    { 0L, ANY_LONG, { (genericptr_t) 0 }, (char *) 0, 20,  0, BL_SCORE},
-    { 0L, ANY_LONG, { (genericptr_t) 0 }, (char *) 0, 20,  0, BL_CAP},
-    { 0L, ANY_LONG, { (genericptr_t) 0 }, (char *) 0, 30,  0, BL_GOLD},
-    { 0L, ANY_INT,  { (genericptr_t) 0 }, (char *) 0, 10,  BL_ENEMAX, BL_ENE},
-    { 0L, ANY_INT,  { (genericptr_t) 0 }, (char *) 0, 10,  0, BL_ENEMAX},
-    { 0L, ANY_LONG, { (genericptr_t) 0 }, (char *) 0, 10,  0, BL_XP},
-    { 0L, ANY_INT,  { (genericptr_t) 0 }, (char *) 0, 10,  0, BL_AC},
-    { 0L, ANY_INT,  { (genericptr_t) 0 }, (char *) 0, 10,  0, BL_HD},
-    { 0L, ANY_INT,  { (genericptr_t) 0 }, (char *) 0, 20,  0, BL_TIME},
-    { 0L, ANY_UINT, { (genericptr_t) 0 }, (char *) 0, 40,  0, BL_HUNGER},
-    { 0L, ANY_INT,  { (genericptr_t) 0 }, (char *) 0, 10,  BL_HPMAX, BL_HP},
-    { 0L, ANY_INT,  { (genericptr_t) 0 }, (char *) 0, 10,  0, BL_HPMAX},
-    { 0L, ANY_STR,  { (genericptr_t) 0 }, (char *) 0, 80,  0, BL_LEVELDESC},
-    { 0L, ANY_LONG, { (genericptr_t) 0 }, (char *) 0, 20,  0, BL_EXP},
-    { 0L, ANY_MASK32,
-                    { (genericptr_t) 0 }, (char *) 0,  0,  0, BL_CONDITION}
+    INIT_BLSTAT("title", "%s", ANY_STR, 80, BL_TITLE),
+    INIT_BLSTAT("strength", " St:%s", ANY_INT, 10, BL_STR),
+    INIT_BLSTAT("dexterity", " Dx:%s", ANY_INT,  10, BL_DX),
+    INIT_BLSTAT("constitution", " Co:%s", ANY_INT, 10, BL_CO),
+    INIT_BLSTAT("intelligence", " In:%s", ANY_INT, 10, BL_IN),
+    INIT_BLSTAT("wisdom", " Wi:%s", ANY_INT, 10, BL_WI),
+    INIT_BLSTAT("charisma", " Ch:%s", ANY_INT, 10, BL_CH),
+    INIT_BLSTAT("alignment", " %s", ANY_STR, 40, BL_ALIGN),
+    INIT_BLSTAT("score", " S:%s", ANY_LONG, 20, BL_SCORE),
+    INIT_BLSTAT("carrying-capacity", " %s", ANY_LONG, 20, BL_CAP),
+    INIT_BLSTAT("gold", " %s", ANY_LONG, 30, BL_GOLD),
+    INIT_BLSTATP("power", " Pw:%s", ANY_INT, 10, BL_ENEMAX, BL_ENE),
+    INIT_BLSTAT("power-max", "(%s)", ANY_INT, 10, BL_ENEMAX),
+    INIT_BLSTAT("experience-level", " Xp:%s", ANY_LONG, 10, BL_XP),
+    INIT_BLSTAT("armor-class", " AC:%s", ANY_INT, 10, BL_AC),
+    INIT_BLSTAT("HD", " HD:%s", ANY_INT, 10, BL_HD),
+    INIT_BLSTAT("time", " T:%s", ANY_INT, 20, BL_TIME),
+    INIT_BLSTAT("hunger", " %s", ANY_UINT, 40, BL_HUNGER),
+    INIT_BLSTATP("hitpoints", " HP:%s", ANY_INT, 10, BL_HPMAX, BL_HP),
+    INIT_BLSTAT("hitpoints-max", "(%s)", ANY_INT, 10, BL_HPMAX),
+    INIT_BLSTAT("dungeon-level", "%s", ANY_STR, 80, BL_LEVELDESC),
+    INIT_BLSTAT("experience", "/%s", ANY_LONG, 20, BL_EXP),
+    INIT_BLSTAT("condition", "%s", ANY_MASK32, 0, BL_CONDITION)
 };
 
+#undef INIT_BLSTATP
+#undef INIT_BLSTAT
+
 struct istat_s blstats[2][MAXBLSTATS];
 static boolean blinit = FALSE, update_all = FALSE;
+static boolean valset[MAXBLSTATS];
+unsigned long blcolormasks[CLR_MAX];
+static long bl_hilite_moves = 0L;
+
+/* we don't put this next declaration in #ifdef STATUS_HILITES.
+ * In the absence of STATUS_HILITES, each array
+ * element will be 0 however, and quite meaningless,
+ * but we need to pass the first array element as
+ * the final argument of status_update, with or
+ * without STATUS_HILITES.
+ */
+unsigned long cond_hilites[BL_ATTCLR_MAX];
 
 void
-bot()
+bot_via_windowport()
 {
     char buf[BUFSZ];
     register char *nb;
-    static int idx = 0, idx_p, idxmax;
-    unsigned anytype;
+    static int i, idx = 0, idx_p, cap;
     long money;
-    int i, pc, chg, cap;
-    struct istat_s *curr, *prev;
-    boolean valset[MAXBLSTATS], chgval = FALSE, updated = FALSE;
 
     if (!blinit)
         panic("bot before init.");
-    if (!youmonst.data || !iflags.status_updates) {
-        context.botl = context.botlx = 0;
-        update_all = FALSE;
-        return;
-    }
 
     idx_p = idx;
     idx = 1 - idx; /* 0 -> 1, 1 -> 0 */
@@ -514,11 +575,9 @@ bot()
     /* Score */
     blstats[idx][BL_SCORE].a.a_long =
 #ifdef SCORE_ON_BOTL
-        botl_score()
-#else
-        0L
+        flags.showscore ? botl_score() :
 #endif
-        ;
+        0L;
 
     /*  Hit points  */
     i = Upolyd ? u.mh : u.uhp;
@@ -564,7 +623,7 @@ bot()
     blstats[idx][BL_AC].a.a_int = u.uac;
 
     /* Monster level (if Upolyd) */
-    blstats[idx][BL_HD].a.a_int = Upolyd ? mons[u.umonnum].mlevel : 0;
+    blstats[idx][BL_HD].a.a_int = Upolyd ? (int) mons[u.umonnum].mlevel : 0;
 
     /* Experience */
     blstats[idx][BL_XP].a.a_int = u.ulevel;
@@ -618,6 +677,89 @@ bot()
         blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_FLY;
     if (u.usteed)
         blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_RIDE;
+    evaluate_and_notify_windowport(valset, idx, idx_p);
+}
+
+STATIC_OVL boolean
+evaluate_and_notify_windowport_field(fld, valsetlist, idx, idx_p)
+int fld, idx, idx_p;
+boolean *valsetlist;
+{
+    static int oldrndencode = 0;
+    int pc, chg, color = NO_COLOR;
+    unsigned anytype;
+    boolean updated = FALSE, reset;
+    struct istat_s *curr = NULL, *prev = NULL;
+    enum statusfields idxmax;
+
+    /*
+     *  Now pass the changed values to window port.
+     */
+    anytype = blstats[idx][fld].anytype;
+    curr = &blstats[idx][fld];
+    prev = &blstats[idx_p][fld];
+    color = NO_COLOR;
+
+    chg = update_all ? 0 : compare_blstats(prev, curr);
+
+    /* Temporary? hack: moveloop()'s prolog for a new game sets
+     * context.rndencode after the status window has been init'd,
+     * so $:0 has already been encoded and cached by the window
+     * port.  Without this hack, gold's \G sequence won't be
+     * recognized and ends up being displayed as-is for 'update_all'.
+     */
+    if (context.rndencode != oldrndencode && fld == BL_GOLD) {
+        chg = 2;
+        oldrndencode = context.rndencode;
+    }
+
+    reset = FALSE;
+#ifdef STATUS_HILITES
+    if (!update_all && !chg) {
+        reset = hilite_reset_needed(prev, bl_hilite_moves);
+        if (reset)
+          curr->time = prev->time = 0L;
+    }
+#endif
+
+    if (update_all || chg || reset) {
+        idxmax = curr->idxmax;
+        pc = (idxmax > BL_FLUSH) ? percentage(curr, &blstats[idx][idxmax]) : 0;
+
+        if (!valsetlist[fld])
+            (void) anything_to_s(curr->val, &curr->a, anytype);
+
+        if (anytype != ANY_MASK32) {
+#ifdef STATUS_HILITES
+            if ((chg || *curr->val)) {
+                get_hilite_color(idx, fld, (genericptr_t)&curr->a,
+                                 chg, pc, &color);
+                if (chg == 2) {
+                    color = NO_COLOR;
+                    chg = 0;
+                }
+            }
+#endif /* STATUS_HILITES */
+            status_update(fld, (genericptr_t) curr->val,
+                          chg, pc, color, &cond_hilites[0]);
+        } else {
+            /* Color for conditions is done through cond_hilites[] */
+            status_update(fld, (genericptr_t) &curr->a.a_ulong, chg, pc,
+                          color, &cond_hilites[0]);
+        }
+        curr->chg = prev->chg = TRUE;
+        updated = TRUE;
+    }
+    return updated;
+}
+
+static void
+evaluate_and_notify_windowport(valsetlist, idx, idx_p)
+int idx, idx_p;
+boolean *valsetlist;
+{
+    int i;
+    boolean updated = FALSE;
 
     /*
      *  Now pass the changed values to window port.
@@ -629,28 +771,8 @@ bot()
             || ((i == BL_HD) && !Upolyd)
             || ((i == BL_XP || i == BL_EXP) && Upolyd))
             continue;
-        anytype = blstats[idx][i].anytype;
-        curr = &blstats[idx][i];
-        prev = &blstats[idx_p][i];
-        chg = 0;
-        if (update_all
-            || ((chg = compare_blstats(prev, curr)) != 0)
-            || ((chgval = (valset[i]
-                           && strcmp(blstats[idx][i].val,
-                                     blstats[idx_p][i].val))) != 0)) {
-            idxmax = blstats[idx][i].idxmax;
-            pc = (idxmax) ? percentage(curr, &blstats[idx][idxmax]) : 0;
-            if (!valset[i])
-                (void) anything_to_s(curr->val, &curr->a, anytype);
-            if (anytype != ANY_MASK32) {
-                status_update(i, (genericptr_t) curr->val,
-                              valset[i] ? chgval : chg, pc);
-            } else {
-                /* send pointer to mask */
-                status_update(i, (genericptr_t) &curr->a.a_ulong, chg, 0);
-            }
+        if (evaluate_and_notify_windowport_field(i, valsetlist, idx, idx_p))
             updated = TRUE;
-        }
     }
     /*
      * It is possible to get here, with nothing having been pushed
@@ -664,13 +786,49 @@ bot()
      * index of BL_FLUSH (-1).
      */
     if ((context.botlx && !updated)
-        || windowprocs.win_status_update == genl_status_update)
-        status_update(BL_FLUSH, (genericptr_t) 0, 0, 0);
+        || (windowprocs.wincap2 & WC2_FLUSH_STATUS) != 0L)
+        status_update(BL_FLUSH, (genericptr_t) 0, 0, 0,
+                      NO_COLOR, &cond_hilites[0]);
 
     context.botl = context.botlx = 0;
     update_all = FALSE;
 }
 
+void
+status_eval_next_unhilite()
+{
+    int i;
+    struct istat_s *curr = NULL;
+    long next_unhilite, this_unhilite;
+
+    bl_hilite_moves = moves;
+    /* figure out when the next unhilight needs to be performed */
+    next_unhilite = 0L;
+    for (i = 0; i < MAXBLSTATS; ++i) {
+        curr = &blstats[0][i]; /* blstats[0][*].time == blstats[1][*].time */
+
+        if (curr->chg) {
+            struct istat_s *prev = &blstats[1][i];
+
+#ifdef STATUS_HILITES
+            curr->time = prev->time = (bl_hilite_moves + iflags.hilite_delta);
+#endif
+            curr->chg = prev->chg = FALSE;
+        }
+
+        this_unhilite = curr->time;
+        if (this_unhilite > 0L
+            && (next_unhilite == 0L || this_unhilite < next_unhilite)
+#ifdef STATUS_HILITES
+            && hilite_reset_needed(curr, this_unhilite + 1L)
+#endif
+            )
+            next_unhilite = this_unhilite;
+    }
+    if (next_unhilite > 0L && next_unhilite < bl_hilite_moves)
+        context.botl = TRUE;
+}
+
 void
 status_initialize(reassessment)
 boolean
@@ -681,141 +839,24 @@ boolean
     const char *fieldname = (const char *) 0;
 
     if (!reassessment) {
+        if (blinit)
+            impossible("2nd status_initialize with full init.");
         init_blstats();
         (*windowprocs.win_status_init)();
         blinit = TRUE;
-#ifdef STATUS_HILITES
-        status_notify_windowport(TRUE);
-#endif
     }
     for (i = 0; i < MAXBLSTATS; ++i) {
         enum statusfields fld = initblstats[i].fld;
-
-        switch (fld) {
-        case BL_TITLE:
-            fieldfmt = "%s";
-            fieldname = "title";
-            status_enablefield(fld, fieldname, fieldfmt, TRUE);
-            break;
-        case BL_STR:
-            fieldfmt = " St:%s";
-            fieldname = "strength";
-            status_enablefield(fld, fieldname, fieldfmt, TRUE);
-            break;
-        case BL_DX:
-            fieldfmt = " Dx:%s";
-            fieldname = "dexterity";
-            status_enablefield(fld, fieldname, fieldfmt, TRUE);
-            break;
-        case BL_CO:
-            fieldfmt = " Co:%s";
-            fieldname = "constitution";
-            status_enablefield(fld, fieldname, fieldfmt, TRUE);
-            break;
-        case BL_IN:
-            fieldfmt = " In:%s";
-            fieldname = "intelligence";
-            status_enablefield(fld, fieldname, fieldfmt, TRUE);
-            break;
-        case BL_WI:
-            fieldfmt = " Wi:%s";
-            fieldname = "wisdom";
-            status_enablefield(fld, fieldname, fieldfmt, TRUE);
-            break;
-        case BL_CH:
-            fieldfmt = " Ch:%s";
-            fieldname = "charisma";
-            status_enablefield(fld, fieldname, fieldfmt, TRUE);
-            break;
-        case BL_ALIGN:
-            fieldfmt = " %s";
-            fieldname = "alignment";
-            status_enablefield(fld, fieldname, fieldfmt, TRUE);
-            break;
-        case BL_SCORE:
-            fieldfmt = " S:%s";
-            fieldname = "score";
-            status_enablefield(fld, fieldname, fieldfmt,
-                               (!flags.showscore) ? FALSE : TRUE);
-            break;
-        case BL_CAP:
-            fieldfmt = " %s";
-            fieldname = "carrying-capacity";
-            status_enablefield(fld, fieldname, fieldfmt, TRUE);
-            break;
-        case BL_GOLD:
-            fieldfmt = " %s";
-            fieldname = "gold";
-            status_enablefield(fld, fieldname, fieldfmt, TRUE);
-            break;
-        case BL_ENE:
-            fieldfmt = " Pw:%s";
-            fieldname = "power";
-            status_enablefield(fld, fieldname, fieldfmt, TRUE);
-            break;
-        case BL_ENEMAX:
-            fieldfmt = "(%s)";
-            fieldname = "power-max";
-            status_enablefield(fld, fieldname, fieldfmt, TRUE);
-            break;
-        case BL_XP:
-            fieldfmt = " Xp:%s";
-            fieldname = "experience-level";
-            status_enablefield(fld, fieldname, fieldfmt,
-                                   (Upolyd) ? FALSE : TRUE);
-            break;
-        case BL_AC:
-            fieldfmt = " AC:%s";
-            fieldname = "armor-class";
-            status_enablefield(fld, fieldname, fieldfmt, TRUE);
-            break;
-        case BL_HD:
-            fieldfmt = " HD:%s";
-            fieldname = "HD";
-            status_enablefield(fld, fieldname, fieldfmt,
-                                   (!Upolyd) ? FALSE : TRUE);
-            break;
-        case BL_TIME:
-            fieldfmt = " T:%s";
-            fieldname = "time";
-            status_enablefield(fld, fieldname, fieldfmt,
-                                   (!flags.time) ? FALSE : TRUE);
-            break;
-        case BL_HUNGER:
-            fieldfmt = " %s";
-            fieldname = "hunger";
-            status_enablefield(fld, fieldname, fieldfmt, TRUE);
-            break;
-        case BL_HP:
-            fieldfmt = " HP:%s";
-            fieldname = "hitpoints";
-            status_enablefield(fld, fieldname, fieldfmt, TRUE);
-            break;
-        case BL_HPMAX:
-            fieldfmt = "(%s)";
-            fieldname = "hitpoint-max";
-            status_enablefield(fld, fieldname, fieldfmt, TRUE);
-            break;
-        case BL_LEVELDESC:
-            fieldfmt = "%s";
-            fieldname = "dungeon-level";
-            status_enablefield(fld, fieldname, fieldfmt, TRUE);
-            break;
-        case BL_EXP:
-            fieldfmt = "/%s";
-            fieldname = "experience";
-            status_enablefield(fld, fieldname, fieldfmt,
-                                  (!flags.showexp || Upolyd) ? FALSE : TRUE);
-            break;
-        case BL_CONDITION:
-            fieldfmt = "%s";
-            fieldname = "condition";
-            status_enablefield(fld, fieldname, fieldfmt, TRUE);
-            break;
-        case BL_FLUSH:
-        default:
-            break;
-        }
+        boolean fldenabled = (fld == BL_SCORE) ? flags.showscore
+            : (fld == BL_XP) ? (boolean) !Upolyd
+            : (fld == BL_HD) ? (boolean) Upolyd
+            : (fld == BL_TIME) ? flags.time
+            : (fld == BL_EXP) ? (boolean) (flags.showexp && !Upolyd)
+            : TRUE;
+
+        fieldname = initblstats[i].fldname;
+        fieldfmt = initblstats[i].fldfmt;
+        status_enablefield(fld, fieldname, fieldfmt, fldenabled);
     }
     update_all = TRUE;
 }
@@ -831,9 +872,22 @@ status_finish()
     /* free memory that we alloc'd now */
     for (i = 0; i < MAXBLSTATS; ++i) {
         if (blstats[0][i].val)
-            free((genericptr_t) blstats[0][i].val);
+            free((genericptr_t) blstats[0][i].val), blstats[0][i].val = 0;
         if (blstats[1][i].val)
-            free((genericptr_t) blstats[1][i].val);
+            free((genericptr_t) blstats[1][i].val), blstats[1][i].val = 0;
+#ifdef STATUS_HILITES
+        if (blstats[0][i].thresholds) {
+            struct hilite_s *temp = blstats[0][i].thresholds,
+                            *next = (struct hilite_s *)0;
+            while (temp) {
+                next = temp->next;
+                free(temp);
+                blstats[0][i].thresholds = (struct hilite_s *)0;
+                blstats[1][i].thresholds = blstats[0][i].thresholds;
+                temp = next;
+            }
+       }
+#endif /* STATUS_HILITES */
     }
 }
 
@@ -851,6 +905,9 @@ init_blstats()
     initalready = TRUE;
     for (i = BEFORE; i <= NOW; ++i) {
         for (j = 0; j < MAXBLSTATS; ++j) {
+#ifdef STATUS_HILITES
+            struct hilite_s *keep_hilite_chain = blstats[i][j].thresholds;
+#endif
             blstats[i][j] = initblstats[j];
             blstats[i][j].a = zeroany;
             if (blstats[i][j].valwidth) {
@@ -858,10 +915,105 @@ init_blstats()
                 blstats[i][j].val[0] = '\0';
             } else
                 blstats[i][j].val = (char *) 0;
+#ifdef STATUS_HILITES
+            if (keep_hilite_chain)
+                blstats[i][j].thresholds = keep_hilite_chain;
+#endif
         }
     }
 }
 
+/*
+ * This compares the previous stat with the current stat,
+ * and returns one of the following results based on that:
+ *
+ *   if prev_value < new_value (stat went up, increased)
+ *      return 1
+ *
+ *   if prev_value > new_value (stat went down, decreased)
+ *      return  -1
+ *
+ *   if prev_value == new_value (stat stayed the same)
+ *      return 0
+ *
+ *   Special cases:
+ *     - for bitmasks, 0 = stayed the same, 1 = changed
+ *     - for strings,  0 = stayed the same, 1 = changed
+ *
+ */
+STATIC_OVL int
+compare_blstats(bl1, bl2)
+struct istat_s *bl1, *bl2;
+{
+    int anytype, result = 0;
+
+    if (!bl1 || !bl2) {
+        panic("compare_blstat: bad istat pointer %s, %s",
+              fmt_ptr((genericptr_t) bl1), fmt_ptr((genericptr_t) bl2));
+    }
+
+    anytype = bl1->anytype;
+    if ((!bl1->a.a_void || !bl2->a.a_void)
+        && (anytype == ANY_IPTR || anytype == ANY_UPTR || anytype == ANY_LPTR
+            || anytype == ANY_ULPTR)) {
+        panic("compare_blstat: invalid pointer %s, %s",
+              fmt_ptr((genericptr_t) bl1->a.a_void),
+              fmt_ptr((genericptr_t) bl2->a.a_void));
+    }
+
+    switch (anytype) {
+    case ANY_INT:
+        result = (bl1->a.a_int < bl2->a.a_int)
+                     ? 1
+                     : (bl1->a.a_int > bl2->a.a_int) ? -1 : 0;
+        break;
+    case ANY_IPTR:
+        result = (*bl1->a.a_iptr < *bl2->a.a_iptr)
+                     ? 1
+                     : (*bl1->a.a_iptr > *bl2->a.a_iptr) ? -1 : 0;
+        break;
+    case ANY_LONG:
+        result = (bl1->a.a_long < bl2->a.a_long)
+                     ? 1
+                     : (bl1->a.a_long > bl2->a.a_long) ? -1 : 0;
+        break;
+    case ANY_LPTR:
+        result = (*bl1->a.a_lptr < *bl2->a.a_lptr)
+                     ? 1
+                     : (*bl1->a.a_lptr > *bl2->a.a_lptr) ? -1 : 0;
+        break;
+    case ANY_UINT:
+        result = (bl1->a.a_uint < bl2->a.a_uint)
+                     ? 1
+                     : (bl1->a.a_uint > bl2->a.a_uint) ? -1 : 0;
+        break;
+    case ANY_UPTR:
+        result = (*bl1->a.a_uptr < *bl2->a.a_uptr)
+                     ? 1
+                     : (*bl1->a.a_uptr > *bl2->a.a_uptr) ? -1 : 0;
+        break;
+    case ANY_ULONG:
+        result = (bl1->a.a_ulong < bl2->a.a_ulong)
+                     ? 1
+                     : (bl1->a.a_ulong > bl2->a.a_ulong) ? -1 : 0;
+        break;
+    case ANY_ULPTR:
+        result = (*bl1->a.a_ulptr < *bl2->a.a_ulptr)
+                     ? 1
+                     : (*bl1->a.a_ulptr > *bl2->a.a_ulptr) ? -1 : 0;
+        break;
+    case ANY_STR:
+        result = sgn(strcmp(bl1->val, bl2->val));
+        break;
+    case ANY_MASK32:
+        result = (bl1->a.a_ulong != bl2->a.a_ulong);
+        break;
+    default:
+        result = 1;
+    }
+    return result;
+}
+
 STATIC_OVL char *
 anything_to_s(buf, a, anytype)
 char *buf;
@@ -908,8 +1060,6 @@ int anytype;
     return buf;
 }
 
-#ifdef STATUS_HILITES
-
 STATIC_OVL void
 s_to_anything(a, buf, anytype)
 anything *a;
@@ -958,129 +1108,68 @@ int anytype;
     return;
 }
 
-#endif
-
 STATIC_OVL int
-compare_blstats(bl1, bl2)
-struct istat_s *bl1, *bl2;
+percentage(bl, maxbl)
+struct istat_s *bl, *maxbl;
 {
-    int anytype, result = 0;
+    int result = 0;
+    int anytype;
+    int ival;
+    long lval;
+    unsigned uval;
+    unsigned long ulval;
 
-    if (!bl1 || !bl2) {
-        panic("compare_blstat: bad istat pointer %s, %s",
-              fmt_ptr((genericptr_t) bl1), fmt_ptr((genericptr_t) bl2));
+    if (!bl || !maxbl) {
+        impossible("percentage: bad istat pointer %s, %s",
+                   fmt_ptr((genericptr_t) bl), fmt_ptr((genericptr_t) maxbl));
+        return 0;
     }
 
-    anytype = bl1->anytype;
-    if ((!bl1->a.a_void || !bl2->a.a_void)
-        && (anytype == ANY_IPTR || anytype == ANY_UPTR || anytype == ANY_LPTR
-            || anytype == ANY_ULPTR)) {
-        panic("compare_blstat: invalid pointer %s, %s",
-              fmt_ptr((genericptr_t) bl1->a.a_void),
-              fmt_ptr((genericptr_t) bl2->a.a_void));
+    ival = 0, lval = 0L, uval = 0U, ulval = 0UL;
+    anytype = bl->anytype;
+    if (maxbl->a.a_void) {
+        switch (anytype) {
+        case ANY_INT:
+            ival = bl->a.a_int;
+            result = ((100 * ival) / maxbl->a.a_int);
+            break;
+        case ANY_LONG:
+            lval  = bl->a.a_long;
+            result = (int) ((100L * lval) / maxbl->a.a_long);
+            break;
+        case ANY_UINT:
+            uval = bl->a.a_uint;
+            result = (int) ((100U * uval) / maxbl->a.a_uint);
+            break;
+        case ANY_ULONG:
+            ulval = bl->a.a_ulong;
+            result = (int) ((100UL * ulval) / maxbl->a.a_ulong);
+            break;
+        case ANY_IPTR:
+            ival = *bl->a.a_iptr;
+            result = ((100 * ival) / (*maxbl->a.a_iptr));
+            break;
+        case ANY_LPTR:
+            lval = *bl->a.a_lptr;
+            result = (int) ((100L * lval) / (*maxbl->a.a_lptr));
+            break;
+        case ANY_UPTR:
+            uval = *bl->a.a_uptr;
+            result = (int) ((100U * uval) / (*maxbl->a.a_uptr));
+            break;
+        case ANY_ULPTR:
+            ulval = *bl->a.a_ulptr;
+            result = (int) ((100UL * ulval) / (*maxbl->a.a_ulptr));
+            break;
+        }
     }
+    /* don't let truncation from integer division produce a zero result
+       from a non-zero input; note: if we ever change to something like
+       ((((1000 * val) / max) + 5) / 10) for a rounded result, we'll
+       also need to check for and convert false 100 to 99 */
+    if (result == 0 && (ival != 0 || lval != 0L || uval != 0U || ulval != 0UL))
+        result = 1;
 
-    switch (anytype) {
-    case ANY_INT:
-        result = (bl1->a.a_int < bl2->a.a_int)
-                     ? 1
-                     : (bl1->a.a_int > bl2->a.a_int) ? -1 : 0;
-        break;
-    case ANY_IPTR:
-        result = (*bl1->a.a_iptr < *bl2->a.a_iptr)
-                     ? 1
-                     : (*bl1->a.a_iptr > *bl2->a.a_iptr) ? -1 : 0;
-        break;
-    case ANY_LONG:
-        result = (bl1->a.a_long < bl2->a.a_long)
-                     ? 1
-                     : (bl1->a.a_long > bl2->a.a_long) ? -1 : 0;
-        break;
-    case ANY_LPTR:
-        result = (*bl1->a.a_lptr < *bl2->a.a_lptr)
-                     ? 1
-                     : (*bl1->a.a_lptr > *bl2->a.a_lptr) ? -1 : 0;
-        break;
-    case ANY_UINT:
-        result = (bl1->a.a_uint < bl2->a.a_uint)
-                     ? 1
-                     : (bl1->a.a_uint > bl2->a.a_uint) ? -1 : 0;
-        break;
-    case ANY_UPTR:
-        result = (*bl1->a.a_uptr < *bl2->a.a_uptr)
-                     ? 1
-                     : (*bl1->a.a_uptr > *bl2->a.a_uptr) ? -1 : 0;
-        break;
-    case ANY_ULONG:
-        result = (bl1->a.a_ulong < bl2->a.a_ulong)
-                     ? 1
-                     : (bl1->a.a_ulong > bl2->a.a_ulong) ? -1 : 0;
-        break;
-    case ANY_ULPTR:
-        result = (*bl1->a.a_ulptr < *bl2->a.a_ulptr)
-                     ? 1
-                     : (*bl1->a.a_ulptr > *bl2->a.a_ulptr) ? -1 : 0;
-        break;
-    case ANY_STR:
-        if (strcmp(bl1->val, bl2->val) == 0)
-            result = 0;
-        else
-            result = 1;
-        break;
-    case ANY_MASK32:
-        if (bl1->a.a_ulong == bl2->a.a_ulong)
-            result = 0;
-        else
-            result = 1;
-        break;
-    default:
-        result = 1;
-    }
-    return result;
-}
-
-STATIC_OVL int
-percentage(bl, maxbl)
-struct istat_s *bl, *maxbl;
-{
-    int result = 0;
-    int anytype;
-
-    if (!bl || !maxbl) {
-        impossible("percentage: bad istat pointer %s, %s",
-                   fmt_ptr((genericptr_t) bl), fmt_ptr((genericptr_t) maxbl));
-        return 0;
-    }
-
-    anytype = bl->anytype;
-    if (maxbl->a.a_void) {
-        switch (anytype) {
-        case ANY_INT:
-            result = ((100 * bl->a.a_int) / maxbl->a.a_int);
-            break;
-        case ANY_LONG:
-            result = (int) ((100L * bl->a.a_long) / maxbl->a.a_long);
-            break;
-        case ANY_UINT:
-            result = (int) ((100U * bl->a.a_uint) / maxbl->a.a_uint);
-            break;
-        case ANY_ULONG:
-            result = (int) ((100UL * bl->a.a_ulong) / maxbl->a.a_ulong);
-            break;
-        case ANY_IPTR:
-            result = ((100 * (*bl->a.a_iptr)) / (*maxbl->a.a_iptr));
-            break;
-        case ANY_LPTR:
-            result = (int) ((100L * (*bl->a.a_lptr)) / (*maxbl->a.a_lptr));
-            break;
-        case ANY_UPTR:
-            result = (int) ((100U * (*bl->a.a_uptr)) / (*maxbl->a.a_uptr));
-            break;
-        case ANY_ULPTR:
-            result = (int) ((100UL * (*bl->a.a_ulptr)) / (*maxbl->a.a_ulptr));
-            break;
-        }
-    }
     return result;
 }
 
@@ -1091,78 +1180,309 @@ struct istat_s *bl, *maxbl;
 /* Core status hiliting support */
 /****************************************************************************/
 
+struct hilite_s status_hilites[MAXBLSTATS];
+
 static struct fieldid_t {
     const char *fieldname;
     enum statusfields fldid;
-} fieldids[] = {
-    {"title",               BL_TITLE},
-    {"strength",            BL_STR},
-    {"dexterity",           BL_DX},
-    {"constitution",        BL_CO},
-    {"intelligence",        BL_IN},
-    {"wisdom",              BL_WI},
-    {"charisma",            BL_CH},
-    {"alignment",           BL_ALIGN},
-    {"score",               BL_SCORE},
-    {"carrying-capacity",   BL_CAP},
-    {"gold",                BL_GOLD},
-    {"power",               BL_ENE},
-    {"power-max",           BL_ENEMAX},
-    {"experience-level",    BL_XP},
-    {"armor-class",         BL_AC},
-    {"HD",                  BL_HD},
-    {"time",                BL_TIME},
-    {"hunger",              BL_HUNGER},
-    {"hitpoints",           BL_HP},
-    {"hitpoints-max",       BL_HPMAX},
-    {"dungeon-level",       BL_LEVELDESC},
-    {"experience",          BL_EXP},
-    {"condition",           BL_CONDITION},
+} fieldids_alias[] = {
+    {"characteristics", BL_CHARACTERISTICS},
+    {"dx",       BL_DX},
+    {"co",       BL_CO},
+    {"con",      BL_CO},
+    {"points",   BL_SCORE},
+    {"cap",      BL_CAP},
+    {"pw",       BL_ENE},
+    {"pw-max",   BL_ENEMAX},
+    {"xl",       BL_XP},
+    {"xplvl",    BL_XP},
+    {"ac",       BL_AC},
+    {"hit-dice", BL_HD},
+    {"turns",    BL_TIME},
+    {"hp",       BL_HP},
+    {"hp-max",   BL_HPMAX},
+    {"dgn",      BL_LEVELDESC},
+    {"xp",       BL_EXP},
+    {"exp",      BL_EXP},
+    {"flags",    BL_CONDITION},
+    {0,          BL_FLUSH}
 };
 
-struct hilite_s {
-    boolean set;
-    unsigned anytype;
-    anything threshold;
-    int behavior;
-    int coloridx[2];
-};
+/* field name to bottom line index */
+STATIC_OVL enum statusfields
+fldname_to_bl_indx(name)
+const char *name;
+{
+    int i, nmatches = 0, fld = 0;
+
+    if (name && *name) {
+        /* check matches to canonical names */
+        for (i = 0; i < SIZE(initblstats); i++)
+            if (fuzzymatch(initblstats[i].fldname, name, " -_", TRUE)) {
+                fld = initblstats[i].fld;
+                nmatches++;
+            }
+
+        if (!nmatches) {
+            /* check aliases */
+            for (i = 0; fieldids_alias[i].fieldname; i++)
+                if (fuzzymatch(fieldids_alias[i].fieldname, name,
+                               " -_", TRUE)) {
+                    fld = fieldids_alias[i].fldid;
+                    nmatches++;
+                }
+        }
+
+        if (!nmatches) {
+            /* check partial matches to canonical names */
+            int len = (int) strlen(name);
+            for (i = 0; i < SIZE(initblstats); i++)
+                if (!strncmpi(name, initblstats[i].fldname, len)) {
+                    fld = initblstats[i].fld;
+                    nmatches++;
+                }
+        }
+
+    }
+    return (nmatches == 1) ? fld : BL_FLUSH;
+}
+
+STATIC_OVL boolean
+hilite_reset_needed(bl_p, augmented_time)
+struct istat_s *bl_p;
+long augmented_time;
+{
+    struct hilite_s *tl = bl_p->thresholds;
+
+    /*
+     * This 'multi' handling may need some tuning...
+     */
+    if (multi)
+        return FALSE;
+
+    if (bl_p->time == 0 || bl_p->time >= augmented_time)
+        return FALSE;
+
+    while (tl) {
+        /* only this style times out */
+        if (tl->behavior == BL_TH_UPDOWN)
+            return TRUE;
+        tl = tl->next;
+    }
+
+    return FALSE;
+}
+
+/* called by options handling when 'statushilites' boolean is toggled */
+void
+reset_status_hilites()
+{
+    if (iflags.hilite_delta) {
+        int i;
+
+        for (i = 0; i < MAXBLSTATS; ++i)
+            blstats[0][i].time = blstats[1][i].time = 0L;
+        update_all = TRUE;
+    }
+    context.botlx = TRUE;
+}
+
+STATIC_OVL void
+merge_bestcolor(bestcolor, newcolor)
+int *bestcolor;
+int newcolor;
+{
+    int batr, bclr, natr, nclr;
+
+    split_clridx(*bestcolor, &bclr, &batr);
+    split_clridx(newcolor, &nclr, &natr);
+
+    if (nclr != NO_COLOR)
+        *bestcolor = (*bestcolor & 0xff00) | nclr;
+
+    if (natr != HL_UNDEF) {
+        if (natr == HL_NONE)
+            *bestcolor = *bestcolor & 0x00ff; /* reset all attributes */
+        else
+            *bestcolor |= (natr << 8); /* merge attributes */
+    }
+}
+
+/*
+ * get_hilite_color
+ * 
+ * Figures out, based on the value and the
+ * direction it is moving, the color that the field
+ * should be displayed in.
+ *
+ *
+ * Provide get_hilite_color() with the following
+ * to work with:
+ *     actual value vp
+ *          useful for BL_TH_VAL_ABSOLUTE
+ *     indicator of down, up, or the same (-1, 1, 0) chg
+ *          useful for BL_TH_UPDOWN or change detection
+ *     percentage (current value percentage of max value) pc
+ *          useful for BL_TH_VAL_PERCENTAGE
+ *
+ * Get back:
+ *     color     based on user thresholds set in config file.
+ *               The rightmost 8 bits contain a color index.
+ *               The 8 bits to the left of that contain
+ *               the attribute bits.
+ *                   color = 0x00FF
+ *                   attrib= 0xFF00
+ */
+
+STATIC_OVL void
+get_hilite_color(idx, fldidx, vp, chg, pc, colorptr)
+int idx, fldidx, chg, pc;
+genericptr_t vp;
+int *colorptr;
+{
+    int bestcolor = NO_COLOR;
+    struct hilite_s *hl;
+    anything *value = (anything *)vp;
+    char *txtstr, *cmpstr;
+
+    if (!colorptr || fldidx < 0 || fldidx >= MAXBLSTATS)
+        return;
+
+    if (blstats[idx][fldidx].thresholds) {
+        /* there are hilites set here */
+        int max_pc = 0, min_pc = 100;
+        int max_val = 0, min_val = LARGEST_INT;
+        boolean changed = FALSE;
+        boolean exactmatch = FALSE;
+
+        hl = blstats[idx][fldidx].thresholds;
+
+        while (hl) {
+            switch (hl->behavior) {
+            case BL_TH_VAL_PERCENTAGE:
+                if (hl->rel == EQ_VALUE && pc == hl->value.a_int) {
+                    merge_bestcolor(&bestcolor, hl->coloridx);
+                    min_pc = max_pc = hl->value.a_int;
+                    exactmatch = TRUE;
+                } else if (hl->rel == LT_VALUE && !exactmatch
+                           && (hl->value.a_int >= pc)
+                           && (hl->value.a_int <= min_pc)) {
+                    merge_bestcolor(&bestcolor, hl->coloridx);
+                    min_pc = hl->value.a_int;
+                } else if (hl->rel == GT_VALUE && !exactmatch
+                           && (hl->value.a_int <= pc)
+                           && (hl->value.a_int >= max_pc)) {
+                    merge_bestcolor(&bestcolor, hl->coloridx);
+                    max_pc = hl->value.a_int;
+                }
+                break;
+            case BL_TH_UPDOWN:
+                if (chg < 0 && hl->rel == LT_VALUE) {
+                    merge_bestcolor(&bestcolor, hl->coloridx);
+                    changed = TRUE;
+                } else if (chg > 0 && hl->rel == GT_VALUE) {
+                    merge_bestcolor(&bestcolor, hl->coloridx);
+                    changed = TRUE;
+                } else if (hl->rel == EQ_VALUE && chg) {
+                    merge_bestcolor(&bestcolor, hl->coloridx);
+                    min_val = max_val = hl->value.a_int;
+                    changed = TRUE;
+                }
+                break;
+            case BL_TH_VAL_ABSOLUTE:
+                if (hl->rel == EQ_VALUE && hl->value.a_int == value->a_int) {
+                    merge_bestcolor(&bestcolor, hl->coloridx);
+                    min_val = max_val = hl->value.a_int;
+                    exactmatch = TRUE;
+                } else if (hl->rel == LT_VALUE && !exactmatch
+                           && (hl->value.a_int >= value->a_int)
+                           && (hl->value.a_int < min_val)) {
+                    merge_bestcolor(&bestcolor, hl->coloridx);
+                    min_val = hl->value.a_int;
+                } else if (hl->rel == GT_VALUE && !exactmatch
+                           && (hl->value.a_int <= value->a_int)
+                           && (hl->value.a_int > max_val)) {
+                    merge_bestcolor(&bestcolor, hl->coloridx);
+                    max_val = hl->value.a_int;
+                }
+                break;
+            case BL_TH_TEXTMATCH:
+                txtstr = dupstr(blstats[idx][fldidx].val);
+                cmpstr = txtstr;
+                if (fldidx == BL_TITLE) {
+                    int len = (strlen(plname) + sizeof(" the"));
+                    cmpstr += len;
+                }
+                (void) trimspaces(cmpstr);
+                if (hl->rel == TXT_VALUE && hl->textmatch[0] &&
+                    !strcmpi(hl->textmatch, cmpstr)) {
+                    merge_bestcolor(&bestcolor, hl->coloridx);
+                }
+                free(txtstr);
+                break;
+            case BL_TH_ALWAYS_HILITE:
+                merge_bestcolor(&bestcolor, hl->coloridx);
+                break;
+            case BL_TH_NONE:
+                break;
+            default:
+                break;
+            }
+            hl = hl->next;
+       }
+    }
+    *colorptr = bestcolor;
+    return;
+}
+
+STATIC_OVL void
+split_clridx(idx, coloridx, attrib)
+int idx;
+int *coloridx, *attrib;
+{
+    if (idx && coloridx && attrib) {
+           *coloridx = idx & 0x00FF;
+           *attrib = (idx & 0xFF00) >> 8;
+    }
+}
 
-struct hilite_s status_hilites[MAXBLSTATS];
 
 /*
  * This is the parser for the hilite options
- * Example:
- *    OPTION=hilite_status: hitpoints/10%/red/normal
  *
- * set_hilite_status() separates each hilite entry into its 4 component
- * strings, then calls assign_hilite() to make the adjustments.
+ * parse_status_hl1() separates each hilite entry into
+ * a set of field threshold/action component strings,
+ * then calls parse_status_hl2() to parse further
+ * and configure the hilite.
  */
 boolean
-set_status_hilites(op, from_configfile)
+parse_status_hl1(op, from_configfile)
 char *op;
 boolean from_configfile;
 {
-    char hsbuf[4][QBUFSZ];
+#define MAX_THRESH 21
+    char hsbuf[MAX_THRESH][QBUFSZ];
     boolean rslt, badopt = FALSE;
-    int fldnum, num = 0, ccount = 0;
+    int i, fldnum, ccount = 0;
     char c;
 
-    num = fldnum = 0;
-    hsbuf[0][0] = hsbuf[1][0] = hsbuf[2][0] = hsbuf[3][0] = '\0';
-    while (*op && fldnum < 4 && ccount < (QBUFSZ - 2)) {
+    fldnum = 0;
+    for (i = 0; i < MAX_THRESH; ++i) {
+        hsbuf[i][0] = '\0';
+    }
+    while (*op && fldnum < MAX_THRESH && ccount < (QBUFSZ - 2)) {
         c = lowc(*op);
         if (c == ' ') {
-            if (fldnum >= 2) {
-                rslt = assign_hilite(&hsbuf[0][0], &hsbuf[1][0], &hsbuf[2][0],
-                                     &hsbuf[3][0], from_configfile);
+            if (fldnum >= 1) {
+                rslt = parse_status_hl2(hsbuf, from_configfile);
                 if (!rslt) {
                     badopt = TRUE;
                     break;
                 }
             }
-            hsbuf[0][0] = hsbuf[1][0] = '\0';
-            hsbuf[2][0] = hsbuf[3][0] = '\0';
+            for (i = 0; i < MAX_THRESH; ++i) {
+                hsbuf[i][0] = '\0';
+            }
             fldnum = 0;
             ccount = 0;
         } else if (c == '/') {
@@ -1174,9 +1494,8 @@ boolean from_configfile;
         }
         op++;
     }
-    if (fldnum >= 2 && !badopt) {
-        rslt = assign_hilite(&hsbuf[0][0], &hsbuf[1][0], &hsbuf[2][0],
-                             &hsbuf[3][0], from_configfile);
+    if (fldnum >= 1 && !badopt) {
+        rslt = parse_status_hl2(hsbuf, from_configfile);
         if (!rslt)
             badopt = TRUE;
     }
@@ -1185,453 +1504,1737 @@ boolean from_configfile;
     return TRUE;
 }
 
-void
-clear_status_hilites(from_configfile)
-boolean from_configfile;
+/* is str in the format of "(<>)?[0-9]+%?" regex */
+STATIC_OVL boolean
+is_ltgt_percentnumber(str)
+const char *str;
 {
-    int i;
-    anything it;
+    const char *s = str;
 
-    it = zeroany;
-    for (i = 0; i < MAXBLSTATS; ++i) {
-        (void) memset((genericptr_t) &status_hilites[i], 0,
-                      sizeof(struct hilite_s));
-        /* notify window port */
-        if (!from_configfile)
-            status_threshold(i, blstats[0][i].anytype, it, 0, 0, 0);
-    }
+    if (*s == '<' || *s == '>') s++;
+    while (digit(*s)) s++;
+    if (*s == '%') s++;
+
+    return (*s == '\0');
 }
 
+/* does str only contain "<>0-9%" chars */
 STATIC_OVL boolean
-assign_hilite(sa, sb, sc, sd, from_configfile)
-char *sa, *sb, *sc, *sd;
-boolean from_configfile;
+has_ltgt_percentnumber(str)
+const char *str;
 {
-    char *tmp, *how;
-    int i = -1, dt = -1, idx = -1;
-    int coloridx[2] = { -1, -1 };
-    boolean inverse[2] = { FALSE, FALSE };
-    boolean bold[2] = { FALSE, FALSE };
-    boolean normal[2] = { 0, 0 };
-    boolean percent = FALSE, down_up = FALSE, changed = FALSE;
-    anything threshold;
-    enum statusfields fld = BL_FLUSH;
-    threshold.a_void = 0;
-
-    /* Example:
-     *  hilite_status: hitpoints/10%/red/normal
-     */
-
-    /* field name to statusfield */
-    for (i = 0; sa && i < SIZE(fieldids); ++i) {
-        if (strcmpi(sa, fieldids[i].fieldname) == 0) {
-            idx = i;
-            fld = fieldids[i].fldid;
-            break;
-        }
-    }
-    if (idx == -1)
-        return FALSE;
-    status_hilites[idx].set = FALSE; /* mark it "unset" */
+    const char *s = str;
 
-    /* threshold */
-    if (!sb)
-        return FALSE;
-    if ((strcmpi(sb, "updown") == 0) || (strcmpi(sb, "downup") == 0)
-        || (strcmpi(sb, "up") == 0) || (strcmpi(sb, "down") == 0)) {
-        down_up = TRUE;
-    } else if ((strcmpi(sb, "changed") == 0)
-               && (fld == BL_TITLE || fld == BL_ALIGN || fld == BL_LEVELDESC
-                   || fld == BL_CONDITION)) {
-        changed = TRUE; /* changed is only thing allowed */
-    } else {
-        tmp = sb;
-        while (*tmp) {
-            if (*tmp == '%') {
-                *tmp = '\0';
-                percent = TRUE;
-                break;
-            } else if (!index("0123456789", *tmp))
-                return FALSE;
-            tmp++;
-        }
-        if (strlen(sb) > 0) {
-            dt = blstats[0][idx].anytype;
-            if (percent)
-                dt = ANY_INT;
-            (void) s_to_anything(&threshold, sb, dt);
-        } else
-            return FALSE;
-        if (percent && (threshold.a_int < 1 || threshold.a_int > 100))
-            return FALSE;
-        if (!threshold.a_void && (strcmp(sb, "0") != 0))
+    while (*s) {
+        if (!index("<>0123456789%", *s))
             return FALSE;
+        s++;
     }
+    return TRUE;
+}
 
-    /* actions */
-    for (i = 0; i < 2; ++i) {
-        how = !i ? sc : sd;
-        if (!how) {
-            if (!i)
-                return FALSE;
-            break; /* sc is mandatory; sd is not */
+/* splitsubfields(): splits str in place into '+' or '&' separated strings.
+ * returns number of strings, or -1 if more than maxsf or MAX_SUBFIELDS
+ */
+#define MAX_SUBFIELDS 16
+STATIC_OVL int
+splitsubfields(str, sfarr, maxsf)
+char *str;
+char ***sfarr;
+int maxsf;
+{
+    static char *subfields[MAX_SUBFIELDS];
+    char *st = (char *) 0;
+    int sf = 0;
+
+    if (!str)
+        return 0;
+    for (sf = 0; sf < MAX_SUBFIELDS; ++sf)
+        subfields[sf] = (char *) 0;
+
+    maxsf = (maxsf == 0) ? MAX_SUBFIELDS : min(maxsf, MAX_SUBFIELDS);
+
+    if (index(str, '+') || index(str, '&')) {
+        char *c = str;
+
+        sf = 0;
+        st = c;
+        while (*c && sf < maxsf) {
+            if (*c == '&' || *c == '+') {
+                *c = '\0';
+                subfields[sf] = st;
+                st = c+1;
+                sf++;
+            }
+            c++;
         }
+        if (sf >= maxsf - 1)
+            return -1;
+        if (!*c && c != st)
+            subfields[sf++] = st;
+    } else {
+        sf = 1;
+        subfields[0] = str;
+    }
+    *sfarr = subfields;
+    return sf;
+}
+#undef MAX_SUBFIELDS
 
-        if (strcmpi(how, "bold") == 0) {
-            bold[i] = TRUE;
-        } else if (strcmpi(how, "inverse") == 0) {
-            inverse[i] = TRUE;
-        } else if (strcmpi(how, "normal") == 0) {
-            normal[i] = TRUE;
-        } else {
-            int k = match_str2clr(how);
+boolean
+is_fld_arrayvalues(str, arr, arrmin, arrmax, retidx)
+const char *str;
+const char *const *arr;
+int arrmin, arrmax;
+int *retidx;
+{
+    int i;
 
-            if (k >= CLR_MAX)
-                return FALSE;
-            coloridx[i] = k;
+    for (i = arrmin; i < arrmax; i++)
+        if (!strcmpi(str, arr[i])) {
+            *retidx = i;
+            return TRUE;
         }
-    }
+    return FALSE;
+}
+
+int
+query_arrayvalue(querystr, arr, arrmin, arrmax)
+const char *querystr;
+const char *const *arr;
+int arrmin, arrmax;
+{
+    int i, res, ret = arrmin - 1;
+    winid tmpwin;
+    anything any;
+    menu_item *picks = (menu_item *) 0;
+    int adj = (arrmin > 0) ? 1 : arrmax;
 
-    /* Assign the values */
+    tmpwin = create_nhwindow(NHW_MENU);
+    start_menu(tmpwin);
 
-    for (i = 0; i < 2; ++i) {
-        if (inverse[i])
-            status_hilites[idx].coloridx[i] = BL_HILITE_INVERSE;
-        else if (bold[i])
-            status_hilites[idx].coloridx[i] = BL_HILITE_BOLD;
-        else if (coloridx[i])
-            status_hilites[idx].coloridx[i] = coloridx[i];
-        else
-            status_hilites[idx].coloridx[i] = BL_HILITE_NONE;
+    for (i = arrmin; i < arrmax; i++) {
+        any = zeroany;
+        any.a_int = i + adj;
+        add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
+                 arr[i], MENU_UNSELECTED);
     }
 
-    if (percent)
-        status_hilites[idx].behavior = BL_TH_VAL_PERCENTAGE;
-    else if (down_up)
-        status_hilites[idx].behavior = BL_TH_UPDOWN;
-    else if (threshold.a_void)
-        status_hilites[idx].behavior = BL_TH_VAL_ABSOLUTE;
-    else
-        status_hilites[idx].behavior = BL_TH_NONE;
+    end_menu(tmpwin, querystr);
 
-    if (status_hilites[idx].behavior != BL_TH_NONE) {
-        status_hilites[idx].threshold = threshold;
-        status_hilites[idx].set = TRUE;
+    res = select_menu(tmpwin, PICK_ONE, &picks);
+    destroy_nhwindow(tmpwin);
+    if (res > 0) {
+        ret = picks->item.a_int - adj;
+        free((genericptr_t) picks);
     }
-    status_hilites[idx].anytype = dt;
 
-    /* Now finally, we notify the window port */
-    if (!from_configfile)
-        status_threshold(idx, status_hilites[idx].anytype,
-                         status_hilites[idx].threshold,
-                         status_hilites[idx].behavior,
-                         status_hilites[idx].coloridx[0],
-                         status_hilites[idx].coloridx[1]);
-
-    return TRUE;
+    return ret;
 }
 
-/*ARGUSED*/
 void
-status_notify_windowport(all)
-boolean all UNUSED;
+status_hilite_add_threshold(fld, hilite)
+int fld;
+struct hilite_s *hilite;
 {
-    int idx;
-    anything it;
-
-    it = zeroany;
-    for (idx = 0; idx < MAXBLSTATS; ++idx) {
-        if (status_hilites[idx].set)
-            status_threshold(idx, status_hilites[idx].anytype,
-                             status_hilites[idx].threshold,
-                             status_hilites[idx].behavior,
-                             status_hilites[idx].coloridx[0],
-                             status_hilites[idx].coloridx[1]);
-        else
-            status_threshold(idx, blstats[0][idx].anytype, it, 0, 0, 0);
+    struct hilite_s *new_hilite;
+
+    if (!hilite)
+        return;
+
+    /* alloc and initialize a new hilite_s struct */
+    new_hilite = (struct hilite_s *) alloc(sizeof(struct hilite_s));
+    *new_hilite = *hilite;   /* copy struct */
+
+    new_hilite->set = TRUE;
+    new_hilite->fld = fld;
+    new_hilite->next = (struct hilite_s *)0;
 
+    /* Does that status field currently have any hilite thresholds? */
+    if (!blstats[0][fld].thresholds) {
+        blstats[0][fld].thresholds = new_hilite;
+    } else {
+        struct hilite_s *temp_hilite = blstats[0][fld].thresholds;
+        new_hilite->next = temp_hilite;
+        blstats[0][fld].thresholds = new_hilite;
+        /* sort_hilites(fld) */
     }
+    /* current and prev must both point at the same hilites */
+    blstats[1][fld].thresholds = blstats[0][fld].thresholds;
 }
 
-/*
- * get_status_hilites
- *
- * Returns a string containing all the status hilites in the
- * same format that is used to specify a status hilite preference
- * in the config file.
- */
-char *
-get_status_hilites(buf, bufsiz)
-char *buf;
-int bufsiz;
+
+STATIC_OVL boolean
+parse_status_hl2(s, from_configfile)
+char (*s)[QBUFSZ];
+boolean from_configfile;
 {
-    int i, j, k, coloridx;
-    const char *text = (char *) 0;
-    char tmp[BUFSZ], colorname[BUFSZ];
-    boolean val_percentage, val_absolute, up_down;
-    boolean added_one = FALSE;
+    char *tmp, *how;
+    int sidx = 0, i = -1, dt = -1;
+    int coloridx = -1, successes = 0;
+    int disp_attrib = 0;
+    boolean percent = FALSE, changed = FALSE, numeric = FALSE;
+    boolean down= FALSE, up = FALSE;
+    boolean gt = FALSE, lt = FALSE, eq = FALSE, neq = FALSE;
+    boolean txtval = FALSE;
+    boolean always = FALSE;
+    const char *txt;
+    enum statusfields fld = BL_FLUSH;
+    struct hilite_s hilite;
+    char tmpbuf[BUFSZ];
+    const char *aligntxt[] = {"chaotic", "neutral", "lawful"};
+    /* hu_stat[] from eat.c has trailing spaces which foul up comparisons */
+    const char *hutxt[] = {"Satiated", "", "Hungry", "Weak",
+                           "Fainting", "Fainted", "Starved"};
+
+    /* Examples:
+        3.6.1:
+      OPTION=hilite_status: hitpoints/<10%/red
+      OPTION=hilite_status: hitpoints/<10%/red/<5%/purple/1/red+blink+inverse
+      OPTION=hilite_status: experience/down/red/up/green
+      OPTION=hilite_status: cap/strained/yellow/overtaxed/orange
+      OPTION=hilite_status: title/always/blue
+      OPTION=hilite_status: title/blue
+    */
 
-    if (!buf)
-        return (char *) 0;
-    *buf = '\0';
+    /* field name to statusfield */
+    fld = fldname_to_bl_indx(s[sidx]);
 
-    bufsiz--; /* required trailing null */
-    for (i = 0; i < MAXBLSTATS; ++i) {
-        val_percentage = val_absolute = up_down = FALSE;
-        if (status_hilites[i].set) {
-            if (!added_one)
-                added_one = TRUE;
-            else {
-                Strcat(buf, " ");
-                bufsiz--;
-            }
-            k = strlen(fieldids[i].fieldname);
-            if (k < bufsiz) {
-                Strcat(buf, fieldids[i].fieldname);
-                bufsiz -= k;
-            }
-            if (bufsiz > 1) {
-                Strcat(buf, "/");
-                bufsiz--;
-            }
-            if (status_hilites[i].behavior == BL_TH_VAL_PERCENTAGE) {
-                val_percentage = TRUE;
-            } else if (status_hilites[i].behavior == BL_TH_VAL_ABSOLUTE) {
-                val_absolute = TRUE;
-            } else if (status_hilites[i].behavior == BL_TH_UPDOWN) {
-                up_down = TRUE;
-                text = "updown";
-            }
+    if (fld == BL_CHARACTERISTICS) {
+        boolean res = FALSE;
 
-            if (status_hilites[i].behavior != BL_TH_UPDOWN) {
-                anything_to_s(tmp, &status_hilites[i].threshold,
-                          blstats[0][i].anytype);
-                text = tmp;
-            }
-            k = strlen(text);
-            if (k < (bufsiz - 1)) {
-                Strcat(buf, text);
-                if (val_percentage)
-                    Strcat(buf, "%"), k++;
-                bufsiz -= k;
-            }
-            for (j = 0; j < 2; ++j) {
-                if (bufsiz > 1) {
-                    Strcat(buf, "/");
-                    bufsiz--;
-                }
-                coloridx = status_hilites[i].coloridx[j];
-                if (coloridx < 0) {
-                    if (coloridx == BL_HILITE_BOLD)
-                        text = "bold";
-                    else if (coloridx == BL_HILITE_INVERSE)
-                        text = "inverse";
-                    else
-                        text = "normal";
-                } else {
-                    char *blank;
-
-                    (void) strcpy(colorname, c_obj_colors[coloridx]);
-                    for (blank = index(colorname, ' '); blank;
-                         blank = index(colorname, ' '))
-                        *blank = '-';
-                    text = colorname;
-                }
-                k = strlen(text);
-                if (k < bufsiz) {
-                    Strcat(buf, text);
-                    bufsiz -= k;
-                }
-            }
+        /* recursively set each of strength, dexterity, constitution, &c */
+        for (fld = BL_STR; fld <= BL_CH; fld++) {
+            Strcpy(s[sidx], initblstats[fld].fldname);
+            res = parse_status_hl2(s, from_configfile);
+            if (!res)
+                return FALSE;
         }
+        return TRUE;
     }
-    return buf;
-}
-
-STATIC_OVL const char *
-clridx_to_s(buf, idx)
-char *buf;
-int idx;
-{
-    static const char *a[] = { "bold", "inverse", "normal" };
-    char* p = 0;
-
-    if (buf) {
-        buf[0] = '\0';
-        if (idx < 0 && idx >= BL_HILITE_BOLD)
-            Strcpy(buf, a[idx + 3]);
-        else if (idx >= 0 && idx < CLR_MAX)
-            Strcpy(buf, c_obj_colors[idx]);
-        /* replace spaces with - */
-        for(p = buf; *p; p++)
-            if(*p == ' ') *p = '-';
+    if (fld == BL_FLUSH) {
+        config_error_add("Unknown status field '%s'", s[sidx]);
+        return FALSE;
     }
-    return buf;
-}
-
-boolean
-status_hilite_menu()
+    if (fld == BL_CONDITION)
+        return parse_condition(s, sidx);
+
+    ++sidx;
+    while(s[sidx]) {
+        char buf[BUFSZ], **subfields;
+        int sf = 0;     /* subfield count */
+        int kidx;
+
+        txt = (const char *)0;
+        percent = changed = numeric = FALSE;
+        down = up = FALSE;
+        gt = eq = lt = neq = txtval = FALSE;
+        always = FALSE;
+
+        /* threshold value */
+        if (!s[sidx][0])
+            return TRUE;
+
+        memset((genericptr_t) &hilite, 0, sizeof(struct hilite_s));
+        hilite.set = FALSE; /* mark it "unset" */
+        hilite.fld = fld;
+
+        if (*s[sidx+1] == '\0' || !strcmpi(s[sidx], "always")) {
+            /* "field/always/color" OR "field/color" */
+            always = TRUE;
+            if (*s[sidx+1] == '\0')
+                sidx--;
+            goto do_rel;
+        } else if (!strcmpi(s[sidx], "up") || !strcmpi(s[sidx], "down")) {
+            if (!strcmpi(s[sidx], "down"))
+                down = TRUE;
+            else
+                up = TRUE;
+            changed = TRUE;
+            goto do_rel;
+       } else if (fld == BL_CAP
+                   && is_fld_arrayvalues(s[sidx], enc_stat,
+                                         SLT_ENCUMBER, OVERLOADED+1, &kidx)) {
+            txt = enc_stat[kidx];
+            txtval = TRUE;
+           goto do_rel;
+        } else if (fld == BL_ALIGN
+                   && is_fld_arrayvalues(s[sidx], aligntxt, 0, 3, &kidx)) {
+            txt = aligntxt[kidx];
+            txtval = TRUE;
+            goto do_rel;
+        } else if (fld == BL_HUNGER
+                   && is_fld_arrayvalues(s[sidx], hutxt,
+                                         SATIATED, STARVED+1, &kidx)) {
+            txt = hu_stat[kidx];   /* store hu_stat[] val, not hutxt[] */
+            txtval = TRUE;
+            goto do_rel;
+        } else if (!strcmpi(s[sidx], "changed")) {
+            changed = TRUE;
+            goto do_rel;
+        } else if (is_ltgt_percentnumber(s[sidx])) {
+            tmp = s[sidx];
+            if (strchr(tmp, '%'))
+               percent = TRUE;
+            if (strchr(tmp, '<'))
+                lt = TRUE;
+            if (strchr(tmp, '>'))
+                gt = TRUE;
+            (void) stripchars(tmpbuf, "%<>", tmp);
+            tmp = tmpbuf;
+            while (*tmp) {
+                if (!index("0123456789", *tmp))
+                    return FALSE;
+                tmp++;
+            }
+            numeric = TRUE;
+            tmp = tmpbuf;
+            if (strlen(tmp) > 0) {
+                dt = blstats[0][fld].anytype;
+                if (percent)
+                    dt = ANY_INT;
+                (void) s_to_anything(&hilite.value, tmp, dt);
+            } else
+                return FALSE;
+            if (!hilite.value.a_void && (strcmp(tmp, "0") != 0))
+               return FALSE;
+        } else if (initblstats[fld].anytype == ANY_STR) {
+            txt = s[sidx];
+            txtval = TRUE;
+            goto do_rel;
+        } else {
+            config_error_add(has_ltgt_percentnumber(s[sidx])
+                 ? "Wrong format '%s', expected a threshold number or percent"
+                 : "Unknown behavior '%s'", s[sidx]);
+            return FALSE;
+        }
+do_rel:
+        /* relationships { LT_VALUE, GT_VALUE, EQ_VALUE} */
+        if (gt)
+            hilite.rel = GT_VALUE;
+        else if (eq)
+            hilite.rel = EQ_VALUE;
+        else if (lt)
+            hilite.rel = LT_VALUE;
+        else if (percent)
+            hilite.rel = EQ_VALUE;
+        else if (numeric)
+            hilite.rel = EQ_VALUE;
+        else if (down)
+            hilite.rel = LT_VALUE;
+        else if (up)
+            hilite.rel = GT_VALUE;
+        else if (changed)
+            hilite.rel = EQ_VALUE;
+        else if (txtval)
+            hilite.rel = TXT_VALUE;
+        else
+            hilite.rel = LT_VALUE;
+
+        if (initblstats[fld].anytype == ANY_STR
+            && (percent || numeric)) {
+            config_error_add("Field '%s' does not support numeric values",
+                             initblstats[fld].fldname);
+            return FALSE;
+        }
+
+        if (percent) {
+            if (initblstats[fld].idxmax <= BL_FLUSH) {
+                config_error_add("Cannot use percent with '%s'",
+                                 initblstats[fld].fldname);
+                return FALSE;
+            } else if ((hilite.value.a_int < 0)
+                       || (hilite.value.a_int == 0
+                           && hilite.rel == LT_VALUE)
+                       || (hilite.value.a_int > 100)
+                       || (hilite.value.a_int == 100
+                           && hilite.rel == GT_VALUE)) {
+                config_error_add("Illegal percentage value");
+                return FALSE;
+            }
+        }
+
+        /* actions */
+        sidx++;
+        how = s[sidx];
+        if (!how) {
+            if (!successes)
+                return FALSE;
+        }
+        coloridx = -1;
+        Strcpy(buf, how);
+        sf = splitsubfields(buf, &subfields, 0);
+
+        if (sf < 1)
+            return FALSE;
+
+        disp_attrib = HL_UNDEF;
+
+        for (i = 0; i < sf; ++i) {
+            int a = match_str2attr(subfields[i], FALSE);
+            if (a == ATR_DIM)
+                disp_attrib |= HL_DIM;
+            else if (a == ATR_BLINK)
+                disp_attrib |= HL_BLINK;
+            else if (a == ATR_ULINE)
+                disp_attrib |= HL_ULINE;
+            else if (a == ATR_INVERSE)
+                disp_attrib |= HL_INVERSE;
+            else if (a == ATR_BOLD)
+                disp_attrib |= HL_BOLD;
+            else if (a == ATR_NONE)
+                disp_attrib = HL_NONE;
+            else {
+                int c = match_str2clr(subfields[i]);
+
+                if (c >= CLR_MAX || coloridx != -1)
+                    return FALSE;
+                coloridx = c;
+           }
+        }
+        if (coloridx == -1)
+            coloridx = NO_COLOR;
+
+        /* Assign the values */
+        hilite.coloridx = coloridx | (disp_attrib << 8);
+
+        if (always)
+            hilite.behavior = BL_TH_ALWAYS_HILITE;
+        else if (percent)
+            hilite.behavior = BL_TH_VAL_PERCENTAGE;
+        else if (changed)
+            hilite.behavior = BL_TH_UPDOWN;
+        else if (numeric)
+            hilite.behavior = BL_TH_VAL_ABSOLUTE;
+        else if (txtval)
+            hilite.behavior = BL_TH_TEXTMATCH;
+        else if (hilite.value.a_void)
+            hilite.behavior = BL_TH_VAL_ABSOLUTE;
+       else
+            hilite.behavior = BL_TH_NONE;
+
+        hilite.anytype = dt;
+
+        if (hilite.behavior == BL_TH_TEXTMATCH && txt
+            && strlen(txt) < QBUFSZ-1) {
+            Strcpy(hilite.textmatch, txt);
+            (void) trimspaces(hilite.textmatch);
+        }
+
+        status_hilite_add_threshold(fld, &hilite);
+
+        successes++;
+        sidx++;
+    }
+
+    return TRUE;
+}
+
+
+
+const struct condmap valid_conditions[] = {
+    {"stone",    BL_MASK_STONE},
+    {"slime",    BL_MASK_SLIME},
+    {"strngl",   BL_MASK_STRNGL},
+    {"foodPois", BL_MASK_FOODPOIS},
+    {"termIll",  BL_MASK_TERMILL},
+    {"blind",    BL_MASK_BLIND},
+    {"deaf",     BL_MASK_DEAF},
+    {"stun",     BL_MASK_STUN},
+    {"conf",     BL_MASK_CONF},
+    {"hallu",    BL_MASK_HALLU},
+    {"lev",      BL_MASK_LEV},
+    {"fly",      BL_MASK_FLY},
+    {"ride",     BL_MASK_RIDE},
+};
+
+const struct condmap condition_aliases[] = {
+    {"strangled",      BL_MASK_STRNGL},
+    {"all",            BL_MASK_STONE | BL_MASK_SLIME | BL_MASK_STRNGL |
+                       BL_MASK_FOODPOIS | BL_MASK_TERMILL |
+                       BL_MASK_BLIND | BL_MASK_DEAF | BL_MASK_STUN |
+                       BL_MASK_CONF | BL_MASK_HALLU |
+                       BL_MASK_LEV | BL_MASK_FLY | BL_MASK_RIDE },
+    {"major_troubles", BL_MASK_STONE | BL_MASK_SLIME | BL_MASK_STRNGL |
+                       BL_MASK_FOODPOIS | BL_MASK_TERMILL},
+    {"minor_troubles", BL_MASK_BLIND | BL_MASK_DEAF | BL_MASK_STUN |
+                       BL_MASK_CONF | BL_MASK_HALLU},
+    {"movement",       BL_MASK_LEV | BL_MASK_FLY | BL_MASK_RIDE}
+};
+
+unsigned long
+query_conditions()
 {
-    int i, j, k, pick_cnt, pick_idx, opt_idx;
-    menu_item *statfield_picks = (menu_item *) 0;
-    const char *fieldname;
-    int field_picks[MAXBLSTATS], res;
-    struct hilite_s hltemp[MAXBLSTATS];
-    char buf[BUFSZ], thresholdbuf[BUFSZ], below[BUFSZ], above[BUFSZ];
+    int i,res;
+    unsigned long ret = 0UL;
     winid tmpwin;
     anything any;
+    menu_item *picks = (menu_item *) 0;
 
     tmpwin = create_nhwindow(NHW_MENU);
     start_menu(tmpwin);
+
+    for (i = 0; i < SIZE(valid_conditions); i++) {
+        any = zeroany;
+        any.a_ulong = valid_conditions[i].bitmask;
+        add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
+                 valid_conditions[i].id, MENU_UNSELECTED);
+    }
+
+    end_menu(tmpwin, "Choose status conditions");
+
+    res = select_menu(tmpwin, PICK_ANY, &picks);
+    destroy_nhwindow(tmpwin);
+    if (res > 0) {
+        for (i = 0; i < res; i++)
+            ret |= picks[i].item.a_ulong;
+        free((genericptr_t) picks);
+    }
+    return ret;
+}
+
+STATIC_OVL char *
+conditionbitmask2str(ul)
+unsigned long ul;
+{
+    static char buf[BUFSZ];
+    int i;
+    boolean first = TRUE;
+    const char *alias = (char *) 0;
+
+
+    buf[0] = '\0';
+    if (!ul)
+        return buf;
+
+    for (i = 1; i < SIZE(condition_aliases); i++)
+        if (condition_aliases[i].bitmask == ul)
+            alias = condition_aliases[i].id;
+
+    for (i = 0; i < SIZE(valid_conditions); i++)
+        if ((valid_conditions[i].bitmask & ul) != 0UL) {
+            Sprintf(eos(buf), "%s%s", (first) ? "" : "+",
+                    valid_conditions[i].id);
+            first = FALSE;
+        }
+
+    if (!first && alias)
+        Sprintf(buf, "%s", alias);
+
+    return buf;
+}
+
+STATIC_OVL unsigned long
+match_str2conditionbitmask(str)
+const char *str;
+{
+    int i, nmatches = 0;
+    unsigned long mask = 0UL;
+
+    if (str && *str) {
+        /* check matches to canonical names */
+        for (i = 0; i < SIZE(valid_conditions); i++)
+            if (fuzzymatch(valid_conditions[i].id, str, " -_", TRUE)) {
+                mask |= valid_conditions[i].bitmask;
+                nmatches++;
+            }
+
+        if (!nmatches) {
+            /* check aliases */
+            for (i = 0; i < SIZE(condition_aliases); i++)
+                if (fuzzymatch(condition_aliases[i].id, str, " -_", TRUE)) {
+                    mask |= condition_aliases[i].bitmask;
+                    nmatches++;
+                }
+        }
+
+        if (!nmatches) {
+            /* check partial matches to aliases */
+            int len = (int) strlen(str);
+            for (i = 0; i < SIZE(condition_aliases); i++)
+                if (!strncmpi(str, condition_aliases[i].id, len)) {
+                    mask |= condition_aliases[i].bitmask;
+                    nmatches++;
+                }
+        }
+    }
+
+    return mask;
+}
+
+STATIC_OVL unsigned long
+str2conditionbitmask(str)
+char *str;
+{
+    unsigned long conditions_bitmask = 0UL;
+    char **subfields;
+    int i, sf;
+
+    sf = splitsubfields(str, &subfields, SIZE(valid_conditions));
+
+    if (sf < 1)
+        return 0UL;
+
+    for (i = 0; i < sf; ++i) {
+        unsigned long bm = match_str2conditionbitmask(subfields[i]);
+
+        if (!bm) {
+            config_error_add("Unknown condition '%s'", subfields[i]);
+            return 0UL;
+        }
+        conditions_bitmask |= bm;
+    }
+    return conditions_bitmask;
+}
+
+STATIC_OVL boolean
+parse_condition(s, sidx)
+char (*s)[QBUFSZ];
+int sidx;
+{
+    int i;
+    int coloridx = NO_COLOR;
+    char *tmp, *how;
+    unsigned long conditions_bitmask = 0UL;
+    boolean success = FALSE;
+
+    if (!s)
+        return FALSE;
+
+    /*3.6.1:
+      OPTION=hilite_status: condition/stone+slime+foodPois/red&inverse */
+
+    sidx++;
+    while(s[sidx]) {
+        int sf = 0;     /* subfield count */
+        char buf[BUFSZ], **subfields;
+
+        tmp = s[sidx];
+        if (!*tmp) {
+            if (!success)
+                config_error_add("Missing condition(s)");
+            return success;
+       }
+
+        Strcpy(buf, tmp);
+        conditions_bitmask = str2conditionbitmask(buf);
+
+        if (!conditions_bitmask)
+            return FALSE;
+
+        /*
+         * We have the conditions_bitmask with bits set for
+         * each ailment we want in a particular color and/or
+         * attribute, but we need to assign it to an arry of
+         * bitmasks indexed by the color chosen
+         *        (0 to (CLR_MAX - 1))
+         * and/or attributes chosen
+         *        (HL_ATTCLR_DIM to (BL_ATTCLR_MAX - 1))
+         * We still have to parse the colors and attributes out.
+         */
+
+        /* actions */
+        sidx++;
+        how = s[sidx];
+        if (!how || !*how) {
+            config_error_add("Missing color+attribute");
+            return FALSE;
+        }
+
+        Strcpy(buf, how);
+        sf = splitsubfields(buf, &subfields, 0);
+
+        /*
+         * conditions_bitmask now has bits set representing
+         * the conditions that player wants represented, but
+         * now we parse out *how* they will be represented.
+         *
+         * Only 1 colour is allowed, but potentially multiple
+         * attributes are allowed.
+         *
+         * We have the following additional array offsets to
+         * use for storing the attributes beyond the end of
+         * the color indexes, all of which are less than CLR_MAX.
+         * HL_ATTCLR_DIM        = CLR_MAX
+         * HL_ATTCLR_BLINK      = CLR_MAX + 1
+         * HL_ATTCLR_ULINE      = CLR_MAX + 2
+         * HL_ATTCLR_INVERSE    = CLR_MAX + 3
+         * HL_ATTCLR_BOLD       = CLR_MAX + 4
+         * HL_ATTCLR_MAX        = CLR_MAX + 5 (this is past array boundary)
+         *
+         */
+
+        for (i = 0; i < sf; ++i) {
+            int a = match_str2attr(subfields[i], FALSE);
+            if (a == ATR_DIM)
+                cond_hilites[HL_ATTCLR_DIM] |= conditions_bitmask;
+            else if (a == ATR_BLINK)
+                cond_hilites[HL_ATTCLR_BLINK] |= conditions_bitmask;
+            else if (a == ATR_ULINE)
+                cond_hilites[HL_ATTCLR_ULINE] |= conditions_bitmask;
+            else if (a == ATR_INVERSE)
+                cond_hilites[HL_ATTCLR_INVERSE] |= conditions_bitmask;
+            else if (a == ATR_BOLD)
+                cond_hilites[HL_ATTCLR_BOLD] |= conditions_bitmask;
+            else if (a == ATR_NONE) {
+                cond_hilites[HL_ATTCLR_DIM]     = 0UL;
+                cond_hilites[HL_ATTCLR_BLINK]   = 0UL;
+                cond_hilites[HL_ATTCLR_ULINE]   = 0UL;
+                cond_hilites[HL_ATTCLR_INVERSE] = 0UL;
+                cond_hilites[HL_ATTCLR_BOLD]    = 0UL;
+            } else {
+                int k = match_str2clr(subfields[i]);
+
+                if (k >= CLR_MAX)
+                    return FALSE;
+                coloridx = k;
+           }
+        }
+        /* set the bits in the appropriate member of the
+           condition array according to color chosen as index */
+
+        cond_hilites[coloridx] |= conditions_bitmask;
+        success = TRUE;
+        sidx++;
+    }
+    return TRUE;
+}
+
+void
+clear_status_hilites()
+{
+    int i;
+
+    for (i = 0; i < MAXBLSTATS; ++i) {
+        if (blstats[0][i].thresholds) {
+            struct hilite_s *temp = blstats[0][i].thresholds,
+                            *next = (struct hilite_s *)0;
+            while (temp) {
+                next = temp->next;
+                free(temp);
+                blstats[0][i].thresholds = (struct hilite_s *)0;
+                blstats[1][i].thresholds = blstats[0][i].thresholds;
+                temp = next;
+            }
+       }
+    }
+}
+
+STATIC_OVL char *
+hlattr2attrname(attrib, buf, bufsz)
+int attrib, bufsz;
+char *buf;
+{
+    if (attrib && buf) {
+        char attbuf[BUFSZ];
+        int k, first = 0;
+
+        attbuf[0] = '\0';
+        if (attrib & HL_NONE) {
+            Strcpy(buf, "normal");
+            return buf;
+        }
+
+        if (attrib & HL_BOLD)
+            Strcat(attbuf, first++ ? "+bold" : "bold");
+        if (attrib & HL_INVERSE)
+            Strcat(attbuf, first++ ? "+inverse" : "inverse");
+        if (attrib & HL_ULINE)
+            Strcat(attbuf, first++ ? "+underline" : "underline");
+        if (attrib & HL_BLINK)
+            Strcat(attbuf, first++ ? "+blink" : "blink");
+        if (attrib & HL_DIM)
+            Strcat(attbuf, first++ ? "+dim" : "dim");
+
+        k = strlen(attbuf);
+        if (k < (bufsz - 1))
+            Strcpy(buf, attbuf);
+        return buf;
+    }
+    return (char *) 0;
+}
+
+
+struct _status_hilite_line_str {
+    int id;
+    int fld;
+    struct hilite_s *hl;
+    unsigned long mask;
+    char str[BUFSZ];
+    struct _status_hilite_line_str *next;
+};
+
+struct _status_hilite_line_str *status_hilite_str =
+    (struct _status_hilite_line_str *) 0;
+static int status_hilite_str_id = 0;
+
+STATIC_OVL void
+status_hilite_linestr_add(fld, hl, mask, str)
+int fld;
+struct hilite_s *hl;
+unsigned long mask;
+const char *str;
+{
+    struct _status_hilite_line_str *tmp = (struct _status_hilite_line_str *)
+        alloc(sizeof(struct _status_hilite_line_str));
+    struct _status_hilite_line_str *nxt = status_hilite_str;
+
+    (void) memset(tmp, 0, sizeof(struct _status_hilite_line_str));
+
+    ++status_hilite_str_id;
+    tmp->fld = fld;
+    tmp->hl = hl;
+    tmp->mask = mask;
+    (void) stripchars(tmp->str, " ", str);
+
+    tmp->id = status_hilite_str_id;
+
+    if (nxt) {
+        while (nxt && nxt->next)
+            nxt = nxt->next;
+        nxt->next = tmp;
+    } else {
+        tmp->next = (struct _status_hilite_line_str *) 0;
+        status_hilite_str = tmp;
+    }
+}
+
+STATIC_OVL void
+status_hilite_linestr_done()
+{
+    struct _status_hilite_line_str *tmp = status_hilite_str;
+    struct _status_hilite_line_str *nxt;
+
+    while (tmp) {
+        nxt = tmp->next;
+        free(tmp);
+        tmp = nxt;
+    }
+    status_hilite_str = (struct _status_hilite_line_str *) 0;
+    status_hilite_str_id = 0;
+}
+
+STATIC_OVL int
+status_hilite_linestr_countfield(fld)
+int fld;
+{
+    struct _status_hilite_line_str *tmp = status_hilite_str;
+    int count = 0;
+
+    while (tmp) {
+        if (tmp->fld == fld || fld == BL_FLUSH)
+            count++;
+        tmp = tmp->next;
+    }
+    return count;
+}
+
+int
+count_status_hilites()
+{
+    int count;
+    status_hilite_linestr_gather();
+    count = status_hilite_linestr_countfield(BL_FLUSH);
+    status_hilite_linestr_done();
+    return count;
+}
+
+STATIC_OVL void
+status_hilite_linestr_gather_conditions()
+{
+    int i;
+    struct _cond_map {
+        unsigned long bm;
+        unsigned long clratr;
+    } cond_maps[SIZE(valid_conditions)];
+
+    (void)memset(cond_maps, 0,
+                 sizeof(struct _cond_map) * SIZE(valid_conditions));
+
+    for (i = 0; i < SIZE(valid_conditions); i++) {
+        int clr = NO_COLOR;
+        int atr = HL_NONE;
+        int j;
+        for (j = 0; j < CLR_MAX; j++)
+            if (cond_hilites[j] & valid_conditions[i].bitmask)
+                clr = j;
+        if (cond_hilites[HL_ATTCLR_DIM] & valid_conditions[i].bitmask)
+            atr |= HL_DIM;
+        if (cond_hilites[HL_ATTCLR_BOLD] & valid_conditions[i].bitmask)
+            atr |= HL_BOLD;
+        if (cond_hilites[HL_ATTCLR_BLINK] & valid_conditions[i].bitmask)
+            atr |= HL_BLINK;
+        if (cond_hilites[HL_ATTCLR_ULINE] & valid_conditions[i].bitmask)
+            atr |= HL_ULINE;
+        if (cond_hilites[HL_ATTCLR_INVERSE] & valid_conditions[i].bitmask)
+            atr |= HL_INVERSE;
+
+        if (clr != NO_COLOR || atr != HL_NONE) {
+            unsigned long ca = clr | (atr << 8);
+            boolean added_condmap = FALSE;
+            for (j = 0; j < SIZE(valid_conditions); j++)
+                if (cond_maps[j].clratr == ca) {
+                    cond_maps[j].bm |= valid_conditions[i].bitmask;
+                    added_condmap = TRUE;
+                    break;
+                }
+            if (!added_condmap) {
+                for (j = 0; j < SIZE(valid_conditions); j++)
+                    if (!cond_maps[j].bm) {
+                        cond_maps[j].bm = valid_conditions[i].bitmask;
+                        cond_maps[j].clratr = ca;
+                        break;
+                    }
+            }
+        }
+    }
+
+    for (i = 0; i < SIZE(valid_conditions); i++)
+        if (cond_maps[i].bm) {
+            int clr = NO_COLOR, atr = HL_NONE;
+            split_clridx(cond_maps[i].clratr, &clr, &atr);
+            if (clr != NO_COLOR || atr != HL_NONE) {
+                char clrbuf[BUFSZ];
+                char attrbuf[BUFSZ];
+                char condbuf[BUFSZ];
+                char *tmpattr;
+                (void) stripchars(clrbuf, " ", clr2colorname(clr));
+                tmpattr = hlattr2attrname(atr, attrbuf, BUFSZ);
+                if (tmpattr)
+                    Sprintf(eos(clrbuf), "&%s", tmpattr);
+                Sprintf(condbuf, "condition/%s/%s",
+                        conditionbitmask2str(cond_maps[i].bm), clrbuf);
+                status_hilite_linestr_add(BL_CONDITION, 0,
+                                          cond_maps[i].bm, condbuf);
+            }
+        }
+}
+
+STATIC_OVL void
+status_hilite_linestr_gather()
+{
+    int i;
+    struct hilite_s *hl;
+
+    status_hilite_linestr_done();
+
     for (i = 0; i < MAXBLSTATS; i++) {
-        (void) memset(&hltemp[i], 0, sizeof(struct hilite_s));
-        fieldname = fieldids[i].fieldname;
-        any.a_int = i + 1;
-        add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, fieldname,
-                 MENU_UNSELECTED);
-        field_picks[i] = 0;
-    }
-    end_menu(tmpwin, "Change hilite on which status field(s):");
-    if ((pick_cnt = select_menu(tmpwin, PICK_ANY, &statfield_picks)) > 0) {
-        for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx) {
-            opt_idx = statfield_picks[pick_idx].item.a_int - 1;
-            field_picks[opt_idx] = 1;
+        hl = blstats[0][i].thresholds;
+        while (hl) {
+            status_hilite_linestr_add(i, hl, 0UL, status_hilite2str(hl));
+            hl = hl->next;
         }
-        free((genericptr_t) statfield_picks);
-        statfield_picks = (menu_item *) 0;
     }
+
+    status_hilite_linestr_gather_conditions();
+}
+
+
+char *
+status_hilite2str(hl)
+struct hilite_s *hl;
+{
+    static char buf[BUFSZ];
+    int clr = 0, attr = 0;
+    char behavebuf[BUFSZ];
+    char clrbuf[BUFSZ];
+    char attrbuf[BUFSZ];
+    char *tmpattr;
+
+    if (!hl)
+        return (char *) 0;
+
+    behavebuf[0] = '\0';
+    clrbuf[0] = '\0';
+
+    switch (hl->behavior) {
+    case BL_TH_VAL_PERCENTAGE:
+        if (hl->rel == LT_VALUE)
+            Sprintf(behavebuf, "<%i%%", hl->value.a_int);
+        else if (hl->rel == GT_VALUE)
+            Sprintf(behavebuf, ">%i%%", hl->value.a_int);
+        else if (hl->rel == EQ_VALUE)
+            Sprintf(behavebuf, "%i%%", hl->value.a_int);
+        else
+            impossible("hl->behavior=percentage, rel error");
+        break;
+    case BL_TH_UPDOWN:
+        if (hl->rel == LT_VALUE)
+            Sprintf(behavebuf, "down");
+        else if (hl->rel == GT_VALUE)
+            Sprintf(behavebuf, "up");
+        else if (hl->rel == EQ_VALUE)
+            Sprintf(behavebuf, "changed");
+        else
+            impossible("hl->behavior=updown, rel error");
+        break;
+    case BL_TH_VAL_ABSOLUTE:
+        if (hl->rel == LT_VALUE)
+            Sprintf(behavebuf, "<%i", hl->value.a_int);
+        else if (hl->rel == GT_VALUE)
+            Sprintf(behavebuf, ">%i", hl->value.a_int);
+        else if (hl->rel == EQ_VALUE)
+            Sprintf(behavebuf, "%i", hl->value.a_int);
+        else
+            impossible("hl->behavior=absolute, rel error");
+        break;
+    case BL_TH_TEXTMATCH:
+        if (hl->rel == TXT_VALUE && hl->textmatch[0])
+            Sprintf(behavebuf, "%s", hl->textmatch);
+        else
+            impossible("hl->behavior=textmatch, rel or textmatch error");
+        break;
+    case BL_TH_CONDITION:
+        if (hl->rel == EQ_VALUE)
+            Sprintf(behavebuf, "%s", conditionbitmask2str(hl->value.a_ulong));
+        else
+            impossible("hl->behavior=condition, rel error");
+        break;
+    case BL_TH_ALWAYS_HILITE:
+        Sprintf(behavebuf, "always");
+        break;
+    case BL_TH_NONE:
+        break;
+    default:
+        break;
+    }
+
+    split_clridx(hl->coloridx, &clr, &attr);
+    if (clr != NO_COLOR)
+        (void) stripchars(clrbuf, " ", clr2colorname(clr));
+    if (attr != HL_UNDEF) {
+        tmpattr = hlattr2attrname(attr, attrbuf, BUFSZ);
+        if (tmpattr)
+            Sprintf(eos(clrbuf), "%s%s",
+                    (clr != NO_COLOR) ? "&" : "",
+                    tmpattr);
+    }
+    Sprintf(buf, "%s/%s/%s", initblstats[hl->fld].fldname, behavebuf, clrbuf);
+
+    return buf;
+}
+
+int
+status_hilite_menu_choose_field()
+{
+    winid tmpwin;
+    int i, res, fld = BL_FLUSH;
+    anything any;
+    menu_item *picks = (menu_item *) 0;
+
+    tmpwin = create_nhwindow(NHW_MENU);
+    start_menu(tmpwin);
+
+    for (i = 0; i < MAXBLSTATS; i++) {
+        any = zeroany;
+        any.a_int = (i+1);
+        add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
+                 initblstats[i].fldname, MENU_UNSELECTED);
+    }
+
+    end_menu(tmpwin, "Select a hilite field:");
+
+    res = select_menu(tmpwin, PICK_ONE, &picks);
+    destroy_nhwindow(tmpwin);
+    if (res > 0) {
+        fld = picks->item.a_int - 1;
+        free((genericptr_t) picks);
+    }
+    return fld;
+}
+
+int
+status_hilite_menu_choose_behavior(fld)
+int fld;
+{
+    winid tmpwin;
+    int res = 0, beh = BL_TH_NONE-1;
+    anything any;
+    menu_item *picks = (menu_item *) 0;
+    char buf[BUFSZ];
+    int at;
+    int onlybeh = BL_TH_NONE, nopts = 0;
+
+    if (fld <= BL_FLUSH || fld >= MAXBLSTATS)
+        return BL_TH_NONE;
+
+    at = initblstats[fld].anytype;
+
+    tmpwin = create_nhwindow(NHW_MENU);
+    start_menu(tmpwin);
+
+    if (fld != BL_CONDITION) {
+        any = zeroany;
+        any.a_int = onlybeh = BL_TH_ALWAYS_HILITE;
+        Sprintf(buf, "Always highlight %s", initblstats[fld].fldname);
+        add_menu(tmpwin, NO_GLYPH, &any, 'a', 0, ATR_NONE,
+                 buf, MENU_UNSELECTED);
+        nopts++;
+    }
+
+    if (fld == BL_CONDITION) {
+        any = zeroany;
+        any.a_int = onlybeh = BL_TH_CONDITION;
+        add_menu(tmpwin, NO_GLYPH, &any, 'b', 0, ATR_NONE,
+                 "Bitmask of conditions", MENU_UNSELECTED);
+        nopts++;
+    }
+
+    if (fld != BL_CONDITION) {
+        any = zeroany;
+        any.a_int = onlybeh = BL_TH_UPDOWN;
+        Sprintf(buf, "%s value changes", initblstats[fld].fldname);
+        add_menu(tmpwin, NO_GLYPH, &any, 'c', 0, ATR_NONE,
+                 buf, MENU_UNSELECTED);
+        nopts++;
+    }
+
+    if (fld != BL_CAP && (at == ANY_INT || at == ANY_LONG || at == ANY_UINT)) {
+        any = zeroany;
+        any.a_int = onlybeh = BL_TH_VAL_ABSOLUTE;
+        add_menu(tmpwin, NO_GLYPH, &any, 'n', 0, ATR_NONE,
+                 "Number threshold", MENU_UNSELECTED);
+        nopts++;
+    }
+
+    if (initblstats[fld].idxmax > BL_FLUSH) {
+        any = zeroany;
+        any.a_int = onlybeh = BL_TH_VAL_PERCENTAGE;
+        add_menu(tmpwin, NO_GLYPH, &any, 'p', 0, ATR_NONE,
+                 "Percentage threshold", MENU_UNSELECTED);
+        nopts++;
+    }
+
+    if (initblstats[fld].anytype == ANY_STR || fld == BL_CAP) {
+        any = zeroany;
+        any.a_int = onlybeh = BL_TH_TEXTMATCH;
+        Sprintf(buf, "%s text match", initblstats[fld].fldname);
+        add_menu(tmpwin, NO_GLYPH, &any, 't', 0, ATR_NONE,
+                 buf, MENU_UNSELECTED);
+        nopts++;
+    }
+
+    Sprintf(buf, "Select %s field hilite behavior:", initblstats[fld].fldname);
+    end_menu(tmpwin, buf);
+
+    if (nopts > 1) {
+        res = select_menu(tmpwin, PICK_ONE, &picks);
+        if (res == 0) /* none chosen*/
+            beh = BL_TH_NONE;
+        else if (res == -1) /* menu cancelled */
+            beh = (BL_TH_NONE - 1);
+    } else if (onlybeh != BL_TH_NONE)
+        beh = onlybeh;
+    destroy_nhwindow(tmpwin);
+    if (res > 0) {
+        beh = picks->item.a_int;
+        free((genericptr_t) picks);
+    }
+    return beh;
+}
+
+int
+status_hilite_menu_choose_updownboth(fld, str)
+int fld;
+const char *str;
+{
+    int res, ret = -2;
+    winid tmpwin;
+    char buf[BUFSZ];
+    anything any;
+    menu_item *picks = (menu_item *) 0;
+
+    tmpwin = create_nhwindow(NHW_MENU);
+    start_menu(tmpwin);
+
+    if (str)
+        Sprintf(buf, "%s or less", str);
+    else
+        Sprintf(buf, "Value goes down");
+    any = zeroany;
+    any.a_int = 10 + LT_VALUE;
+    add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
+             buf, MENU_UNSELECTED);
+
+    if (str)
+        Sprintf(buf, "Exactly %s", str);
+    else
+        Sprintf(buf, "Value changes");
+    any = zeroany;
+    any.a_int = 10 + EQ_VALUE;
+    add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
+             buf, MENU_UNSELECTED);
+
+    if (str)
+        Sprintf(buf, "%s or more", str);
+    else
+        Sprintf(buf, "Value goes up");
+    any = zeroany;
+    any.a_int = 10 + GT_VALUE;
+    add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
+             buf, MENU_UNSELECTED);
+
+    Sprintf(buf, "Select field %s value:", initblstats[fld].fldname);
+    end_menu(tmpwin, buf);
+
+    res = select_menu(tmpwin, PICK_ONE, &picks);
     destroy_nhwindow(tmpwin);
-    if (pick_cnt < 0)
+    if (res > 0) {
+        ret = picks->item.a_int - 10;
+        free((genericptr_t) picks);
+    }
+
+    return ret;
+}
+
+STATIC_OVL boolean
+status_hilite_menu_add(origfld)
+int origfld;
+{
+    int fld;
+    int behavior;
+    int lt_gt_eq = 0;
+    int clr = NO_COLOR, atr = HL_UNDEF;
+    struct hilite_s hilite;
+    unsigned long cond = 0UL;
+    char colorqry[BUFSZ];
+    char attrqry[BUFSZ];
+
+choose_field:
+    fld = origfld;
+    if (fld == BL_FLUSH) {
+        fld = status_hilite_menu_choose_field();
+        if (fld == BL_FLUSH)
+            return FALSE;
+    }
+
+    if (fld == BL_FLUSH)
         return FALSE;
 
-    for (i = 0; i < MAXBLSTATS; i++) {
-        if (field_picks[i]) {
-            menu_item *pick = (menu_item *) 0;
-
-            Sprintf(buf, "Threshold behavior options for %s:",
-                    fieldids[i].fieldname);
-            tmpwin = create_nhwindow(NHW_MENU);
-            start_menu(tmpwin);
-            if (i == BL_CONDITION) {
-                any = zeroany;
-                any.a_int = BL_TH_CONDITION + 1;
-                add_menu(tmpwin, NO_GLYPH, &any, 'c', 0, ATR_NONE,
-                         "Condition bitmask threshold.", MENU_UNSELECTED);
+    colorqry[0] = '\0';
+    attrqry[0] = '\0';
+
+    memset((genericptr_t) &hilite, 0, sizeof(struct hilite_s));
+    hilite.set = FALSE; /* mark it "unset" */
+    hilite.fld = fld;
+
+choose_behavior:
+
+    behavior = status_hilite_menu_choose_behavior(fld);
+
+    if (behavior == (BL_TH_NONE-1)) {
+        return FALSE;
+    } else if (behavior == BL_TH_NONE) {
+        if (origfld == BL_FLUSH)
+            goto choose_field;
+        else
+            return FALSE;
+    }
+
+    hilite.behavior = behavior;
+
+choose_value:
+
+    if (behavior == BL_TH_VAL_PERCENTAGE
+        || behavior == BL_TH_VAL_ABSOLUTE) {
+        char inbuf[BUFSZ], buf[BUFSZ];
+        int val;
+        boolean skipltgt = FALSE;
+        boolean gotnum = FALSE;
+        char *inp = inbuf;
+        char *numstart = inbuf;
+
+        inbuf[0] = '\0';
+        Sprintf(buf, "Enter %svalue for %s threshold:",
+                (behavior == BL_TH_VAL_PERCENTAGE) ? "percentage " : "",
+                initblstats[fld].fldname);
+        getlin(buf, inbuf);
+        if (inbuf[0] == '\0' || inbuf[0] == '\033')
+            goto choose_behavior;
+
+        inp = trimspaces(inbuf);
+        if (!*inp)
+            goto choose_behavior;
+
+        /* allow user to enter "<50%" or ">50" or just "50" */
+        if (*inp == '>' || *inp == '<' || *inp == '=') {
+            lt_gt_eq = (*inp == '>') ? GT_VALUE
+                : (*inp == '<') ? LT_VALUE : EQ_VALUE;
+            skipltgt = TRUE;
+            *inp = ' ';
+            inp++;
+            numstart++;
+        }
+        while (digit(*inp)) {
+            inp++;
+            gotnum = TRUE;
+        }
+        if (*inp == '%') {
+            behavior = BL_TH_VAL_PERCENTAGE;
+            *inp = '\0';
+        } else if (!*inp) {
+            behavior = BL_TH_VAL_ABSOLUTE;
+        } else {
+            /* some random characters */
+            pline("\"%s\" is not a recognized number.", inp);
+            goto choose_value;
+        }
+        if (!gotnum) {
+            pline("Is that an invisible number?");
+            goto choose_value;
+        }
+
+        val = atoi(numstart);
+        if (behavior == BL_TH_VAL_PERCENTAGE) {
+            if (initblstats[fld].idxmax == -1) {
+                pline("Field '%s' does not support percentage values.",
+                      initblstats[fld].fldname);
+                behavior = BL_TH_VAL_ABSOLUTE;
+                goto choose_value;
+            }
+            if (val < 0 || val > 100) {
+                pline("Not a valid percent value.");
+                goto choose_value;
             }
-            any = zeroany;
-            any.a_int = BL_TH_NONE + 1;
-            add_menu(tmpwin, NO_GLYPH, &any, 'n', 0, ATR_NONE, "None",
-                     MENU_UNSELECTED);
-            if (i != BL_CONDITION) {
-                if (blstats[0][i].idxmax > 0) {
-                    any = zeroany;
-                    any.a_int = BL_TH_VAL_PERCENTAGE + 1;
-                    add_menu(tmpwin, NO_GLYPH, &any, 'p', 0, ATR_NONE,
-                             "Percentage threshold.", MENU_UNSELECTED);
+        }
+
+        if (!skipltgt) {
+            lt_gt_eq = status_hilite_menu_choose_updownboth(fld, inbuf);
+            if (lt_gt_eq == -2)
+                goto choose_value;
+        }
+
+        Sprintf(colorqry, "Choose a color for when %s is %s%s:",
+                initblstats[fld].fldname,
+                numstart,
+                (lt_gt_eq == EQ_VALUE) ? ""
+                : (lt_gt_eq == LT_VALUE) ? " or less"
+                : " or more");
+
+        Sprintf(attrqry, "Choose attribute for when %s is %s%s:",
+                initblstats[fld].fldname,
+                inbuf,
+                (lt_gt_eq == EQ_VALUE) ? ""
+                : (lt_gt_eq == LT_VALUE) ? " or less"
+                : " or more");
+
+        hilite.rel = lt_gt_eq;
+        hilite.value.a_int = val;
+    } else if (behavior == BL_TH_UPDOWN) {
+        lt_gt_eq = status_hilite_menu_choose_updownboth(fld, (char *)0);
+        if (lt_gt_eq == -2)
+            goto choose_behavior;
+        Sprintf(colorqry, "Choose a color for when %s %s:",
+                initblstats[fld].fldname,
+                (lt_gt_eq == EQ_VALUE) ? "changes"
+                : (lt_gt_eq == LT_VALUE) ? "decreases"
+                : "increases");
+        Sprintf(attrqry, "Choose attribute for when %s %s:",
+                initblstats[fld].fldname,
+                (lt_gt_eq == EQ_VALUE) ? "changes"
+                : (lt_gt_eq == LT_VALUE) ? "decreases"
+                : "increases");
+        hilite.rel = lt_gt_eq;
+    } else if (behavior == BL_TH_CONDITION) {
+        cond = query_conditions();
+        if (!cond) {
+            if (origfld == BL_FLUSH)
+                goto choose_field;
+            else
+                return FALSE;
+        }
+        Sprintf(colorqry, "Choose a color for conditions %s:",
+                conditionbitmask2str(cond));
+        Sprintf(attrqry, "Choose attribute for conditions %s:",
+                conditionbitmask2str(cond));
+    } else if (behavior == BL_TH_TEXTMATCH) {
+        char qry_buf[BUFSZ];
+        Sprintf(qry_buf, "%s %s text value to match:",
+                (fld == BL_CAP
+                 || fld == BL_ALIGN
+                 || fld == BL_HUNGER
+                 || fld == BL_TITLE) ? "Choose" : "Enter",
+                initblstats[fld].fldname);
+        if (fld == BL_CAP) {
+            int rv = query_arrayvalue(qry_buf,
+                                      enc_stat,
+                                      SLT_ENCUMBER, OVERLOADED+1);
+            if (rv < SLT_ENCUMBER)
+                goto choose_behavior;
+
+            hilite.rel = TXT_VALUE;
+            Strcpy(hilite.textmatch, enc_stat[rv]);
+        } else if (fld == BL_ALIGN) {
+            const char *aligntxt[] = {"chaotic", "neutral", "lawful"};
+            int rv = query_arrayvalue(qry_buf,
+                                      aligntxt, 0, 3);
+            if (rv < 0)
+                goto choose_behavior;
+
+            hilite.rel = TXT_VALUE;
+            Strcpy(hilite.textmatch, aligntxt[rv]);
+        } else if (fld == BL_HUNGER) {
+            const char *hutxt[] = {"Satiated", "", "Hungry", "Weak",
+                                   "Fainting", "Fainted", "Starved"};
+            int rv = query_arrayvalue(qry_buf,
+                                      hutxt,
+                                      SATIATED, STARVED+1);
+            if (rv < SATIATED)
+                goto choose_behavior;
+
+            hilite.rel = TXT_VALUE;
+            Strcpy(hilite.textmatch, hutxt[rv]);
+        } else if (fld == BL_TITLE) {
+            const char *rolelist[9];
+            int i, rv;
+
+            for (i = 0; i < 9; i++)
+                rolelist[i] = (flags.female && urole.rank[i].f)
+                    ? urole.rank[i].f : urole.rank[i].m;
+
+            rv = query_arrayvalue(qry_buf, rolelist, 0, 9);
+            if (rv < 0)
+                goto choose_behavior;
+
+            hilite.rel = TXT_VALUE;
+            Strcpy(hilite.textmatch, rolelist[rv]);
+        } else {
+            char inbuf[BUFSZ];
+
+            inbuf[0] = '\0';
+            getlin(qry_buf, inbuf);
+            if (inbuf[0] == '\0' || inbuf[0] == '\033')
+                goto choose_behavior;
+
+            hilite.rel = TXT_VALUE;
+            if (strlen(inbuf) < QBUFSZ-1)
+                Strcpy(hilite.textmatch, inbuf);
+            else
+                return FALSE;
+        }
+        Sprintf(colorqry, "Choose a color for when %s is '%s':",
+                initblstats[fld].fldname, hilite.textmatch);
+        Sprintf(colorqry, "Choose attribute for when %s is '%s':",
+                initblstats[fld].fldname, hilite.textmatch);
+    } else if (behavior == BL_TH_ALWAYS_HILITE) {
+        Sprintf(colorqry, "Choose a color to always hilite %s:",
+                initblstats[fld].fldname);
+        Sprintf(attrqry, "Choose attribute to always hilite %s:",
+                initblstats[fld].fldname);
+    }
+
+choose_color:
+
+    clr = query_color(colorqry);
+    if (clr == -1) {
+        if (behavior != BL_TH_ALWAYS_HILITE)
+            goto choose_value;
+        else
+            goto choose_behavior;
+    }
+
+    atr = query_attr(attrqry); /* FIXME: pick multiple attrs */
+    if (atr == -1)
+        goto choose_color;
+    if (atr == ATR_DIM)
+        atr = HL_DIM;
+    else if (atr == ATR_BLINK)
+        atr = HL_BLINK;
+    else if (atr == ATR_ULINE)
+        atr = HL_ULINE;
+    else if (atr == ATR_INVERSE)
+        atr = HL_INVERSE;
+    else if (atr == ATR_BOLD)
+        atr = HL_BOLD;
+    else if (atr == ATR_NONE)
+        atr = HL_NONE;
+    else
+        atr = HL_UNDEF;
+
+    if (clr == -1)
+        clr = NO_COLOR;
+
+    if (behavior == BL_TH_CONDITION) {
+        char clrbuf[BUFSZ];
+        char attrbuf[BUFSZ];
+        char *tmpattr;
+        if (atr == HL_DIM)
+            cond_hilites[HL_ATTCLR_DIM] |= cond;
+        else if (atr == HL_BLINK)
+            cond_hilites[HL_ATTCLR_BLINK] |= cond;
+        else if (atr == HL_ULINE)
+            cond_hilites[HL_ATTCLR_ULINE] |= cond;
+        else if (atr == HL_INVERSE)
+            cond_hilites[HL_ATTCLR_INVERSE] |= cond;
+        else if (atr == HL_BOLD)
+            cond_hilites[HL_ATTCLR_BOLD] |= cond;
+        else if (atr == HL_NONE) {
+            cond_hilites[HL_ATTCLR_DIM]     = 0UL;
+            cond_hilites[HL_ATTCLR_BLINK]   = 0UL;
+            cond_hilites[HL_ATTCLR_ULINE]   = 0UL;
+            cond_hilites[HL_ATTCLR_INVERSE] = 0UL;
+            cond_hilites[HL_ATTCLR_BOLD]    = 0UL;
+        }
+        cond_hilites[clr] |= cond;
+        (void) stripchars(clrbuf, " ", clr2colorname(clr));
+        tmpattr = hlattr2attrname(atr, attrbuf, BUFSZ);
+        if (tmpattr)
+            Sprintf(eos(clrbuf), "&%s", tmpattr);
+        pline("Added hilite condition/%s/%s",
+              conditionbitmask2str(cond), clrbuf);
+    } else {
+        hilite.coloridx = clr | (atr << 8);
+        hilite.anytype = initblstats[fld].anytype;
+
+        status_hilite_add_threshold(fld, &hilite);
+        pline("Added hilite %s", status_hilite2str(&hilite));
+    }
+    reset_status_hilites();
+    return TRUE;
+}
+
+boolean
+status_hilite_remove(id)
+int id;
+{
+    struct _status_hilite_line_str *hlstr = status_hilite_str;
+
+    while (hlstr && hlstr->id != id) {
+        hlstr = hlstr->next;
+    }
+
+    if (!hlstr)
+        return FALSE;
+
+    if (hlstr->fld == BL_CONDITION) {
+        int i;
+
+        for (i = 0; i < CLR_MAX; i++)
+            cond_hilites[i] &= ~hlstr->mask;
+        cond_hilites[HL_ATTCLR_DIM] &= ~hlstr->mask;
+        cond_hilites[HL_ATTCLR_BOLD] &= ~hlstr->mask;
+        cond_hilites[HL_ATTCLR_BLINK] &= ~hlstr->mask;
+        cond_hilites[HL_ATTCLR_ULINE] &= ~hlstr->mask;
+        cond_hilites[HL_ATTCLR_INVERSE] &= ~hlstr->mask;
+        return TRUE;
+    } else {
+        int fld = hlstr->fld;
+        struct hilite_s *hl = blstats[0][fld].thresholds;
+        struct hilite_s *hlprev = (struct hilite_s *) 0;
+
+        if (hl) {
+            while (hl) {
+                if (hlstr->hl == hl) {
+                    if (hlprev)
+                        hlprev->next = hl->next;
+                    else {
+                        blstats[0][fld].thresholds = hl->next;
+                        blstats[1][fld].thresholds =
+                            blstats[0][fld].thresholds;
+                    }
+                    free(hl);
+                    return TRUE;
                 }
-                any = zeroany;
-                any.a_int = BL_TH_UPDOWN + 1;
-                add_menu(tmpwin, NO_GLYPH, &any, 'u', 0, ATR_NONE,
-                         "UpDown threshold.", MENU_UNSELECTED);
-                any = zeroany;
-                any.a_int = BL_TH_VAL_ABSOLUTE + 1;
-                add_menu(tmpwin, NO_GLYPH, &any, 'v', 0, ATR_NONE,
-                         "Value threshold.", MENU_UNSELECTED);
+                hlprev = hl;
+                hl = hl->next;
             }
-            end_menu(tmpwin, buf);
-            if ((res = select_menu(tmpwin, PICK_ONE, &pick)) > 0) {
-                hltemp[i].behavior = pick->item.a_int - 1;
-                free((genericptr_t) pick);
+        }
+    }
+    return FALSE;
+}
+
+boolean
+status_hilite_menu_fld(fld)
+int fld;
+{
+    winid tmpwin;
+    int i, res;
+    menu_item *picks = (menu_item *) 0;
+    anything any;
+    int count = status_hilite_linestr_countfield(fld);
+    struct _status_hilite_line_str *hlstr;
+    char buf[BUFSZ];
+    boolean acted = FALSE;
+
+    if (!count) {
+        if (status_hilite_menu_add(fld)) {
+            status_hilite_linestr_done();
+            status_hilite_linestr_gather();
+            count = status_hilite_linestr_countfield(fld);
+        } else
+            return FALSE;
+    }
+
+    tmpwin = create_nhwindow(NHW_MENU);
+    start_menu(tmpwin);
+
+    if (count) {
+        hlstr = status_hilite_str;
+        while (hlstr) {
+            if (hlstr->fld == fld) {
+                any = zeroany;
+                any.a_int = hlstr->id;
+                add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
+                         hlstr->str, MENU_UNSELECTED);
             }
-            destroy_nhwindow(tmpwin);
-            if (res < 0)
-                return FALSE;
+            hlstr = hlstr->next;
+        }
+    } else {
+        any = zeroany;
+        Sprintf(buf, "No current hilites for %s", initblstats[fld].fldname);
+        add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
+    }
+
+    /* separator line */
+    any = zeroany;
+    add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
+
+    if (count) {
+        any = zeroany;
+        any.a_int = -1;
+        add_menu(tmpwin, NO_GLYPH, &any, 'X', 0, ATR_NONE,
+                 "Remove selected hilites", MENU_UNSELECTED);
+    }
+
+    any = zeroany;
+    any.a_int = -2;
+    add_menu(tmpwin, NO_GLYPH, &any, 'Z', 0, ATR_NONE,
+             "Add a new hilite", MENU_UNSELECTED);
 
-            if (hltemp[i].behavior == BL_TH_UPDOWN) {
-                Sprintf(below, "%s decreases", fieldids[i].fieldname);
-                Sprintf(above, "%s increases", fieldids[i].fieldname);
-            } else if (hltemp[i].behavior) {
-                /* Have them enter the threshold*/
-                Sprintf(
-                    buf, "Set %s threshold to what%s?", fieldids[i].fieldname,
-                    (hltemp[i].behavior == BL_TH_VAL_PERCENTAGE)
-                        ? " percentage"
-                        : (hltemp[i].behavior == BL_TH_CONDITION) ? " mask"
-                                                                  : "");
-                getlin(buf, thresholdbuf);
-                if (thresholdbuf[0] == '\033')
-                    return FALSE;
-                (void) s_to_anything(&hltemp[i].threshold, thresholdbuf,
-                                     blstats[0][i].anytype);
-                if (!hltemp[i].threshold.a_void)
-                    return FALSE;
 
-                Sprintf(below, "%s falls below %s%s", fieldids[i].fieldname,
-                        thresholdbuf,
-                        (hltemp[i].behavior == BL_TH_VAL_PERCENTAGE) ? "%"
-                                                                     : "");
-                Sprintf(above, "%s rises above %s%s", fieldids[i].fieldname,
-                        thresholdbuf,
-                        (hltemp[i].behavior == BL_TH_VAL_PERCENTAGE) ? "%"
-                                                                     : "");
+    Sprintf(buf, "Current %s hilites:", initblstats[fld].fldname);
+    end_menu(tmpwin, buf);
+
+    if ((res = select_menu(tmpwin, PICK_ANY, &picks)) > 0) {
+        int mode = 0;
+        for (i = 0; i < res; i++) {
+            int idx = picks[i].item.a_int;
+            if (idx == -1) {
+                /* delete selected hilites */
+                if (mode)
+                    goto shlmenu_free;
+                mode = -1;
+                break;
+            } else if (idx == -2) {
+                /* create a new hilite */
+                if (mode)
+                    goto shlmenu_free;
+                mode = -2;
+                break;
             }
-            for (j = 0; j < 2 && (hltemp[i].behavior != BL_TH_NONE); ++j) {
-                char prompt[QBUFSZ];
-                /* j == 0 below, j == 1 above */
-                menu_item *pick2 = (menu_item *) 0;
-
-                Sprintf(prompt, "Display how when %s?", j ? above : below);
-                tmpwin = create_nhwindow(NHW_MENU);
-                start_menu(tmpwin);
-                for (k = -3; k < CLR_MAX; ++k) {
-                    /* if (k == -1) continue; */
-                    any = zeroany;
-                    any.a_int = (k >= 0) ? k + 1 : k;
-                    if (k > 0)
-                        add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
-                                 c_obj_colors[k], MENU_UNSELECTED);
-                    else if (k == -1)
-                        add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
-                                 "normal", MENU_UNSELECTED);
-                    else if (k == -2)
-                        add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
-                                 "inverse", MENU_UNSELECTED);
-                    else if (k == -3)
-                        add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
-                                 "bold", MENU_UNSELECTED);
-                }
-                end_menu(tmpwin, prompt);
-                if ((res = select_menu(tmpwin, PICK_ONE, &pick2)) > 0) {
-                    hltemp[i].coloridx[j] = (pick2->item.a_char > 0)
-                                                ? pick2->item.a_int - 1
-                                                : pick2->item.a_int;
-                    free((genericptr_t) pick2);
-                }
-                destroy_nhwindow(tmpwin);
-                if (res < 0)
-                    return FALSE;
+        }
+
+        if (mode == -1) {
+            /* delete selected hilites */
+            for (i = 0; i < res; i++) {
+                int idx = picks[i].item.a_int;
+                if (idx > 0)
+                    (void) status_hilite_remove(idx);
             }
+            reset_status_hilites();
+            acted = TRUE;
+        } else if (mode == -2) {
+            /* create a new hilite */
+            if (status_hilite_menu_add(fld))
+                acted = TRUE;
         }
+
+        free((genericptr_t) picks);
     }
-    buf[0] = '\0';
+
+shlmenu_free:
+
+    picks = (menu_item *) 0;
+    destroy_nhwindow(tmpwin);
+    return acted;
+}
+
+void
+status_hilites_viewall()
+{
+    winid datawin;
+    struct _status_hilite_line_str *hlstr = status_hilite_str;
+    char buf[BUFSZ];
+
+    datawin = create_nhwindow(NHW_TEXT);
+
+    while (hlstr) {
+        Sprintf(buf, "OPTIONS=hilite_status: %s", hlstr->str);
+        putstr(datawin, 0, buf);
+        hlstr = hlstr->next;
+    }
+
+    display_nhwindow(datawin, FALSE);
+    destroy_nhwindow(datawin);
+}
+
+boolean
+status_hilite_menu()
+{
+    winid tmpwin;
+    int i, res;
+    menu_item *picks = (menu_item *) 0;
+    anything any;
+    boolean redo;
+    int countall;
+
+shlmenu_redo:
+    redo = FALSE;
+
+    tmpwin = create_nhwindow(NHW_MENU);
+    start_menu(tmpwin);
+
+    status_hilite_linestr_gather();
+
+    countall = status_hilite_linestr_countfield(BL_FLUSH);
+
+    if (countall) {
+        any = zeroany;
+        any.a_int = -1;
+        add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
+                 "View all hilites in config format", MENU_UNSELECTED);
+
+        any = zeroany;
+        add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
+    }
+
     for (i = 0; i < MAXBLSTATS; i++) {
-        if (field_picks[i]) {
-            Sprintf(eos(buf), "%s/%s%s/", fieldids[i].fieldname,
-                    (hltemp[i].behavior == BL_TH_UPDOWN)
-                        ? "updown"
-                        : anything_to_s(thresholdbuf, &hltemp[i].threshold,
-                                        blstats[0][i].anytype),
-                    (hltemp[i].behavior == BL_TH_VAL_PERCENTAGE) ? "%" : "");
-            /* borrow thresholdbuf for use with these last two */
-            Sprintf(eos(buf), "%s/",
-                    clridx_to_s(thresholdbuf, hltemp[i].coloridx[0]));
-            Sprintf(eos(buf), "%s ",
-                    clridx_to_s(thresholdbuf, hltemp[i].coloridx[1]));
-        }
+        int count = status_hilite_linestr_countfield(i);
+        char buf[BUFSZ];
+
+        any = zeroany;
+        any.a_int = (i+1);
+        if (count)
+            Sprintf(buf, "%-18s (%i defined)",
+                    initblstats[i].fldname, count);
+        else
+            Sprintf(buf, "%-18s", initblstats[i].fldname);
+        add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
+                 buf, MENU_UNSELECTED);
+    }
+
+
+    end_menu(tmpwin, "Status hilites:");
+    if ((res = select_menu(tmpwin, PICK_ONE, &picks)) > 0) {
+        i = picks->item.a_int - 1;
+        if (i < 0)
+            status_hilites_viewall();
+        else
+            (void) status_hilite_menu_fld(i);
+        free((genericptr_t) picks);
+        redo = TRUE;
     }
-    return set_status_hilites(buf, FALSE);
+
+    picks = (menu_item *) 0;
+    destroy_nhwindow(tmpwin);
+    status_hilite_linestr_done();
+
+    if (redo)
+        goto shlmenu_redo;
+
+    return TRUE;
 }
-#endif /*STATUS_HILITES*/
-#endif /*STATUS_VIA_WINDOWPORT*/
+
+#endif /* STATUS_HILITES */
 
 /*botl.c*/
index 77ed16bbff72f7148f5b8c168b4e85a4b200c019..c97c7dc93a0ecea81c155fbac3e8fa96fa0f391c 100644 (file)
@@ -264,9 +264,7 @@ NEARDATA char **viz_array = 0; /* used in cansee() and couldsee() macros */
 
 /* Global windowing data, defined here for multi-window-system support */
 NEARDATA winid WIN_MESSAGE = WIN_ERR;
-#ifndef STATUS_VIA_WINDOWPORT
 NEARDATA winid WIN_STATUS = WIN_ERR;
-#endif
 NEARDATA winid WIN_MAP = WIN_ERR, WIN_INVEN = WIN_ERR;
 char toplines[TBUFSZ];
 /* Windowing stuff that's really tty oriented, but present for all ports */
index 3344f577124020896e92bd2317abf22ea1950519..31914dbb5e816e20bfc07f1ce978b5907957dbb2 100644 (file)
--- a/src/end.c
+++ b/src/end.c
@@ -1277,7 +1277,7 @@ int how;
             destroy_nhwindow(WIN_INVEN),  WIN_INVEN = WIN_ERR;
         display_nhwindow(WIN_MESSAGE, TRUE);
         destroy_nhwindow(WIN_MAP),  WIN_MAP = WIN_ERR;
-#ifndef STATUS_VIA_WINDOWPORT
+#ifndef STATUS_HILITES
         destroy_nhwindow(WIN_STATUS),  WIN_STATUS = WIN_ERR;
 #endif
         destroy_nhwindow(WIN_MESSAGE),  WIN_MESSAGE = WIN_ERR;
index 8ca16bab2fd436d7a149b4289f6c25c994d958db..8abacce665664aadffcd8ad88f37d76bb06e05a4 100644 (file)
@@ -2540,6 +2540,11 @@ char *origbuf;
     } else if (match_varname(buf, "MENUCOLOR", 9)) {
         if (!add_menu_coloring(bufp))
             retval = FALSE;
+    } else if (match_varname(buf, "HILITE_STATUS", 6)) {
+#ifdef STATUS_HILITES
+        if (!parse_status_hl1(bufp, TRUE))
+            retval = FALSE;
+#endif
     } else if (match_varname(buf, "WARNINGS", 5)) {
         (void) get_uchars(bufp, translate, FALSE, WARNCOUNT,
                           "WARNINGS");
index 1c4fe63d651b1b2d856f56a58c1ca44c7c3e98d2..5d18fcbf7e24175ff6cd15fa8ecb42725f54bf02 100644 (file)
@@ -20,6 +20,7 @@
         char *          mungspaces      (char *)
         char *          trimspaces      (char *)
         char *          strip_newline   (char *)
+        char *          stripchars      (char *, const char *, const char *)
         char *          eos             (char *)
         boolean         str_end_is      (const char *, const char *)
         char *          strkitten       (char *,char)
@@ -433,6 +434,31 @@ char c;
     return ccc;
 }
 
+/* strip all the chars in stuff_to_strip from orig */
+/* caller is responsible for ensuring that bp is a
+   valid pointer to a BUFSZ buffer */
+char *
+stripchars(bp, stuff_to_strip, orig)
+char *bp;
+const char *stuff_to_strip, *orig;
+{
+    int i = 0;
+    char *s = bp;
+
+    if (s) {
+        while (s && *orig && i < (BUFSZ - 1)) {
+            if (!index(stuff_to_strip, *orig)) {
+                *s++ = *orig;
+                i++;
+            }
+            orig++;
+        }
+        *s = '\0';
+    } else
+        impossible("no output buf in stripchars");
+    return bp;
+}
+
 /* substitute a word or phrase in a string (in place) */
 /* caller is responsible for ensuring that bp points to big enough buffer */
 char *
index 467a669ff459180af5f22adced5ad3ca1aee7cf7..8029f9a04b8827b0fc48ed08e0208ae63f715e1a 100644 (file)
@@ -131,6 +131,9 @@ static struct Bool_Opt {
     { "help", &flags.help, TRUE, SET_IN_GAME },
     { "hilite_pet", &iflags.wc_hilite_pet, FALSE, SET_IN_GAME }, /*WC*/
     { "hilite_pile", &iflags.hilite_pile, FALSE, SET_IN_GAME },
+#ifdef STATUS_HILITES
+    { "hitpointbar", &iflags.wc2_hitpointbar, FALSE, SET_IN_GAME }, /*WC2*/
+#endif
 #ifndef MAC
     { "ignintr", &flags.ignintr, FALSE, SET_IN_GAME },
 #else
@@ -205,11 +208,6 @@ static struct Bool_Opt {
     { "sparkle", &flags.sparkle, TRUE, SET_IN_GAME },
     { "splash_screen", &iflags.wc_splash_screen, TRUE, DISP_IN_GAME }, /*WC*/
     { "standout", &flags.standout, FALSE, SET_IN_GAME },
-#if defined(STATUS_VIA_WINDOWPORT) && defined(STATUS_HILITES)
-    { "statushilites", &iflags.use_status_hilites, TRUE, SET_IN_GAME },
-#else
-    { "statushilites", &iflags.use_status_hilites, FALSE, DISP_IN_GAME },
-#endif
     { "status_updates", &iflags.status_updates, TRUE, DISP_IN_GAME },
     { "tiled_map", &iflags.wc_tiled_map, PREFER_TILED, DISP_IN_GAME }, /*WC*/
     { "time", &flags.time, FALSE, SET_IN_GAME },
@@ -375,6 +373,13 @@ static struct Comp_Opt {
       SET_IN_GAME },
 #ifdef MSDOS
     { "soundcard", "type of sound card to use", 20, SET_IN_FILE },
+#endif
+#ifdef STATUS_HILITES
+    { "statushilites",
+      "0=no status highlighting, N=show highlights for N turns",
+      20, SET_IN_GAME },
+#else
+    { "statushilites", "highlight control", 20, SET_IN_FILE },
 #endif
     { "symset", "load a set of display symbols from the symbols file", 70,
       SET_IN_GAME },
@@ -516,10 +521,7 @@ STATIC_DCL int FDECL(feature_alert_opts, (char *, const char *));
 STATIC_DCL boolean FDECL(duplicate_opt_detection, (const char *, int));
 STATIC_DCL void FDECL(complain_about_duplicate, (const char *, int));
 
-STATIC_DCL int FDECL(match_str2attr, (const char *));
 STATIC_DCL const char *FDECL(attr2attrname, (int));
-STATIC_DCL int NDECL(query_color);
-STATIC_DCL int FDECL(query_attr, (const char *));
 STATIC_DCL const char * FDECL(msgtype2name, (int));
 STATIC_DCL int NDECL(query_msgtype);
 STATIC_DCL boolean FDECL(msgtype_add, (int, char *));
@@ -1279,9 +1281,9 @@ static const struct {
     { "light magenta", CLR_BRIGHT_MAGENTA },
     { "light cyan", CLR_BRIGHT_CYAN },
     { "white", CLR_WHITE },
+    { "no color", NO_COLOR },
     { NULL, CLR_BLACK }, /* everything after this is an alias */
     { "transparent", NO_COLOR },
-    { "nocolor", NO_COLOR },
     { "purple", CLR_MAGENTA },
     { "light purple", CLR_BRIGHT_MAGENTA },
     { "bright purple", CLR_BRIGHT_MAGENTA },
@@ -1302,7 +1304,10 @@ static const struct {
     { "dim", ATR_DIM },
     { "underline", ATR_ULINE },
     { "blink", ATR_BLINK },
-    { "inverse", ATR_INVERSE }
+    { "inverse", ATR_INVERSE },
+    { NULL, ATR_NONE }, /* everything after this is an alias */
+    { "normal", ATR_NONE },
+    { "uline", ATR_ULINE }
 };
 
 const char *
@@ -1321,7 +1326,7 @@ int
 match_str2clr(str)
 char *str;
 {
-    int i, c = NO_COLOR;
+    int i, c = CLR_MAX;
 
     /* allow "lightblue", "light blue", and "light-blue" to match "light blue"
        (also junk like "_l i-gh_t---b l u e" but we won't worry about that);
@@ -1353,9 +1358,10 @@ int attr;
     return (char *) 0;
 }
 
-STATIC_OVL int
-match_str2attr(str)
+int
+match_str2attr(str, complain)
 const char *str;
+boolean complain;
 {
     int i, a = -1;
 
@@ -1366,14 +1372,15 @@ const char *str;
             break;
         }
 
-    if (a == -1)
+    if (a == -1 && complain)
         config_error_add("Unknown text attribute '%s'", str);
 
     return a;
 }
 
-STATIC_OVL int
-query_color()
+int
+query_color(prompt)
+const char *prompt;
 {
     winid tmpwin;
     anything any;
@@ -1390,7 +1397,7 @@ query_color()
         add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, colornames[i].name,
                  MENU_UNSELECTED);
     }
-    end_menu(tmpwin, "Pick a color");
+    end_menu(tmpwin, (prompt && *prompt) ? prompt : "Pick a color");
     pick_cnt = select_menu(tmpwin, PICK_ONE, &picks);
     destroy_nhwindow(tmpwin);
     if (pick_cnt > 0) {
@@ -1401,7 +1408,7 @@ query_color()
     return -1;
 }
 
-STATIC_OVL int
+int
 query_attr(prompt)
 const char *prompt;
 {
@@ -1420,7 +1427,7 @@ const char *prompt;
         add_menu(tmpwin, NO_GLYPH, &any, 0, 0, attrnames[i].attr,
                  attrnames[i].name, MENU_UNSELECTED);
     }
-    end_menu(tmpwin, prompt ? prompt : "Pick an attribute");
+    end_menu(tmpwin, (prompt && *prompt) ? prompt : "Pick an attribute");
     pick_cnt = select_menu(tmpwin, PICK_ONE, &picks);
     destroy_nhwindow(tmpwin);
     if (pick_cnt > 0) {
@@ -1706,7 +1713,7 @@ char *tmpstr;
 
     if (amp) {
         tmps = amp + 1; /* advance past '&' */
-        a = match_str2attr(tmps);
+        a = match_str2attr(tmps, TRUE);
         if (a == -1)
             return FALSE;
     }
@@ -3427,7 +3434,7 @@ boolean tinitial, tfrom_file;
         } else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
             return FALSE;
         }
-        tmpattr = match_str2attr(opts);
+        tmpattr = match_str2attr(opts, TRUE);
         if (tmpattr == -1)
             return FALSE;
         else
@@ -3458,23 +3465,39 @@ boolean tinitial, tfrom_file;
             return retval;
         }
     }
-#if defined(STATUS_VIA_WINDOWPORT) && defined(STATUS_HILITES)
+#ifdef STATUS_HILITES
     /* hilite fields in status prompt */
     if (match_optname(opts, "hilite_status", 13, TRUE)) {
         if (duplicate)
             complain_about_duplicate(opts, 1);
         op = string_for_opt(opts, TRUE);
         if (op && negated) {
-            clear_status_hilites(tfrom_file);
+            clear_status_hilites();
             return retval;
         } else if (!op) {
             config_error_add("Value is mandatory for hilite_status");
             return FALSE;
         }
-        if (!set_status_hilites(op, tfrom_file)) /* TODO: error msg? */
+        if (!parse_status_hl1(op, tfrom_file))
             return FALSE;
         return retval;
     }
+
+    /* control over whether highlights should be displayed, and for how long */
+    fullname = "statushilites";
+    if (match_optname(opts, fullname, 9, TRUE)) {
+        if (negated) {
+            iflags.hilite_delta = 0L;
+        } else {
+            op = string_for_opt(opts, TRUE);
+            iflags.hilite_delta = (!op || !*op) ? 3L : atol(op);
+            if (iflags.hilite_delta < 0L)
+                iflags.hilite_delta = 1L;
+        }
+        if (!tfrom_file)
+            reset_status_hilites();
+        return retval;
+    }
 #endif
 
 #if defined(BACKWARD_COMPAT)
@@ -3624,7 +3647,7 @@ boolean tinitial, tfrom_file;
                 || boolopt[i].addr == &flags.showscore
 #endif
                 || boolopt[i].addr == &flags.showexp) {
-#ifdef STATUS_VIA_WINDOWPORT
+#ifdef STATUS_HILITES
                 status_initialize(REASSESS_ONLY);
 #endif
                 context.botl = TRUE;
@@ -3650,6 +3673,9 @@ boolean tinitial, tfrom_file;
                        || boolopt[i].addr == &iflags.hilite_pile
                        || boolopt[i].addr == &iflags.hilite_pet) {
                 need_redraw = TRUE;
+            } else if ((boolopt[i].addr) == &iflags.wc2_hitpointbar) {
+                status_initialize(REASSESS_ONLY);
+                need_redraw = TRUE;
 #ifdef TEXTCOLOR
             } else if (boolopt[i].addr == &iflags.use_color) {
                 need_redraw = TRUE;
@@ -3954,10 +3980,8 @@ static struct other_opts {
     { "autopickup exceptions", SET_IN_GAME, OPT_OTHER_APEXC },
     { "menucolors", SET_IN_GAME, OPT_OTHER_MENUCOLOR },
     { "message types", SET_IN_GAME, OPT_OTHER_MSGTYPE },
-#ifdef STATUS_VIA_WINDOWPORT
 #ifdef STATUS_HILITES
-    { "status_hilites", SET_IN_GAME, OPT_OTHER_STATHILITE },
-#endif
+    { "status hilite rules", SET_IN_GAME, OPT_OTHER_STATHILITE },
 #endif
     { (char *) 0, 0, (enum opt_other_enums) 0 },
 };
@@ -4092,13 +4116,9 @@ doset() /* changing options via menu by Per Liboriussen */
                     NULL, count_menucolors());
     opts_add_others(tmpwin, "message types", OPT_OTHER_MSGTYPE,
                     NULL, msgtype_count());
-#ifdef STATUS_VIA_WINDOWPORT
 #ifdef STATUS_HILITES
-    get_status_hilites(buf2, 60);
-    if (!*buf2)
-        Sprintf(buf2, "%s", "(none)");
-    opts_add_others(tmpwin, "status_hilites", OPT_OTHER_STATHILITE, buf2, 0);
-#endif
+    opts_add_others(tmpwin, "status hilite rules", OPT_OTHER_STATHILITE,
+                    NULL, count_status_hilites());
 #endif
 #ifdef PREFIXES_IN_USE
     any = zeroany;
@@ -4123,16 +4143,14 @@ doset() /* changing options via menu by Per Liboriussen */
             if (opt_indx == OPT_OTHER_APEXC) {
                 (void) special_handling("autopickup_exception", setinitial,
                                         fromfile);
-#ifdef STATUS_VIA_WINDOWPORT
 #ifdef STATUS_HILITES
             } else if (opt_indx == OPT_OTHER_STATHILITE) {
                 if (!status_hilite_menu()) {
                     pline("Bad status hilite(s) specified.");
                 } else {
-                    if (wc2_supported("status_hilites"))
-                        preference_update("status_hilites");
+                    if (wc2_supported("hilite_status"))
+                        preference_update("hilite_status");
                 }
-#endif
 #endif
             } else if (opt_indx == OPT_OTHER_MENUCOLOR) {
                     (void) special_handling("menucolors", setinitial,
@@ -4728,7 +4746,7 @@ boolean setinitial, setfromfile;
                 return TRUE;
             if (*mcbuf
                 && test_regex_pattern(mcbuf, (const char *)0)
-                && (mcclr = query_color()) != -1
+                && (mcclr = query_color((char *) 0)) != -1
                 && (mcattr = query_attr((char *) 0)) != -1
                 && !add_menu_coloring_parsed(mcbuf, mcclr, mcattr)) {
                 pline("Error adding the menu color.");
@@ -5305,6 +5323,14 @@ char *buf;
 #ifdef MSDOS
     } else if (!strcmp(optname, "soundcard")) {
         Sprintf(buf, "%s", to_be_done);
+#endif
+#ifdef STATUS_HILITES
+    } else if (!strcmp("statushilites", optname)) {
+        if (!iflags.hilite_delta)
+            Strcpy(buf, "0 (off: don't highlight status fields)");
+        else
+            Sprintf(buf, "%ld (on: highlight status for %ld turns)",
+                    iflags.hilite_delta, iflags.hilite_delta);
 #endif
     } else if (!strcmp(optname, "suppress_alert")) {
         if (flags.suppress_alert == 0L)
@@ -6010,7 +6036,8 @@ struct wc_Opt wc2_options[] = { { "fullscreen", WC2_FULLSCREEN },
                                 { "softkeyboard", WC2_SOFTKEYBOARD },
                                 { "wraptext", WC2_WRAPTEXT },
                                 { "use_darkgray", WC2_DARKGRAY },
-#ifdef STATUS_VIA_WINDOWPORT
+#ifdef STATUS_HILITES
+                                { "hitpointbar", WC2_HITPOINTBAR },
                                 { "hilite_status", WC2_HILITE_STATUS },
 #endif
                                 { (char *) 0, 0L } };
index 9b15b32c073e0b5557d15354cc82808ad128a694..c1dc74ff61de927150ec3b1447aa6395e05dbe78 100644 (file)
@@ -107,9 +107,11 @@ set_uasmon()
             youmonst.movement = new_speed * youmonst.movement / old_speed;
     }
 
-#ifdef STATUS_VIA_WINDOWPORT
+#ifdef STATUS_HILITES
     status_initialize(REASSESS_ONLY);
 #endif
+
+    polysense();
 }
 
 /* Levitation overrides Flying; set or clear BFlying|I_SPECIAL */
index b907b1ad182d400b06f729838d6813ff5f6eb597..8426a2ceecac32112c773009db6c863761ef68bc 100644 (file)
@@ -1410,7 +1410,7 @@ freedynamicdata()
     /* free_pickinv_cache();  --  now done from really_done()... */
     free_symsets();
 #endif /* FREE_ALL_MEMORY */
-#ifdef STATUS_VIA_WINDOWPORT
+#ifdef STATUS_HILITES
     status_finish();
 #endif
 #ifdef DUMPLOG
index a23ec95c70eccf2a20e2814ba3ac5e6359daf5d8..7a62582e6e43eeade8fca90cc7debcfb5f2e559f 100644 (file)
@@ -474,9 +474,7 @@ static short FDECL(hup_set_font_name, (winid, char *));
 #endif
 static char *NDECL(hup_get_color_string);
 #endif /* CHANGE_COLOR */
-#ifdef STATUS_VIA_WINDOWPORT
-static void FDECL(hup_status_update, (int, genericptr_t, int, int));
-#endif
+static void FDECL(hup_status_update, (int, genericptr_t, int, int, int, unsigned long *));
 
 static int NDECL(hup_int_ndecl);
 static void NDECL(hup_void_ndecl);
@@ -526,14 +524,9 @@ static struct window_procs hup_procs = {
     hup_void_ndecl,                                   /* end_screen */
     hup_outrip, genl_preference_update, genl_getmsghistory,
     genl_putmsghistory,
-#ifdef STATUS_VIA_WINDOWPORT
     hup_void_ndecl,                                   /* status_init */
     hup_void_ndecl,                                   /* status_finish */
     genl_status_enablefield, hup_status_update,
-#ifdef STATUS_HILITES
-    genl_status_threshold,
-#endif
-#endif /* STATUS_VIA_WINDOWPORT */
     genl_can_suspend_no,
 };
 
@@ -762,17 +755,17 @@ hup_get_color_string(VOID_ARGS)
 }
 #endif /* CHANGE_COLOR */
 
-#ifdef STATUS_VIA_WINDOWPORT
 /*ARGSUSED*/
 static void
-hup_status_update(idx, ptr, chg, percent)
+hup_status_update(idx, ptr, chg, pc, color, colormasks)
 int idx UNUSED;
 genericptr_t ptr UNUSED;
-int chg UNUSED, percent UNUSED;
+int chg UNUSED, pc UNUSED, color UNUSED;
+unsigned long *colormasks UNUSED;
+
 {
     return;
 }
-#endif /* STATUS_VIA_WINDOWPORT */
 
 /*
  * Non-specific stubs.
@@ -816,7 +809,6 @@ const char *string UNUSED;
 
 #endif /* HANGUPHANDLING */
 
-#ifdef STATUS_VIA_WINDOWPORT
 
 /****************************************************************************/
 /* genl backward compat stuff                                               */
@@ -871,10 +863,11 @@ boolean enable;
 
 /* call once for each field, then call with BL_FLUSH to output the result */
 void
-genl_status_update(idx, ptr, chg, percent)
+genl_status_update(idx, ptr, chg, percent, color, colormasks)
 int idx;
 genericptr_t ptr;
-int chg UNUSED, percent UNUSED;
+int chg UNUSED, percent UNUSED, color UNUSED;
+unsigned long *colormasks UNUSED;
 {
     char newbot1[MAXCO], newbot2[MAXCO];
     long cond, *condptr = (long *) ptr;
@@ -912,12 +905,17 @@ int chg UNUSED, percent UNUSED;
           BL_LEVELDESC, BL_GOLD, BL_XP, BL_EXP, BL_HD, BL_TIME, BL_FLUSH },
     };
 
+    /* in case interface is using genl_status_update() but has not
+       specified WC2_FLUSH_STATUS (status_update() for field values
+       is buffered so final BL_FLUSH is needed to produce output) */
+    windowprocs.wincap2 |= WC2_FLUSH_STATUS;
+
     if (idx != BL_FLUSH) {
         if (!status_activefields[idx])
             return;
         switch (idx) {
         case BL_CONDITION:
-            cond = *condptr;
+            cond = condptr ? *condptr : 0L;
             nb = status_vals[idx];
             *nb = '\0';
             if (cond & BL_MASK_STONE)
@@ -949,7 +947,8 @@ int chg UNUSED, percent UNUSED;
             break;
         default:
             Sprintf(status_vals[idx],
-                    status_fieldfmt[idx] ? status_fieldfmt[idx] : "%s", text);
+                    status_fieldfmt[idx] ? status_fieldfmt[idx] : "%s",
+                    text ? text : "");
             break;
         }
         return; /* processed one field other than BL_FLUSH */
@@ -1035,18 +1034,6 @@ int chg UNUSED, percent UNUSED;
     putmixed(WIN_STATUS, 0, newbot2); /* putmixed() due to GOLD glyph */
 }
 
-#ifdef STATUS_HILITES
-void
-genl_status_threshold(fldidx, thresholdtype, threshold, behavior, under, over)
-int fldidx UNUSED, thresholdtype UNUSED;
-anything threshold UNUSED;
-int behavior UNUSED, under UNUSED, over UNUSED;
-{
-    return;
-}
-#endif /* STATUS_HILITES */
-#endif /* STATUS_VIA_WINDOWPORT */
-
 STATIC_VAR struct window_procs dumplog_windowprocs_backup;
 STATIC_VAR FILE *dumplog_file;
 
index 58d4165da8c9a451d872c857ed761345f79dca7f..1819ccde368472da2187874cced7040ac86aa2f6 100644 (file)
@@ -51,13 +51,8 @@ struct window_procs amii_procs = {
     /* other defs that really should go away (they're tty specific) */
     amii_delay_output, amii_delay_output, amii_outrip, genl_preference_update,
     genl_getmsghistory, genl_putmsghistory,
-#ifdef STATUS_VIA_WINDOWPORT
     genl_status_init, genl_status_finish, genl_status_enablefield,
     genl_status_update,
-#ifdef STATUS_HILITES
-    genl_status_threshold,
-#endif
-#endif
     genl_can_suspend_yes,
 };
 
@@ -88,13 +83,8 @@ struct window_procs amiv_procs = {
     /* other defs that really should go away (they're tty specific) */
     amii_delay_output, amii_delay_output, amii_outrip, genl_preference_update,
     genl_getmsghistory, genl_putmsghistory,
-#ifdef STATUS_VIA_WINDOWPORT
     genl_status_init, genl_status_finish, genl_status_enablefield,
     genl_status_update,
-#ifdef STATUS_HILITES
-    genl_status_threshold,
-#endif
-#endif
     genl_can_suspend_yes,
 };
 
index 500306875aec303966c32038a4ae3f0059a59140..7137a062a7f87347e6d1269e506945f264b4141b 100644 (file)
@@ -73,13 +73,8 @@ struct window_procs mswin_procs = {
     /* other defs that really should go away (they're tty specific) */
     mswin_start_screen, mswin_end_screen, mswin_outrip,
     mswin_preference_update, genl_getmsghistory, genl_putmsghistory,
-#ifdef STATUS_VIA_WINDOWPORT
     genl_status_init, genl_status_finish, genl_status_enablefield,
     genl_status_update,
-#ifdef STATUS_HILITES
-    genl_status_threshold,
-#endif
-#endif
     genl_can_suspend_no,
 };
 
index 7a77e4612d9b8a74e4ed3eb43b197356187552ce..64bea743c64ae0738b4531195df8782a2fd53ab5 100644 (file)
@@ -42,9 +42,7 @@ void FDECL(cmov, (int, int));
 void FDECL(nocmov, (int, int));
 int FDECL(process_keystroke,
           (INPUT_RECORD *, boolean *, BOOLEAN_P numberpad, int portdebug));
-#ifdef TEXTCOLOR
 static void NDECL(init_ttycolor);
-#endif
 static void NDECL(really_move_cursor);
 
 /* Win32 Console handles for input and output */
@@ -111,8 +109,10 @@ static DWORD ccount, acount;
 #ifndef CLR_MAX
 #define CLR_MAX 16
 #endif
+
 int ttycolors[CLR_MAX];
 int ttycolors_inv[CLR_MAX];
+
 #define MAX_OVERRIDES 256
 unsigned char key_overrides[MAX_OVERRIDES];
 static char nullstr[] = "";
@@ -158,7 +158,7 @@ gettty()
     init_ttycolor();
 #else
     for (k = 0; k < CLR_MAX; ++k)
-        ttycolors[k] = 7;
+        ttycolors[k] = NO_COLOR;
 #endif
 }
 
@@ -692,6 +692,7 @@ tty_delay_output()
 static void
 init_ttycolor()
 {
+#ifdef TEXTCOLOR
     ttycolors[CLR_BLACK]        = FOREGROUND_INTENSITY; /* fix by Quietust */
     ttycolors[CLR_RED]          = FOREGROUND_RED;
     ttycolors[CLR_GREEN]        = FOREGROUND_GREEN;
@@ -728,6 +729,15 @@ init_ttycolor()
     ttycolors_inv[CLR_BRIGHT_CYAN] = BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY;
     ttycolors_inv[CLR_WHITE]       = BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED
                                        | BACKGROUND_INTENSITY;
+#else
+    int k;
+    ttycolors[0] = FOREGROUND_INTENSITY;
+    ttycolors_inv[0] = BACKGROUND_INTENSITY;
+    for (k = 1; k < SIZE(ttycolors); ++k) {
+        ttycolors[k] = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED;
+        ttycolors_inv[k] = BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED;
+    }
+#endif
     init_ttycolor_completed = TRUE;
 }
 #endif /* TEXTCOLOR */
@@ -739,7 +749,7 @@ has_color(int color)
     if ((color >= 0) && (color < CLR_MAX))
         return 1;
 #else
-    if ((color == CLR_BLACK) || (color == CLR_WHITE))
+    if ((color == CLR_BLACK) || (color == CLR_WHITE) || (color == NO_COLOR))
         return 1;
 #endif
     else
@@ -794,7 +804,7 @@ term_start_color(int color)
         console.current_nhcolor = color;
     } else
 #endif
-    console.current_nhcolor = color;
+    console.current_nhcolor = NO_COLOR;
 }
 
 void
index 92d1feb897e2a3cce1be0f9ba251066fbcea1847..cfcabb3ca674da182cf2f94c688bb9df1037afb9 100644 (file)
@@ -1501,14 +1501,11 @@ static const char *build_opts[] = {
 #ifdef SHELL
     "shell command",
 #endif
-#ifdef STATUS_VIA_WINDOWPORT
-# ifdef STATUS_HILITES
+    "traditional status display",
+#ifdef STATUS_HILITES
     "status via windowport with highlighting",
-# else
-    "status via windowport without highlighting",
-# endif
 #else
-    "traditional status display",
+    "status via windowport without highlighting",
 #endif
 #ifdef SUSPEND
     "suspend command",
index 52c925ae63f033bc983185752c052d02259ba5f8..84ac6a82c1aa9dc93f81335ddfeaec6398c61686 100644 (file)
@@ -5286,15 +5286,11 @@ struct window_procs Qt_procs = {
     genl_preference_update,
     genl_getmsghistory,
     genl_putmsghistory,
-#ifdef STATUS_VIA_WINDOWPORT
     genl_status_init,
     genl_status_finish,
     genl_status_enablefield,
     genl_status_update,
-# ifdef STATUS_HILITES
-    genl_status_threshold,
-# endif
-#endif
+    genl_can_suspend_yes,
 };
 
 extern "C" void play_usersound(const char* filename, int volume)
index 25229541a24e98d96623bea849ca226dd014b3db..78e304b1f3824baf7c32c0e120d5e397a4c2d884 100644 (file)
@@ -125,13 +125,8 @@ struct window_procs X11_procs = {
     genl_outrip,
 #endif
     X11_preference_update, genl_getmsghistory, genl_putmsghistory,
-#ifdef STATUS_VIA_WINDOWPORT
     genl_status_init, genl_status_finish, genl_status_enablefield,
     genl_status_update,
-#ifdef STATUS_HILITES
-    genl_status_threshold,
-#endif
-#endif
     genl_can_suspend_no, /* XXX may not always be correct */
 };
 
index 66362bd0bea335a4aa405b1c3665690db4c652f4..bd0a1182748f7caa3b4e380e0fbbac246f064a33 100644 (file)
@@ -462,7 +462,6 @@ boolean is_restoring;
     (*cibase->nprocs->win_putmsghistory)(cibase->ndata, msg, is_restoring);
 }
 
-#ifdef STATUS_VIA_WINDOWPORT
 void
 chainin_status_init()
 {
@@ -487,29 +486,15 @@ boolean enable;
 }
 
 void
-chainin_status_update(idx, ptr, chg, percent)
-int idx, chg, percent;
+chainin_status_update(idx, ptr, chg, percent, color, colormasks)
+int idx, chg, percent, color;
 genericptr_t ptr;
+unsigned long *colormasks;
 {
     (*cibase->nprocs->win_status_update)(cibase->ndata, idx, ptr, chg,
-                                         percent);
+                                         percent, color, colormasks);
 }
 
-#ifdef STATUS_HILITES
-void
-chainin_status_threshold(fldidx, thresholdtype, threshold, behavior, under,
-                         over)
-int fldidx, thresholdtype;
-int behavior, under, over;
-anything threshold;
-{
-    (*cibase->nprocs->win_status_threshold)(cibase->ndata, fldidx,
-                                            thresholdtype, threshold,
-                                            behavior, under, over);
-}
-#endif
-#endif
-
 boolean
 chainin_can_suspend()
 {
@@ -561,12 +546,7 @@ struct window_procs chainin_procs = {
 
     chainin_outrip, chainin_preference_update, chainin_getmsghistory,
     chainin_putmsghistory,
-#ifdef STATUS_VIA_WINDOWPORT
     chainin_status_init, chainin_status_finish, chainin_status_enablefield,
     chainin_status_update,
-#ifdef STATUS_HILITES
-    chainin_status_threshold,
-#endif
-#endif
     chainin_can_suspend,
 };
index 85b265117aa3417ae40548242aefb2f2da1dbcc1..593bd6cd88fa9fd645edce6c5703a53372788815 100644 (file)
@@ -586,7 +586,6 @@ boolean is_restoring;
     (*tdp->nprocs->win_putmsghistory)(msg, is_restoring);
 }
 
-#ifdef STATUS_VIA_WINDOWPORT
 void
 chainout_status_init(vp)
 void *vp;
@@ -619,33 +618,17 @@ boolean enable;
 }
 
 void
-chainout_status_update(vp, idx, ptr, chg, percent)
+chainout_status_update(vp, idx, ptr, chg, percent, color, colormasks)
 void *vp;
 int idx, chg, percent;
 genericptr_t ptr;
+unsigned long *colormasks;
 {
     struct chainout_data *tdp = vp;
 
-    (*tdp->nprocs->win_status_update)(idx, ptr, chg, percent);
+    (*tdp->nprocs->win_status_update)(idx, ptr, chg, percent, color, colormasks);
 }
 
-#ifdef STATUS_HILITES
-void
-chainout_status_threshold(vp, fldidx, thresholdtype, threshold, behavior,
-                          under, over)
-void *vp;
-int fldidx, thresholdtype;
-int behavior, under, over;
-anything threshold;
-{
-    struct chainout_data *tdp = vp;
-
-    (*tdp->nprocs->win_status_threshold)(fldidx, thresholdtype, threshold,
-                                         behavior, under, over);
-}
-#endif
-#endif
-
 boolean
 chainout_can_suspend(vp)
 void *vp;
@@ -700,12 +683,7 @@ struct chain_procs chainout_procs = {
 
     chainout_outrip, chainout_preference_update, chainout_getmsghistory,
     chainout_putmsghistory,
-#ifdef STATUS_VIA_WINDOWPORT
     chainout_status_init, chainout_status_finish, chainout_status_enablefield,
     chainout_status_update,
-#ifdef STATUS_HILITES
-    chainout_status_threshold,
-#endif
-#endif
     chainout_can_suspend,
 };
index b3d21e7ea1f845f4e283094c8b87acf492a28ca7..60877623d0b003de49367aa04db4e7121afebb0e 100644 (file)
@@ -1027,7 +1027,6 @@ boolean is_restoring;
     POST;
 }
 
-#ifdef STATUS_VIA_WINDOWPORT
 void
 trace_status_init(vp)
 void *vp;
@@ -1084,10 +1083,11 @@ boolean enable;
 }
 
 void
-trace_status_update(vp, idx, ptr, chg, percent)
+trace_status_update(vp, idx, ptr, chg, color, colormasks)
 void *vp;
 int idx, chg, percent;
 genericptr_t ptr;
+unsigned long *colormasks;
 {
     struct trace_data *tdp = vp;
 
@@ -1095,33 +1095,10 @@ genericptr_t ptr;
             ptr, chg, percent);
 
     PRE;
-    (*tdp->nprocs->win_status_update)(tdp->ndata, idx, ptr, chg, percent);
+    (*tdp->nprocs->win_status_update)(tdp->ndata, idx, ptr, chg, color colormasks);
     POST;
 }
 
-#ifdef STATUS_HILITES
-void
-trace_status_threshold(vp, fldidx, thresholdtype, threshold, behavior, under,
-                       over)
-void *vp;
-int fldidx, thresholdtype;
-int behavior, under, over;
-anything threshold;
-{
-    struct trace_data *tdp = vp;
-
-    /* XXX how do we print an anything?  We don't. */
-    fprintf(wc_tracelogf, "%sstatus_threshold(%d, %d, -, %d, %d, %d)\n",
-            INDENT, fldidx, thresholdtype, behavior, under, over);
-
-    PRE;
-    (*tdp->nprocs->win_status_threshold)(tdp->ndata, fldidx, thresholdtype,
-                                         threshold, behavior, under, over);
-    POST;
-}
-#endif
-#endif
-
 boolean
 trace_can_suspend(vp)
 void *vp;
@@ -1179,12 +1156,7 @@ struct chain_procs trace_procs = {
 
     trace_outrip, trace_preference_update, trace_getmsghistory,
     trace_putmsghistory,
-#ifdef STATUS_VIA_WINDOWPORT
     trace_status_init, trace_status_finish, trace_status_enablefield,
     trace_status_update,
-#ifdef STATUS_HILITES
-    trace_status_threshold,
-#endif
-#endif
     trace_can_suspend,
 };
index 72daffd14550a4fbd435b899f74f28cddc12034b..8cd33ca2aea322c387bb8e11f7431af6d57fa1eb 100644 (file)
@@ -70,13 +70,8 @@ struct window_procs Gem_procs = {
     /* other defs that really should go away (they're tty specific) */
     Gem_start_screen, Gem_end_screen, Gem_outrip, Gem_preference_update,
     genl_getmsghistory, genl_putmsghistory
-#ifdef STATUS_VIA_WINDOWPORT
                             genl_status_init,
     genl_status_finish, genl_status_enablefield, genl_status_update,
-#ifdef STATUS_HILITES
-    genl_status_threshold,
-#endif
-#endif
     genl_can_suspend_no,
 };
 
index afeef0d1c8d6988090185d65e0f04413a716cd70..bc35214974783fd9b4e30a28cbf4d1e5faa6a683 100644 (file)
@@ -48,13 +48,8 @@ struct window_procs Gnome_procs = {
     /* other defs that really should go away (they're tty specific) */
     gnome_start_screen, gnome_end_screen, gnome_outrip,
     genl_preference_update, genl_getmsghistory, genl_putmsghistory,
-#ifdef STATUS_VIA_WINDOWPORT
     genl_status_init, genl_status_finish, genl_status_enablefield,
     genl_status_update,
-#ifdef STATUS_HILITES
-    genl_status_threshold,
-#endif
-#endif
     genl_can_suspend_yes,
 };
 
index 7e504d669960b8868c2f0ad49691a0df4f6e95df..205bb65790bf2d400420bacf7fecf2d30a6d7bdd 100644 (file)
@@ -62,6 +62,9 @@ struct window_procs tty_procs = {
         WC_COLOR | WC_HILITE_PET | WC_INVERSE | WC_EIGHT_BIT_IN,
 #if defined(SELECTSAVED)
     WC2_SELECTSAVED |
+#endif
+#if defined(STATUS_HILITES)
+    WC2_HITPOINTBAR | WC2_FLUSH_STATUS |
 #endif
         WC2_DARKGRAY,
     tty_init_nhwindows, tty_player_selection, tty_askname, tty_get_nh_event,
@@ -96,13 +99,12 @@ struct window_procs tty_procs = {
     genl_preference_update,
 #endif
     tty_getmsghistory, tty_putmsghistory,
-#ifdef STATUS_VIA_WINDOWPORT
     tty_status_init,
     genl_status_finish, genl_status_enablefield,
-    tty_status_update,
 #ifdef STATUS_HILITES
-    tty_status_threshold,
-#endif
+    tty_status_update,
+#else
+    genl_status_update,
 #endif
     genl_can_suspend_yes,
 };
@@ -1293,9 +1295,7 @@ const char *str;
         }
     }
     WIN_MAP = WIN_MESSAGE = WIN_INVEN = WIN_ERR; /* these are all gone now */
-#ifndef STATUS_VIA_WINDOWPORT
     WIN_STATUS = WIN_ERR;
-#endif
 #ifdef FREE_ALL_MEMORY
     if (BASE_WINDOW != WIN_ERR && wins[BASE_WINDOW]) {
         free_window_info(wins[BASE_WINDOW], TRUE);
@@ -2527,7 +2527,16 @@ const char *str;
                 }
                 break;
             }
+#ifdef STATUS_HILITES
+            /* Don't optimize the putsym away, in case it happens
+               to be the same character but different color/attr.
+               We don't optimize on iflags.use_status_hilites either,
+               in case old chars were written with highlighting and
+               that option has just now been toggled off.  [We could
+               do better by tracking color/attr more closely.] */
+#else
             if (*ob != *nb)
+#endif
                 tty_putsym(WIN_STATUS, i, cw->cury, *nb);
             if (*ob)
                 ob++;
@@ -2535,13 +2544,9 @@ const char *str;
 
         (void) strncpy(&cw->data[cw->cury][j], str, cw->cols - j - 1);
         cw->data[cw->cury][cw->cols - 1] = '\0'; /* null terminate */
-#ifdef STATUS_VIA_WINDOWPORT
-        if (!iflags.use_status_hilites) {
-#endif
-            cw->cury = (cw->cury + 1) % 2;
-            cw->curx = 0;
-#ifdef STATUS_VIA_WINDOWPORT
-        }
+#ifndef STATUS_HILITES
+        cw->cury = (cw->cury + 1) % 2;
+        cw->curx = 0;
 #endif
         break;
     case NHW_MAP:
@@ -3402,40 +3407,26 @@ char *posbar;
 }
 #endif
 
-#ifdef STATUS_VIA_WINDOWPORT
 /*
  * The following data structures come from the genl_ routines in
  * src/windows.c and as such are considered to be on the window-port
  * "side" of things, rather than the NetHack-core "side" of things.
  */
 
-extern const char *status_fieldnm[MAXBLSTATS];
 extern const char *status_fieldfmt[MAXBLSTATS];
 extern char *status_vals[MAXBLSTATS];
 extern boolean status_activefields[MAXBLSTATS];
 extern winid WIN_STATUS;
 
 #ifdef STATUS_HILITES
-typedef struct hilite_data_struct {
-    int thresholdtype;
-    anything threshold;
-    int behavior;
-    int under;
-    int over;
-} hilite_data_t;
-static hilite_data_t tty_status_hilites[MAXBLSTATS];
+static long tty_condition_bits;
 static int tty_status_colors[MAXBLSTATS];
+int hpbar_percent, hpbar_color;
+#endif /* STATUS_HILITES */
 
-struct color_option {
-    int color;
-    int attr_bits;
-};
+static int FDECL(condcolor, (long, unsigned long *));
+static int FDECL(condattr, (long, unsigned long *));
 
-static void FDECL(start_color_option, (struct color_option));
-static void FDECL(end_color_option, (struct color_option));
-static void FDECL(apply_color_option, (struct color_option, const char *));
-static void FDECL(add_colored_text, (const char *, char *));
-#endif
 
 void
 tty_status_init()
@@ -3445,15 +3436,11 @@ tty_status_init()
     /* let genl_status_init do most of the initialization */
     genl_status_init();
 
-    for (i = 0; i < MAXBLSTATS; ++i) {
 #ifdef STATUS_HILITES
+    for (i = 0; i < MAXBLSTATS; ++i) {
         tty_status_colors[i] = NO_COLOR; /* no color */
-        tty_status_hilites[i].thresholdtype = 0;
-        tty_status_hilites[i].behavior = BL_TH_NONE;
-        tty_status_hilites[i].under = BL_HILITE_NONE;
-        tty_status_hilites[i].over = BL_HILITE_NONE;
-#endif /* STATUS_HILITES */
     }
+#endif /* STATUS_HILITES */
 }
 
 /*
@@ -3490,22 +3477,102 @@ tty_status_init()
  *         symbol for GOLD "\GXXXXNNNN:nnn". If the window port needs to use
  *         the textual gold amount without the leading "$:" the port will
  *         have to skip past ':' in the passed "ptr" for the BL_GOLD case.
+ *      -- color is an unsigned int.
+ *               color_index = color & 0x00FF;       CLR_* value
+ *               attribute   = color & 0xFF00 >> 8;  BL_* values
+ *         This holds the color and attribute that the field should
+ *         be displayed in.
+ *         This is relevant for everything except BL_CONDITION fldindex.
+ *         If fldindex is BL_CONDITION, this parameter should be ignored,
+ *         as condition hilighting is done via the next colormasks
+ *         parameter instead.
+ *
+ *      -- colormasks - pointer to cond_hilites[] array of colormasks.
+ *         Only relevant for BL_CONDITION fldindex. The window port
+ *         should ignore this parameter for other fldindex values.
+ *         Each condition bit must only ever appear in one of the
+ *         CLR_ array members, but can appear in multiple HL_ATTCLR_
+ *         offsets (because more than one attribute can co-exist).
+ *         See doc/window.doc for more details.
  */
+
+
+/* new approach through status_update() only */
+#define Begin_Attr(m) \
+            if (m) {                                                          \
+                if ((m) & HL_BOLD)                                            \
+                    term_start_attr(ATR_BOLD);                                \
+                if ((m) & HL_INVERSE)                                         \
+                    term_start_attr(ATR_INVERSE);                             \
+                if ((m) & HL_ULINE)                                           \
+                    term_start_attr(ATR_ULINE);                               \
+                if ((m) & HL_BLINK)                                           \
+                    term_start_attr(ATR_BLINK);                               \
+                if ((m) & HL_DIM)                                             \
+                    term_start_attr(ATR_DIM);                                 \
+           }
+
+#define End_Attr(m) \
+            if (m) {                                                          \
+                if ((m) & HL_DIM)                                             \
+                    term_end_attr(ATR_DIM);                                   \
+                if ((m) & HL_BLINK)                                           \
+                    term_end_attr(ATR_BLINK);                                 \
+                if ((m) & HL_ULINE)                                           \
+                    term_end_attr(ATR_ULINE);                                 \
+                if ((m) & HL_INVERSE)                                         \
+                    term_end_attr(ATR_INVERSE);                               \
+                if ((m) & HL_BOLD)                                            \
+                    term_end_attr(ATR_BOLD);                                  \
+           }
+
+#ifdef STATUS_HILITES
+
+#ifdef TEXTCOLOR
+#define MaybeDisplayCond(bm,txt) \
+            if (tty_condition_bits & (bm)) {                                  \
+                putstr(WIN_STATUS, 0, " ");                                   \
+                if (iflags.hilite_delta) {                                    \
+                    attrmask = condattr(bm, colormasks);                      \
+                    Begin_Attr(attrmask);                                     \
+                    if ((coloridx = condcolor(bm, colormasks)) != NO_COLOR)   \
+                        term_start_color(coloridx);                           \
+               }                                                             \
+                putstr(WIN_STATUS, 0, txt);                                   \
+                if (iflags.hilite_delta) {                                    \
+                    if (coloridx != NO_COLOR)                                 \
+                        term_end_color();                                     \
+                    End_Attr(attrmask);                                       \
+               }                                                             \
+            }
+#else
+#define MaybeDisplayCond(bm,txt) \
+            if (tty_condition_bits & (bm)) {                                  \
+                putstr(WIN_STATUS, 0, " ");                                   \
+                if (iflags.hilite_delta) {                                    \
+                    attrmask = condattr(bm, colormasks);                      \
+                    Begin_Attr(attrmask);                                     \
+               }                                                             \
+                putstr(WIN_STATUS, 0, txt);                                   \
+                if (iflags.hilite_delta) {                                    \
+                    End_Attr(attrmask);                                       \
+               }                                                             \
+            }
+#endif
+
 void
-tty_status_update(fldidx, ptr, chg, percent)
-int fldidx, chg, percent;
+tty_status_update(fldidx, ptr, chg, percent, color, colormasks)
+int fldidx, chg UNUSED, percent UNUSED, color;
 genericptr_t ptr;
+unsigned long *colormasks;
 {
-    long cond, *condptr = (long *) ptr;
-    register int i;
+    long *condptr = (long *) ptr;
+    int i, attrmask = 0;
+#ifdef TEXTCOLOR
+    int coloridx = NO_COLOR;
+#endif
     char *text = (char *) ptr;
-    /* Mapping BL attributes to tty attributes
-     * BL_HILITE_NONE     -1 + 3 = 2 (statusattr[2])
-     * BL_HILITE_INVERSE  -2 + 3 = 1 (statusattr[1])
-     * BL_HILITE_BOLD     -3 + 3 = 0 (statusattr[0])
-     */
-    long value = -1L;
-    static boolean beenhere = FALSE;
+    static boolean oncearound = FALSE; /* prevent premature partial status display */
     enum statusfields fieldorder[2][15] = {
         { BL_TITLE, BL_STR, BL_DX, BL_CO, BL_IN, BL_WI, BL_CH, BL_ALIGN,
           BL_SCORE, BL_FLUSH, BL_FLUSH, BL_FLUSH, BL_FLUSH, BL_FLUSH,
@@ -3514,175 +3581,118 @@ genericptr_t ptr;
           BL_AC, BL_XP, BL_EXP, BL_HD, BL_TIME, BL_HUNGER,
           BL_CAP, BL_CONDITION, BL_FLUSH }
     };
-#ifdef STATUS_HILITES
-    static int statusattr[] = { ATR_BOLD, ATR_INVERSE, ATR_NONE };
     int attridx = 0;
-#else
-    nhUse(chg);
-    nhUse(percent);
-#endif
 
     if (fldidx != BL_FLUSH) {
         if (!status_activefields[fldidx])
             return;
         switch (fldidx) {
         case BL_CONDITION:
-            cond = *condptr;
-            *status_vals[fldidx] = '\0';
-            if (cond & BL_MASK_STONE)
-                Strcat(status_vals[fldidx], " Stone");
-            if (cond & BL_MASK_SLIME)
-                Strcat(status_vals[fldidx], " Slime");
-            if (cond & BL_MASK_STRNGL)
-                Strcat(status_vals[fldidx], " Strngl");
-            if (cond & BL_MASK_FOODPOIS)
-                Strcat(status_vals[fldidx], " FoodPois");
-            if (cond & BL_MASK_TERMILL)
-                Strcat(status_vals[fldidx], " TermIll");
-            if (cond & BL_MASK_BLIND)
-                Strcat(status_vals[fldidx], " Blind");
-            if (cond & BL_MASK_DEAF)
-                Strcat(status_vals[fldidx], " Deaf");
-            if (cond & BL_MASK_STUN)
-                Strcat(status_vals[fldidx], " Stun");
-            if (cond & BL_MASK_CONF)
-                Strcat(status_vals[fldidx], " Conf");
-            if (cond & BL_MASK_HALLU)
-                Strcat(status_vals[fldidx], " Hallu");
-            if (cond & BL_MASK_LEV)
-                Strcat(status_vals[fldidx], " Lev");
-            if (cond & BL_MASK_FLY)
-                Strcat(status_vals[fldidx], " Fly");
-            if (cond & BL_MASK_RIDE)
-                Strcat(status_vals[fldidx], " Ride");
-            value = cond;
+            tty_condition_bits = *condptr;
+            oncearound = TRUE;
             break;
         default:
-            value = atol(text);
             Sprintf(status_vals[fldidx],
+                    (fldidx == BL_TITLE && iflags.wc2_hitpointbar) ? "%-30s" :
                     status_fieldfmt[fldidx] ? status_fieldfmt[fldidx] : "%s",
                     text);
-            break;
-        }
-
-#ifdef STATUS_HILITES
-        switch (tty_status_hilites[fldidx].behavior) {
-        case BL_TH_NONE:
+#ifdef TEXTCOLOR
+            tty_status_colors[fldidx] = color;
+#else
             tty_status_colors[fldidx] = NO_COLOR;
-            break;
-        case BL_TH_UPDOWN:
-            if (chg > 0)
-                tty_status_colors[fldidx] = tty_status_hilites[fldidx].over;
-            else if (chg < 0)
-                tty_status_colors[fldidx] = tty_status_hilites[fldidx].under;
-            else
-                tty_status_colors[fldidx] = NO_COLOR;
-            break;
-        case BL_TH_VAL_PERCENTAGE:  {
-            int pct_th = 0;
-
-            if (tty_status_hilites[fldidx].thresholdtype != ANY_INT) {
-                impossible(
-                "tty_status_update: unsupported percentage threshold type %d",
-                           tty_status_hilites[fldidx].thresholdtype);
-            } else {
-                pct_th = tty_status_hilites[fldidx].threshold.a_int;
-                tty_status_colors[fldidx] = (percent >= pct_th)
-                                           ? tty_status_hilites[fldidx].over
-                                           : tty_status_hilites[fldidx].under;
+#endif
+            if (iflags.wc2_hitpointbar && fldidx == BL_HP) {
+                hpbar_percent = percent;
+#ifdef TEXTCOLOR
+                hpbar_color = color;
+#else
+                hpbar_color = NO_COLOR;
+#endif
             }
             break;
         }
-        case BL_TH_VAL_ABSOLUTE: {
-            int c = NO_COLOR;
-            int o = tty_status_hilites[fldidx].over;
-            int u = tty_status_hilites[fldidx].under;
-            anything *t = &tty_status_hilites[fldidx].threshold;
-
-            switch (tty_status_hilites[fldidx].thresholdtype) {
-            case ANY_LONG:
-                c = (value >= t->a_long) ? o : u;
-                break;
-            case ANY_INT:
-                c = (value >= t->a_int) ? o : u;
-                break;
-            case ANY_UINT:
-                c = ((unsigned long) value >= t->a_uint) ? o : u;
-                break;
-            case ANY_ULONG:
-                c = ((unsigned long) value >= t->a_ulong) ? o : u;
-                break;
-            case ANY_MASK32:
-                c = (value & t->a_ulong) ? o : u;
-                break;
-            default:
-                impossible(
-                "tty_status_update: unsupported absolute threshold type %d\n",
-                           tty_status_hilites[fldidx].thresholdtype);
-                break;
-            }
-            tty_status_colors[fldidx] = c;
-            break;
-        } /* case */
-        } /* switch */
-#endif /* STATUS_HILITES */
     }
 
-    /* For now, this version copied from the genl_ version currently
-     * updates everything on the display, everytime
-     */
-
-    if (!beenhere || !iflags.use_status_hilites) {
-        char newbot1[MAXCO], newbot2[MAXCO];
-
-        newbot1[0] = '\0';
-        for (i = 0; fieldorder[0][i] >= 0; ++i) {
-            int idx1 = fieldorder[0][i];
-
-            if (status_activefields[idx1])
-                Strcat(newbot1, status_vals[idx1]);
-        }
-        newbot2[0] = '\0';
-        for (i = 0; fieldorder[1][i] >= 0; ++i) {
-            int idx2 = fieldorder[1][i];
-
-            if (status_activefields[idx2])
-                Strcat(newbot2, status_vals[idx2]);
-        }
-
-        curs(WIN_STATUS, 1, 0);
-        putstr(WIN_STATUS, 0, newbot1);
-        curs(WIN_STATUS, 1, 1);
-        putmixed(WIN_STATUS, 0, newbot2); /* putmixed() due to GOLD glyph */
-        beenhere = TRUE;
-        return;
-    }
+    if (!oncearound) return;
 
     curs(WIN_STATUS, 1, 0);
     for (i = 0; fieldorder[0][i] != BL_FLUSH; ++i) {
         int fldidx1 = fieldorder[0][i];
-
         if (status_activefields[fldidx1]) {
-#ifdef STATUS_HILITES
-            if (tty_status_colors[fldidx1] < 0
-                && tty_status_colors[fldidx1] >= -3) {
-                /* attribute, not a color */
-                attridx = tty_status_colors[fldidx1] + 3;
-                term_start_attr(statusattr[attridx]);
-                putstr(WIN_STATUS, 0, status_vals[fldidx1]);
-                term_end_attr(statusattr[attridx]);
-            } else
+            if (fldidx1 != BL_TITLE || !iflags.wc2_hitpointbar) {
 #ifdef TEXTCOLOR
-            if (tty_status_colors[fldidx1] != CLR_MAX) {
-                if (tty_status_colors[fldidx1] != NO_COLOR)
-                    term_start_color(tty_status_colors[fldidx1]);
-                putstr(WIN_STATUS, 0, status_vals[fldidx1]);
-                if (tty_status_colors[fldidx1] != NO_COLOR)
-                    term_end_color();
-            } else
+                coloridx = tty_status_colors[fldidx1] & 0x00FF;
+#endif
+                attridx = (tty_status_colors[fldidx1] & 0xFF00) >> 8;
+                text = status_vals[fldidx1];
+                if (iflags.hilite_delta) {
+                    if (*text == ' ') {
+                        putstr(WIN_STATUS, 0, " ");
+                        text++;
+                    }
+                    /* multiple attributes can be in effect concurrently */
+                    Begin_Attr(attridx);
+#ifdef TEXTCOLOR
+                    if (coloridx != NO_COLOR && coloridx != CLR_MAX)
+                       term_start_color(coloridx);
 #endif
-#endif /* STATUS_HILITES */
-            putstr(WIN_STATUS, 0, status_vals[fldidx1]);
+               }
+
+                putstr(WIN_STATUS, 0, text);
+
+                if (iflags.hilite_delta) {
+#ifdef TEXTCOLOR
+                    if (coloridx != NO_COLOR)
+                       term_end_color();
+#endif
+                    End_Attr(attridx);
+                }
+            } else {
+                /* hitpointbar using hp percent calculation */
+                int bar_pos, bar_len;
+                char *bar2 = (char *)0;
+                char bar[MAXCO], savedch;
+                boolean twoparts = FALSE;
+
+                text = status_vals[fldidx1];
+                bar_len = strlen(text);
+                if (bar_len < MAXCO-1) {
+                    Strcpy(bar, text);
+                    bar_pos = (bar_len * hpbar_percent) / 100;
+                    if (bar_pos < 1 && hpbar_percent > 0)
+                        bar_pos = 1;
+                    if (bar_pos >= bar_len && hpbar_percent < 100)
+                        bar_pos = bar_len - 1;
+                    if (bar_pos > 0 && bar_pos < bar_len) {
+                        twoparts = TRUE;
+                        bar2 = &bar[bar_pos];
+                        savedch = *bar2;
+                        *bar2 = '\0';
+                    }
+               }
+                if (iflags.hilite_delta && iflags.wc2_hitpointbar) {
+                    putstr(WIN_STATUS, 0, "[");
+#ifdef TEXTCOLOR
+                    coloridx = hpbar_color & 0x00FF;
+                    /* attridx = (hpbar_color & 0xFF00) >> 8; */
+                    if (coloridx != NO_COLOR)
+                        term_start_color(coloridx);
+#endif
+                    term_start_attr(ATR_INVERSE);
+                    putstr(WIN_STATUS, 0, bar);
+                    term_end_attr(ATR_INVERSE);
+#ifdef TEXTCOLOR
+                    if (coloridx != NO_COLOR)
+                        term_end_color();
+#endif
+                    if (twoparts) {
+                        *bar2 = savedch;
+                        putstr(WIN_STATUS, 0, bar2);
+                    }
+                    putstr(WIN_STATUS, 0, "]");
+                } else
+                    putstr(WIN_STATUS, 0, text);
+            }
         }
     }
     curs(WIN_STATUS, 1, 1);
@@ -3690,93 +3700,115 @@ genericptr_t ptr;
         int fldidx2 = fieldorder[1][i];
 
         if (status_activefields[fldidx2]) {
-#ifdef STATUS_HILITES
-            if (tty_status_colors[fldidx2] < 0
-                && tty_status_colors[fldidx2] >= -3) {
-                /* attribute, not a color */
-                attridx = tty_status_colors[fldidx2] + 3;
-                term_start_attr(statusattr[attridx]);
-                putstr(WIN_STATUS, 0, status_vals[fldidx2]);
-                term_end_attr(statusattr[attridx]);
-            } else
+            if (fldidx2 != BL_CONDITION) {
+#ifdef TEXTCOLOR
+                coloridx = tty_status_colors[fldidx2] & 0x00FF;
+#endif
+                attridx = (tty_status_colors[fldidx2] & 0xFF00) >> 8;
+                text = status_vals[fldidx2];
+                if (iflags.hilite_delta) {
+                    if (*text == ' ') {
+                        putstr(WIN_STATUS, 0, " ");
+                        text++;
+                    }
+                    /* multiple attributes can be in effect concurrently */
+                    Begin_Attr(attridx);
 #ifdef TEXTCOLOR
-            if (tty_status_colors[fldidx2] != CLR_MAX) {
-                if (tty_status_colors[fldidx2] != NO_COLOR)
-                    term_start_color(tty_status_colors[fldidx2]);
+                    if (coloridx != NO_COLOR && coloridx != CLR_MAX)
+                        term_start_color(coloridx);
+#endif
+               }
+
                 if (fldidx2 == BL_GOLD) {
                     /* putmixed() due to GOLD glyph */
-                    putmixed(WIN_STATUS, 0, status_vals[fldidx2]);
+                    putmixed(WIN_STATUS, 0, text);
                 } else {
-                    putstr(WIN_STATUS, 0, status_vals[fldidx2]);
+                    putstr(WIN_STATUS, 0, text);
                 }
-                if (tty_status_colors[fldidx2] != NO_COLOR)
-                    term_end_color();
-            } else
+
+                if (iflags.hilite_delta) {
+#ifdef TEXTCOLOR
+                           if (coloridx != NO_COLOR)
+                        term_end_color();
 #endif
-#endif /* STATUS_HILITES */
-            putstr(WIN_STATUS, 0, status_vals[fldidx2]);
+                    End_Attr(attridx);
+                }
+            } else {
+                MaybeDisplayCond(BL_MASK_STONE, "Stone");
+                MaybeDisplayCond(BL_MASK_SLIME, "Slime");
+                MaybeDisplayCond(BL_MASK_STRNGL, "Strngl");
+                MaybeDisplayCond(BL_MASK_FOODPOIS, "FoodPois");
+                MaybeDisplayCond(BL_MASK_TERMILL, "TermIll");
+                MaybeDisplayCond(BL_MASK_BLIND, "Blind");
+                MaybeDisplayCond(BL_MASK_DEAF, "Deaf");
+                MaybeDisplayCond(BL_MASK_STUN, "Stun");
+                MaybeDisplayCond(BL_MASK_CONF, "Conf");
+                MaybeDisplayCond(BL_MASK_HALLU, "Hallu");
+                MaybeDisplayCond(BL_MASK_LEV, "Lev");
+                MaybeDisplayCond(BL_MASK_FLY, "Fly");
+                MaybeDisplayCond(BL_MASK_RIDE, "Ride");
+           }
         }
     }
     return;
 }
 
-#ifdef STATUS_HILITES
+#ifdef TEXTCOLOR
 /*
- *  status_threshold(int fldidx, int threshholdtype, anything threshold,
- *                   int behavior, int under, int over)
- *
- *        -- called when a hiliting preference is added, changed, or
- *           removed.
- *        -- the fldindex identifies which field is having its hiliting
- *           preference set. It is an integer index value from botl.h
- *        -- fldindex could be any one of the following from botl.h:
- *           BL_TITLE, BL_STR, BL_DX, BL_CO, BL_IN, BL_WI, BL_CH,
- *           BL_ALIGN, BL_SCORE, BL_CAP, BL_GOLD, BL_ENE, BL_ENEMAX,
- *           BL_XP, BL_AC, BL_HD, BL_TIME, BL_HUNGER, BL_HP, BL_HPMAX,
- *           BL_LEVELDESC, BL_EXP, BL_CONDITION
- *        -- datatype is P_INT, P_UINT, P_LONG, or P_MASK.
- *        -- threshold is an "anything" union which can contain the
- *           datatype value.
- *        -- behavior is used to define how threshold is used and can
- *           be BL_TH_NONE, BL_TH_VAL_PERCENTAGE, BL_TH_VAL_ABSOLUTE,
- *           or BL_TH_UPDOWN. BL_TH_NONE means don't do anything above
- *           or below the threshold.  BL_TH_VAL_PERCENTAGE treats the
- *           threshold value as a precentage of the maximum possible
- *           value. BL_TH_VAL_ABSOLUTE means that the threshold is an
- *           actual value. BL_TH_UPDOWN means that threshold is not
- *           used, and the two below/above hilite values indicate how
- *           to display something going down (under) or rising (over).
- *        -- under is the hilite attribute used if value is below the
- *           threshold. The attribute can be BL_HILITE_NONE,
- *           BL_HILITE_INVERSE, BL_HILITE_BOLD (-1, -2, or -3), or one
- *           of the color indexes of CLR_BLACK, CLR_RED, CLR_GREEN,
- *           CLR_BROWN, CLR_BLUE, CLR_MAGENTA, CLR_CYAN, CLR_GRAY,
- *           CLR_ORANGE, CLR_BRIGHT_GREEN, CLR_YELLOW, CLR_BRIGHT_BLUE,
- *           CLR_BRIGHT_MAGENTA, CLR_BRIGHT_CYAN, or CLR_WHITE (0 - 15).
- *        -- over is the hilite attribute used if value is at or above
- *           the threshold. The attribute can be BL_HILITE_NONE,
- *           BL_HILITE_INVERSE, BL_HILITE_BOLD (-1, -2, or -3), or one
- *           of the color indexes of CLR_BLACK, CLR_RED, CLR_GREEN,
- *           CLR_BROWN, CLR_BLUE, CLR_MAGENTA, CLR_CYAN, CLR_GRAY,
- *           CLR_ORANGE, CLR_BRIGHT_GREEN, CLR_YELLOW, CLR_BRIGHT_BLUE,
- *           CLR_BRIGHT_MAGENTA, CLR_BRIGHT_CYAN, or CLR_WHITE (0 - 15).
+ * Return what color this condition should
+ * be displayed in based on user settings.
  */
-void
-tty_status_threshold(fldidx, thresholdtype, threshold, behavior, under, over)
-int fldidx, thresholdtype;
-int behavior, under, over;
-anything threshold;
+int condcolor(bm, bmarray)
+long bm;
+unsigned long *bmarray;
 {
-    tty_status_hilites[fldidx].thresholdtype = thresholdtype;
-    tty_status_hilites[fldidx].threshold = threshold;
-    tty_status_hilites[fldidx].behavior = behavior;
-    tty_status_hilites[fldidx].under = under;
-    tty_status_hilites[fldidx].over = over;
-    return;
+#ifdef STATUS_HILITES
+    int i;
+
+    if (bm && bmarray)
+        for (i = 0; i < CLR_MAX; ++i) {
+            if (bmarray[i] && (bm & bmarray[i]))
+                return i;
+        }
+#endif
+    return NO_COLOR;
 }
+#endif /* TEXTCOLOR */
 
+int condattr(bm, bmarray)
+long bm;
+unsigned long *bmarray;
+{
+    int attr = 0;
+    int i;
+
+    if (bm && bmarray) {
+        for (i = HL_ATTCLR_DIM; i < BL_ATTCLR_MAX; ++i) {
+            if (bmarray[i] && (bm & bmarray[i])) {
+                switch(i) {
+                    case HL_ATTCLR_DIM:
+                        attr |= HL_DIM;
+                        break;
+                    case HL_ATTCLR_BLINK:
+                        attr |= HL_BLINK;
+                        break;
+                    case HL_ATTCLR_ULINE:
+                        attr |= HL_ULINE;
+                        break;
+                    case HL_ATTCLR_INVERSE:
+                        attr |= HL_INVERSE;
+                        break;
+                    case HL_ATTCLR_BOLD:
+                        attr |= HL_BOLD;
+                        break;
+                }
+            }
+        }
+    }
+    return attr;
+}
 #endif /* STATUS_HILITES */
-#endif /*STATUS_VIA_WINDOWPORT*/
+
 
 #endif /* TTY_GRAPHICS */
 
index 926f7d0eb37979f34b1bfc70dae6d40732bed2a4..090068d8261f74e5b119c280c004a6adc8bf1648 100644 (file)
@@ -72,6 +72,7 @@ typedef struct mswin_nhmsg_update_status {
     int n_fields;
     const char **vals;
     boolean *activefields;
+    int *percents;
     int *colors;
 } MSNHMsgUpdateStatus, *PMSNHMsgUpdateStatus;
 
index fce51f2685c7e8ce27ff8e3de598c7ebe95d1dc0..5e522b7b14986a0243d089f36d304dd047bba3f2 100644 (file)
@@ -18,10 +18,10 @@ typedef struct mswin_nethack_status_window {
     int n_fields;
     const char **vals;
     boolean *activefields;
+    int *percents;
     int *colors;
 } NHStatusWindow, *PNHStatusWindow;
 
-#ifdef STATUS_VIA_WINDOWPORT
 static int fieldorder1[] = { BL_TITLE, BL_STR, BL_DX,    BL_CO,    BL_IN,
                              BL_WI,    BL_CH,  BL_ALIGN, BL_SCORE, -1 };
 static int fieldorder2[] = { BL_LEVELDESC, BL_GOLD,      BL_HP,   BL_HPMAX,
@@ -29,7 +29,6 @@ static int fieldorder2[] = { BL_LEVELDESC, BL_GOLD,      BL_HP,   BL_HPMAX,
                              BL_EXP,       BL_HD,        BL_TIME, BL_HUNGER,
                              BL_CAP,       BL_CONDITION, -1 };
 static int *fieldorders[] = { fieldorder1, fieldorder2, NULL };
-#endif /*  STATUS_VIA_WINDOWPORT */
 
 static TCHAR szStatusWindowClass[] = TEXT("MSNHStatusWndClass");
 LRESULT CALLBACK StatusWndProc(HWND, UINT, WPARAM, LPARAM);
@@ -133,9 +132,10 @@ StatusWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 
         case MSNH_MSG_GETTEXT: {
             PMSNHMsgGetText msg_data = (PMSNHMsgGetText) lParam;
-#ifdef STATUS_VIA_WINDOWPORT
+#ifdef STATUS_HILITES
             int **fop;
             int *f;
+
             msg_data->buffer[0] = '\0';
             if (data->n_fields > 0) {
                 for (fop = fieldorders; *fop; fop++) {
@@ -143,20 +143,20 @@ StatusWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
                         if (data->activefields[*f])
                             strncat(msg_data->buffer, data->vals[*f],
                                     msg_data->max_size
-                                        - strlen(msg_data->buffer));
+                                    - strlen(msg_data->buffer));
                     }
                     strncat(msg_data->buffer, "\r\n",
                             msg_data->max_size - strlen(msg_data->buffer));
                 }
             }
-#else  /*  STATUS_VIA_WINDOWPORT */
+#else
             strncpy(msg_data->buffer, data->window_text[0],
                     msg_data->max_size);
             strncat(msg_data->buffer, "\r\n",
                     msg_data->max_size - strlen(msg_data->buffer));
             strncat(msg_data->buffer, data->window_text[1],
                     msg_data->max_size - strlen(msg_data->buffer));
-#endif /*  STATUS_VIA_WINDOWPORT */
+#endif
         } break;
 
         case MSNH_MSG_UPDATE_STATUS: {
@@ -164,6 +164,7 @@ StatusWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
             data->n_fields = msg_data->n_fields;
             data->vals = msg_data->vals;
             data->activefields = msg_data->activefields;
+            data->percents = msg_data->percents;
             data->colors = msg_data->colors;
             InvalidateRect(hWnd, NULL, TRUE);
         } break;
@@ -206,10 +207,12 @@ StatusWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
     return 0;
 }
 
-#ifdef STATUS_VIA_WINDOWPORT
+#ifdef STATUS_HILITES
 static LRESULT
 onWMPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
 {
+    int hpbar_percent = 100;
+    int hpbar_color = NO_COLOR;
     int *f;
     int **fop;
     SIZE sz;
@@ -238,46 +241,84 @@ onWMPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
                          : (COLORREF) GetSysColor(DEFAULT_COLOR_FG_STATUS);
     OldFg = SetTextColor(hdc, Fg);
 
+    if (iflags.wc2_hitpointbar && BL_HP < data->n_fields
+        && data->activefields[BL_HP]) {
+        hpbar_percent = data->percents[BL_HP];
+        hpbar_color = data->colors[BL_HP] & 0x00ff;
+    }
+
     for (fop = fieldorders; *fop; fop++) {
         LONG left = rt.left;
         LONG cy = 0;
         int vlen;
         for (f = *fop; *f != -1; f++) {
+            int clr, atr;
+            int fntatr = ATR_NONE;
+            HGDIOBJ fnt;
+            COLORREF nFg, nBg;
+
             if (((*f) >= data->n_fields) || (!data->activefields[*f]))
                 continue;
+            clr = data->colors[*f] & 0x00ff;
+            atr = (data->colors[*f] & 0xff00) >> 8;
             vlen = strlen(data->vals[*f]);
             NH_A2W(data->vals[*f], wbuf, SIZE(wbuf));
 
-            if (!iflags.use_status_hilites) {
-                SelectObject(hdc, normalFont);
-                SetBkColor(hdc, Bg);
-                SetTextColor(hdc, Fg);
-            } else if (data->colors[*f] == CLR_MAX
-                || data->colors[*f] == BL_HILITE_NONE) {
-                SelectObject(hdc, normalFont);
-                SetBkColor(hdc, Bg);
-                SetTextColor(hdc, Fg);
-            } else if (data->colors[*f] > 0) {
-                SelectObject(hdc, normalFont);
-                SetBkColor(hdc, Bg);
-                SetTextColor(hdc, nhcolor_to_RGB(data->colors[*f]));
-            } else if (data->colors[*f] == BL_HILITE_INVERSE) {
-                SelectObject(hdc, normalFont);
-                SetBkColor(hdc, Fg);
-                SetTextColor(hdc, Bg);
-            } else if (data->colors[*f] == BL_HILITE_BOLD) {
-                SelectObject(hdc, boldFont);
+            if (atr & HL_BOLD)
+                fntatr = ATR_BOLD;
+            else if (atr & HL_INVERSE)
+                fntatr = ATR_INVERSE;
+            else if (atr & HL_ULINE)
+                fntatr = ATR_ULINE;
+            else if (atr & HL_BLINK)
+                fntatr = ATR_BLINK;
+            else if (atr & HL_DIM)
+                fntatr = ATR_DIM;
+            fnt = mswin_get_font(NHW_STATUS, fntatr, hdc, FALSE);
+            nFg = (clr >= 0 && clr < CLR_MAX) ? nhcolor_to_RGB(clr) : Fg;
+            nBg = Bg;
+
+            GetTextExtentPoint32(hdc, wbuf, vlen, &sz);
+            if (*f == BL_TITLE && iflags.wc2_hitpointbar) {
+                HBRUSH back_brush = CreateSolidBrush(nhcolor_to_RGB(hpbar_color));
+                RECT barrect;
+
+                /* first draw title normally */
+                SelectObject(hdc, fnt);
+                SetBkMode(hdc, OPAQUE);
                 SetBkColor(hdc, Bg);
-                SetTextColor(hdc, Fg);
+                SetTextColor(hdc, nhcolor_to_RGB(hpbar_color));
+                DrawText(hdc, wbuf, vlen, &rt, DT_LEFT);
+
+                /* calc bar length */
+                barrect.left = rt.left;
+                barrect.top = rt.top;
+                barrect.bottom = sz.cy;
+                if (hpbar_percent > 0)
+                    barrect.right = (int)((hpbar_percent * sz.cx) / 100);
+                else
+                    barrect.right = sz.cx;
+
+                /* then draw hpbar on top of title */
+                FillRect(hdc, &barrect, back_brush);
+                SetBkMode(hdc, TRANSPARENT);
+                SetTextColor(hdc, nBg);
+                DrawText(hdc, wbuf, vlen, &barrect, DT_LEFT);
+
+                DeleteObject(back_brush);
             } else {
-                SelectObject(hdc, normalFont);
-                SetBkColor(hdc, Bg);
-                SetTextColor(hdc, Fg);
+                if (atr & HL_INVERSE) {
+                    COLORREF tmp = nFg;
+                    nFg = nBg;
+                    nBg = tmp;
+                }
+                SelectObject(hdc, fnt);
+                SetBkMode(hdc, OPAQUE);
+                SetBkColor(hdc, nBg);
+                SetTextColor(hdc, nFg);
+                DrawText(hdc, wbuf, vlen, &rt, DT_LEFT);
             }
 
-            GetTextExtentPoint32(hdc, wbuf, vlen, &sz);
-            DrawText(hdc, wbuf, vlen, &rt, DT_LEFT);
-
             rt.left += sz.cx;
             cy = max(cy, sz.cy);
         }
@@ -336,7 +377,7 @@ onWMPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
 
     return 0;
 }
-#endif /*STATUS_VIA_WINDOWPORT*/
+#endif /* !STATUS_HILITES */
 
 void
 mswin_status_window_size(HWND hWnd, LPSIZE sz)
index 7b80cfbc62ef7ccb9368524bfa7aa277b63d4e32..db045a4ccef342ecb24dba0152bdc8432c27b9df 100644 (file)
@@ -85,6 +85,9 @@ struct window_procs mswin_procs = {
         | WC_FONTSIZ_TEXT | WC_TILE_WIDTH | WC_TILE_HEIGHT | WC_TILE_FILE
         | WC_VARY_MSGCOUNT | WC_WINDOWCOLORS | WC_PLAYER_SELECTION
         | WC_SPLASH_SCREEN | WC_POPUP_DIALOG | WC_MOUSE_SUPPORT,
+#ifdef STATUS_HILITES
+    WC2_HITPOINTBAR | WC2_FLUSH_STATUS |
+#endif
     0L, mswin_init_nhwindows, mswin_player_selection, mswin_askname,
     mswin_get_nh_event, mswin_exit_nhwindows, mswin_suspend_nhwindows,
     mswin_resume_nhwindows, mswin_create_nhwindow, mswin_clear_nhwindow,
@@ -108,13 +111,8 @@ struct window_procs mswin_procs = {
     /* other defs that really should go away (they're tty specific) */
     mswin_start_screen, mswin_end_screen, mswin_outrip,
     mswin_preference_update, mswin_getmsghistory, mswin_putmsghistory,
-#ifdef STATUS_VIA_WINDOWPORT
     mswin_status_init, mswin_status_finish, mswin_status_enablefield,
     mswin_status_update,
-#ifdef STATUS_HILITES
-    mswin_status_threshold,
-#endif
-#endif
     genl_can_suspend_yes,
 };
 
@@ -2713,18 +2711,18 @@ NHMessageBox(HWND hWnd, LPCTSTR text, UINT type)
     return MessageBox(hWnd, text, title, type);
 }
 
-#ifdef STATUS_VIA_WINDOWPORT
 static const char *_status_fieldnm[MAXBLSTATS];
 static const char *_status_fieldfmt[MAXBLSTATS];
 static char *_status_vals[MAXBLSTATS];
 static int _status_colors[MAXBLSTATS];
+static int _status_percents[MAXBLSTATS];
 static boolean _status_activefields[MAXBLSTATS];
 extern winid WIN_STATUS;
 
 #ifdef STATUS_HILITES
 typedef struct hilite_data_struct {
     int thresholdtype;
-    anything threshold;
+    anything value;
     int behavior;
     int under;
     int over;
@@ -2747,6 +2745,7 @@ mswin_status_init(void)
         _status_activefields[i] = FALSE;
         _status_fieldfmt[i] = (const char *) 0;
         _status_colors[i] = CLR_MAX; /* no color */
+        _status_percents[i] = 0;
 #ifdef STATUS_HILITES
         _status_hilites[i].thresholdtype = 0;
         _status_hilites[i].behavior = BL_TH_NONE;
@@ -2804,64 +2803,9 @@ mswin_status_enablefield(int fieldidx, const char *nm, const char *fmt,
     _status_activefields[fieldidx] = enable;
 }
 
-#ifdef STATUS_HILITES
-/*
-status_threshold(int fldidx, int threshholdtype, anything threshold,
-                                        int behavior, int under, int over)
-                -- called when a hiliting preference is added, changed, or
-                   removed.
-                -- the fldindex identifies which field is having its hiliting
-                   preference set. It is an integer index value from botl.h
-                -- fldindex could be any one of the following from botl.h:
-                   BL_TITLE, BL_STR, BL_DX, BL_CO, BL_IN, BL_WI, BL_CH,
-                   BL_ALIGN, BL_SCORE, BL_CAP, BL_GOLD, BL_ENE, BL_ENEMAX,
-                   BL_XP, BL_AC, BL_HD, BL_TIME, BL_HUNGER, BL_HP, BL_HPMAX,
-                   BL_LEVELDESC, BL_EXP, BL_CONDITION
-                -- datatype is P_INT, P_UINT, P_LONG, or P_MASK.
-                -- threshold is an "anything" union which can contain the
-                   datatype value.
-                -- behavior is used to define how threshold is used and can
-                   be BL_TH_NONE, BL_TH_VAL_PERCENTAGE, BL_TH_VAL_ABSOLUTE,
-                   or BL_TH_UPDOWN. BL_TH_NONE means don't do anything above
-                   or below the threshold.  BL_TH_VAL_PERCENTAGE treats the
-                   threshold value as a precentage of the maximum possible
-                   value. BL_TH_VAL_ABSOLUTE means that the threshold is an
-                   actual value. BL_TH_UPDOWN means that threshold is not
-                   used, and the two below/above hilite values indicate how
-                   to display something going down (under) or rising (over).
-                -- under is the hilite attribute used if value is below the
-                   threshold. The attribute can be BL_HILITE_NONE,
-                   BL_HILITE_INVERSE, BL_HILITE_BOLD (-1, -2, or -3), or one
-                   of the color indexes of CLR_BLACK, CLR_RED, CLR_GREEN,
-                   CLR_BROWN, CLR_BLUE, CLR_MAGENTA, CLR_CYAN, CLR_GRAY,
-                   CLR_ORANGE, CLR_BRIGHT_GREEN, CLR_YELLOW, CLR_BRIGHT_BLUE,
-                   CLR_BRIGHT_MAGENTA, CLR_BRIGHT_CYAN, or CLR_WHITE (0 - 15).
-                -- over is the hilite attribute used if value is at or above
-                   the threshold. The attribute can be BL_HILITE_NONE,
-                   BL_HILITE_INVERSE, BL_HILITE_BOLD (-1, -2, or -3), or one
-                   of the color indexes of CLR_BLACK, CLR_RED, CLR_GREEN,
-                   CLR_BROWN, CLR_BLUE, CLR_MAGENTA, CLR_CYAN, CLR_GRAY,
-                   CLR_ORANGE, CLR_BRIGHT_GREEN, CLR_YELLOW, CLR_BRIGHT_BLUE,
-                   CLR_BRIGHT_MAGENTA, CLR_BRIGHT_CYAN, or CLR_WHITE (0 - 15).
-*/
-void
-mswin_status_threshold(int fldidx, int thresholdtype, anything threshold,
-                       int behavior, int under, int over)
-{
-    logDebug("mswin_status_threshold(%d, %d, %d, %d, %d)\n", fldidx,
-             thresholdtype, behavior, under, over);
-    assert(fldidx >= 0 && fldidx < MAXBLSTATS);
-    _status_hilites[fldidx].thresholdtype = thresholdtype;
-    _status_hilites[fldidx].threshold = threshold;
-    _status_hilites[fldidx].behavior = behavior;
-    _status_hilites[fldidx].under = under;
-    _status_hilites[fldidx].over = over;
-}
-#endif /* STATUS_HILITES */
-
 /*
 
-status_update(int fldindex, genericptr_t ptr, int chg, int percentage)
+status_update(int fldindex, genericptr_t ptr, int chg, int percent, int color, unsigned long *colormasks)
                 -- update the value of a status field.
                 -- the fldindex identifies which field is changing and
                    is an integer index value from botl.h
@@ -2894,9 +2838,13 @@ status_update(int fldindex, genericptr_t ptr, int chg, int percentage)
                    symbol for GOLD "\GXXXXNNNN:nnn". If window port needs
                    textual gold amount without the leading "$:" the port will
                    have to skip past ':' in passed "ptr" for the BL_GOLD case.
+                -- color is the color that the NetHack core is telling you to
+                   use to display the text.
+                -- colormasks is a pointer to a set of CLR_MAX unsigned longs
+                   telling you which fields should be displayed in each color.
 */
 void
-mswin_status_update(int idx, genericptr_t ptr, int chg, int percent)
+mswin_status_update(int idx, genericptr_t ptr, int chg, int percent, int color, unsigned long *colormasks)
 {
     long cond, *condptr = (long *) ptr;
     char *text = (char *) ptr;
@@ -2905,11 +2853,12 @@ mswin_status_update(int idx, genericptr_t ptr, int chg, int percent)
     unsigned ospecial;
     long value = -1;
 
-    logDebug("mswin_status_update(%d, %p, %d, %d)\n", idx, ptr, chg, percent);
+    logDebug("mswin_status_update(%d, %p, %d, %d, %x, %p)\n", idx, ptr, chg, percent, color, colormasks);
 
     if (idx != BL_FLUSH) {
         if (!_status_activefields[idx])
             return;
+        _status_percents[idx] = percent;
         switch (idx) {
         case BL_CONDITION: {
             cond = *condptr;
@@ -2971,75 +2920,16 @@ mswin_status_update(int idx, genericptr_t ptr, int chg, int percent)
         }
     }
 
-#ifdef STATUS_HILITES
-    switch (_status_hilites[idx].behavior) {
-    case BL_TH_NONE: {
-        _status_colors[idx] = CLR_MAX;
-    } break;
-
-    case BL_TH_UPDOWN: {
-        if (chg > 0)
-            _status_colors[idx] = _status_hilites[idx].over;
-        else if (chg < 0)
-            _status_colors[idx] = _status_hilites[idx].under;
-        else
-            _status_colors[idx] = CLR_MAX;
-    } break;
-
-    case BL_TH_VAL_PERCENTAGE: {
-        int pct_th = 0;
-        if (_status_hilites[idx].thresholdtype != ANY_INT) {
-            impossible("mswin_status_update: unsupported percentage "
-                       "threshold type %d",
-                       _status_hilites[idx].thresholdtype);
-            break;
-        }
-        pct_th = _status_hilites[idx].threshold.a_int;
-        _status_colors[idx] = (percent >= pct_th)
-                                  ? _status_hilites[idx].over
-                                  : _status_hilites[idx].under;
-    } break;
-
-    case BL_TH_VAL_ABSOLUTE: {
-        int c = CLR_MAX;
-        int o = _status_hilites[idx].over;
-        int u = _status_hilites[idx].under;
-        anything *t = &_status_hilites[idx].threshold;
-        switch (_status_hilites[idx].thresholdtype) {
-        case ANY_LONG:
-            c = (value >= t->a_long) ? o : u;
-            break;
-        case ANY_INT:
-            c = (value >= t->a_int) ? o : u;
-            break;
-        case ANY_UINT:
-            c = ((unsigned long) value >= t->a_uint) ? o : u;
-            break;
-        case ANY_ULONG:
-            c = ((unsigned long) value >= t->a_ulong) ? o : u;
-            break;
-        case ANY_MASK32:
-            c = (value & t->a_ulong) ? o : u;
-            break;
-        default:
-            impossible("mswin_status_update: unsupported absolute threshold "
-                       "type %d\n",
-                       _status_hilites[idx].thresholdtype);
-            break;
-        }
-        _status_colors[idx] = c;
-    } break;
-    }
-#endif /* STATUS_HILITES */
+    _status_colors[idx] = color;
 
     /* send command to status window */
     ZeroMemory(&update_cmd_data, sizeof(update_cmd_data));
     update_cmd_data.n_fields = MAXBLSTATS;
     update_cmd_data.vals = _status_vals;
     update_cmd_data.activefields = _status_activefields;
+    update_cmd_data.percents = _status_percents;
     update_cmd_data.colors = _status_colors;
     SendMessage(mswin_hwnd_from_winid(WIN_STATUS), WM_MSNH_COMMAND,
                 (WPARAM) MSNH_MSG_UPDATE_STATUS, (LPARAM) &update_cmd_data);
 }
 
-#endif /*STATUS_VIA_WINDOWPORT*/
index e34cb006f749b932d51a56940a923acaca2ee0ce..b799da1e7bf27663a72ca80e83ba7d2890915e8a 100644 (file)
@@ -182,18 +182,11 @@ void mswin_preference_update(const char *pref);
 char *mswin_getmsghistory(BOOLEAN_P init);
 void mswin_putmsghistory(const char *msg, BOOLEAN_P);
 
-#ifdef STATUS_VIA_WINDOWPORT
 void mswin_status_init(void);
 void mswin_status_finish(void);
 void mswin_status_enablefield(int fieldidx, const char *nm, const char *fmt,
                               boolean enable);
-void mswin_status_update(int idx, genericptr_t ptr, int chg, int percent);
-
-#ifdef STATUS_HILITES
-void mswin_status_threshold(int fldidx, int thresholdtype, anything threshold,
-                            int behavior, int under, int over);
-#endif /* STATUS_HILITES */
-#endif /*STATUS_VIA_WINDOWPORT*/
+void mswin_status_update(int idx, genericptr_t ptr, int chg, int percent, int color, unsigned long *colormasks);
 
 /* helper function */
 HWND mswin_hwnd_from_winid(winid wid);