]> granicus.if.org Git - nethack/commitdiff
Added support for color condition hilites to tile mode.
authorBart House <bart@barthouse.com>
Mon, 26 Nov 2018 05:04:30 +0000 (21:04 -0800)
committerBart House <bart@barthouse.com>
Mon, 26 Nov 2018 05:04:30 +0000 (21:04 -0800)
Code is complete but might take another pass over the code to simplify
where we can.

include/botl.h
win/win32/mhmsg.h
win/win32/mhstatus.c
win/win32/mhstatus.h
win/win32/mswproc.c

index 9e4e365952cf8acf59f55c5dd36f822065952b4e..f7cbce08f99033d846e980a7edc3f9e3fbcca289 100644 (file)
@@ -35,14 +35,15 @@ enum statusfields {
     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, /* 13..18 */
-    BL_HPMAX, BL_LEVELDESC, BL_EXP, BL_CONDITION /* 19..22 */
+    BL_HPMAX, BL_LEVELDESC, BL_EXP, BL_CONDITION, /* 19..22 */
+    BL_COUNT
 };
 
 enum relationships { NO_LTEQGT = -1,
                      EQ_VALUE, LT_VALUE, LE_VALUE,
                      GE_VALUE, GT_VALUE, TXT_VALUE };
 
-#define MAXBLSTATS      (BL_CONDITION + 1)
+#define MAXBLSTATS      (BL_COUNT)
 
 #define BEFORE  0
 #define NOW     1
@@ -63,6 +64,7 @@ enum relationships { NO_LTEQGT = -1,
 #define BL_MASK_LEV             0x00000400L
 #define BL_MASK_FLY             0x00000800L
 #define BL_MASK_RIDE            0x00001000L
+#define BL_MASK_BITS            13 /* number of mask bits that can be set */
 /* clang-format on */
 
 #define REASSESS_ONLY TRUE
index 090068d8261f74e5b119c280c004a6adc8bf1648..7eb65d0c02e956cf4300988e41847f8401b4ecd2 100644 (file)
@@ -69,11 +69,7 @@ typedef struct mswin_nhmsg_get_text {
 } MSNHMsgGetText, *PMSNHMsgGetText;
 
 typedef struct mswin_nhmsg_update_status {
-    int n_fields;
-    const char **vals;
-    boolean *activefields;
-    int *percents;
-    int *colors;
+    struct mswin_status_lines * status_lines;
 } MSNHMsgUpdateStatus, *PMSNHMsgUpdateStatus;
 
 #endif
index 0747628163a393f14d2de6cf37ec9f241f695412..57c70b4366b2679f967e8af58db7ee154ac7ec7d 100644 (file)
@@ -9,7 +9,6 @@
 #include "mhmsg.h"
 #include "mhfont.h"
 
-#define NHSW_LINES 2
 #define MAXWINDOWTEXT BUFSZ
 
 extern COLORREF nhcolor_to_RGB(int c); /* from mhmap */
@@ -60,24 +59,14 @@ void back_buffer_init(back_buffer_t * back_buffer, HWND hWnd, int width, int hei
     back_buffer_size(back_buffer, width, height);
 }
 
+
 typedef struct mswin_nethack_status_window {
     int index;
     char window_text[NHSW_LINES][MAXWINDOWTEXT + 1];
-    int n_fields;
-    const char **vals;
-    boolean *activefields;
-    int *percents;
-    int *colors;
+    mswin_status_lines * status_lines;
     back_buffer_t back_buffer;
 } NHStatusWindow, *PNHStatusWindow;
 
-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,
-                             BL_ENE,       BL_ENEMAX,    BL_AC,   BL_XP,
-                             BL_EXP,       BL_HD,        BL_TIME, BL_HUNGER,
-                             BL_CAP,       BL_CONDITION, -1 };
-static int *fieldorders[] = { fieldorder1, fieldorder2, NULL };
 
 static TCHAR szStatusWindowClass[] = TEXT("MSNHStatusWndClass");
 LRESULT CALLBACK StatusWndProc(HWND, UINT, WPARAM, LPARAM);
@@ -195,22 +184,19 @@ StatusWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
         case MSNH_MSG_GETTEXT: {
             PMSNHMsgGetText msg_data = (PMSNHMsgGetText) lParam;
 #ifdef STATUS_HILITES
-            int **fop;
-            int *f;
-
             msg_data->buffer[0] = '\0';
-            if (data->n_fields > 0) {
-                for (fop = fieldorders; *fop; fop++) {
-                    for (f = *fop; *f != -1; f++) {
-                        if (data->activefields[*f])
-                            strncat(msg_data->buffer, data->vals[*f],
-                                    msg_data->max_size
-                                    - strlen(msg_data->buffer));
-                    }
-                    strncat(msg_data->buffer, "\r\n",
-                            msg_data->max_size - strlen(msg_data->buffer));
+
+            for (int line = 0; line < NHSW_LINES; line++) {
+                mswin_status_line *status_line = data->status_lines[line].lines;
+                for (int i = 0; i < status_line->status_strings.count; i++) {
+                    mswin_status_string * status_string = status_line->status_strings.status_strings[i];
+                    strncat(msg_data->buffer, status_string->str,
+                        msg_data->max_size - strlen(msg_data->buffer));
                 }
+                strncat(msg_data->buffer, "\r\n",
+                    msg_data->max_size - strlen(msg_data->buffer));
             }
+
 #else
             strncpy(msg_data->buffer, data->window_text[0],
                     msg_data->max_size);
@@ -223,11 +209,7 @@ StatusWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 
         case MSNH_MSG_UPDATE_STATUS: {
             PMSNHMsgUpdateStatus msg_data = (PMSNHMsgUpdateStatus) 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;
+            data->status_lines = msg_data->status_lines;
             InvalidateRect(hWnd, NULL, TRUE);
         } break;
         } /* end switch( wParam ) { */
@@ -273,10 +255,6 @@ StatusWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 static LRESULT
 onWMPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
 {
-    int hpbar_percent = 100;
-    int hpbar_color = NO_COLOR;
-    int *f;
-    int **fop;
     SIZE sz;
     HGDIOBJ normalFont, boldFont;
     WCHAR wbuf[BUFSZ];
@@ -308,12 +286,6 @@ onWMPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
     SetBkColor(hdc, status_bg_color);
     SetTextColor(hdc, status_fg_color);
 
-    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;
-    }
-
     clear_rect.left = 0;
     clear_rect.top = 0;
     clear_rect.right = width;
@@ -321,23 +293,38 @@ onWMPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
 
     FillRect(hdc, &clear_rect, status_bg_brush);
 
-    for (fop = fieldorders; *fop; fop++) {
+    // TODO: Put it around for loop instead -- temporary to get a better diff
+    if (data->status_lines == NULL) {
+        BitBlt(front_buffer_hdc, 0, 0, width, height, hdc, 0, 0, SRCCOPY);
+
+        EndPaint(hWnd, &ps);
+        return 0;
+    }
+
+    for (int line = 0; line < NHSW_LINES; line++) {
         LONG left = rt.left;
         LONG cy = 0;
         int vlen;
-        for (f = *fop; *f != BL_FLUSH; f++) {
+
+        mswin_status_line * status_line = &data->status_lines->lines[line];
+
+        for (int i = 0; i < status_line->status_strings.count; i++) {
+            mswin_status_string * status_string = status_line->status_strings.status_strings[i];
             int clr, atr;
             int fntatr = ATR_NONE;
             HGDIOBJ fnt;
             COLORREF nFg, nBg;
 
-            if (((*f) >= data->n_fields) || (!data->activefields[*f]))
+            if (status_string->str == NULL || status_string->str[0] == '\0')
                 continue;
-            clr = data->colors[*f] & 0x00ff;
-            atr = (data->colors[*f] & 0xff00) >> 8;
-            vlen = strlen(data->vals[*f]);
 
-            const char *str = data->vals[*f];
+
+            clr = status_string->color & 0x00ff;
+            atr = (status_string->color & 0xff00) >> 8;
+
+            const char *str = status_string->str;
+
+            vlen = strlen(str);
 
             if (atr & HL_BOLD)
                 fntatr = ATR_BOLD;
@@ -362,8 +349,13 @@ onWMPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
             nBg = status_bg_color;
 
             sz.cy = -1;
-            if (*f == BL_TITLE && iflags.wc2_hitpointbar) {
-                HBRUSH back_brush = CreateSolidBrush(nhcolor_to_RGB(hpbar_color));
+
+            if (status_string->draw_bar && iflags.wc2_hitpointbar) {
+
+                /* when we are drawing bar we need to look at the hp status
+                 * field to get the correct percentage and color */
+                COLORREF bar_color = nhcolor_to_RGB(status_string->bar_color);
+                HBRUSH back_brush = CreateSolidBrush(bar_color);
                 RECT barrect;
 
                 /* prepare for drawing */
@@ -371,7 +363,7 @@ onWMPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
                 SetBkMode(hdc, OPAQUE);
                 SetBkColor(hdc, status_bg_color);
                 /* SetTextColor(hdc, nhcolor_to_RGB(hpbar_color)); */
-                               SetTextColor(hdc, status_fg_color);
+                               SetTextColor(hdc, status_fg_color);
 
                 if (useUnicode) {
                     /* get bounding rectangle */
@@ -379,21 +371,22 @@ onWMPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
 
                     /* first draw title normally */
                     DrawTextW(hdc, wbuf, vlen, &rt, DT_LEFT);
-                } else {
+                }
+                else {
                     /* get bounding rectangle */
                     GetTextExtentPoint32A(hdc, str, vlen, &sz);
 
                     /* first draw title normally */
                     DrawTextA(hdc, str, vlen, &rt, DT_LEFT);
                 }
-
-                if (hpbar_percent > 0) {
+                int bar_percent = status_string->bar_percent;
+                if (bar_percent > 0) {
                     /* 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);
+                    if (bar_percent > 0)
+                        barrect.right = (int)((bar_percent * sz.cx) / 100);
                     /* else
                         barrect.right = sz.cx; */
 
index 2349a29f35c01b34e48bed7dfdf9187cb4bcc81f..1f0d75d260dbab236c1844a5a2959af6176657c6 100644 (file)
@@ -9,6 +9,75 @@
 #include "config.h"
 #include "global.h"
 
+#define NHSW_LINES 2
+
+static const int fieldorder1[] = { BL_TITLE, BL_STR, BL_DX,    BL_CO,    BL_IN,
+                             BL_WI,    BL_CH,  BL_ALIGN, BL_SCORE, -1 };
+static const int fieldorder2[] = { BL_LEVELDESC, BL_GOLD,      BL_HP,   BL_HPMAX,
+                             BL_ENE,       BL_ENEMAX,    BL_AC,   BL_XP,
+                             BL_EXP,       BL_HD,        BL_TIME, BL_HUNGER,
+                             BL_CAP,       BL_CONDITION, -1 };
+static const int *fieldorders[] = { fieldorder1, fieldorder2, NULL };
+static const int fieldcounts[NHSW_LINES] = { SIZE(fieldorder1) - 1, SIZE(fieldorder2) - 1};
+
+#define MSWIN_MAX_LINE1_STRINGS (SIZE(fieldorder1) - 1)
+#define MSWIN_MAX_LINE2_STRINGS (SIZE(fieldorder2) - 1 + BL_MASK_BITS)
+#define MSWIN_MAX_LINE_STRINGS (MSWIN_MAX_LINE1_STRINGS > MSWIN_MAX_LINE2_STRINGS ? \
+                                MSWIN_MAX_LINE1_STRINGS : MSWIN_MAX_LINE2_STRINGS)
+
+#define MSWIN_LINE1_FIELDS (SIZE(fieldorder1) - 1)
+#define MSWIN_LINE2_FIELDS (SIZE(fieldorder2) - 1)
+#define MSWIN_MAX_LINE_FIELDS (MSWIN_LINE1_FIELDS > MSWIN_LINE2_FIELDS ? \
+                               MSWIN_LINE1_FIELDS : MSWIN_LINE2_FIELDS)
+
+/* when status hilites are enabled, we use an array of mswin_status_strings
+ * to represent what needs to be rendered. */
+typedef struct mswin_status_string  {
+    const char * str; /* ascii string to be displayed */
+    int color; /* string text color */
+    boolean draw_bar;
+    int bar_percent; /* a percentage to indicate; 100 will draw no percentage bar */
+    int bar_color; /* color index of percentage bar */
+} mswin_status_string;
+
+typedef struct mswin_status_strings
+{
+    int count;
+    mswin_status_string * status_strings[MSWIN_MAX_LINE_STRINGS];
+} mswin_status_strings;
+
+typedef struct mswin_status_field {
+    int field_index; // field index
+    boolean enabled; // whether the field is enabled
+    const char * name; // name of status field
+    const char * format; // format of field
+
+    int percent;
+    int color;
+    char string[BUFSZ];
+
+} mswin_status_field;
+
+typedef struct mswin_condition_field {
+    int mask;
+    const char * name;
+    int bit_position;
+} mswin_condition_field;
+
+typedef struct mswin_status_fields {
+    int count;
+    mswin_status_field * status_fields[MSWIN_MAX_LINE_FIELDS];
+} mswin_status_fields;
+
+typedef struct mswin_status_line {
+    mswin_status_strings status_strings;
+    mswin_status_fields status_fields;
+} mswin_status_line;
+
+typedef struct mswin_status_lines {
+    mswin_status_line lines[NHSW_LINES]; /* number of strings to be rendered on each line */
+} mswin_status_lines;
+
 HWND mswin_init_status_window(void);
 void mswin_status_window_size(HWND hWnd, LPSIZE sz);
 
index c6714bc1535d972263d9949c19c3681debcb7e44..74a4cd3c6e22001e180d396686ecf830c22bdd74 100644 (file)
@@ -2766,12 +2766,28 @@ NHMessageBox(HWND hWnd, LPCTSTR text, UINT type)
     return MessageBox(hWnd, text, title, type);
 }
 
-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];
+static mswin_status_lines _status_lines;
+static mswin_status_string _status_strings[MAXBLSTATS];
+static mswin_status_string _condition_strings[BL_MASK_BITS];
+static mswin_status_field _status_fields[MAXBLSTATS];
+
+static mswin_condition_field _condition_fields[BL_MASK_BITS] = {
+    { BL_MASK_STONE, " Stone" },
+    { BL_MASK_SLIME, " Slime" },
+    { BL_MASK_STRNGL, " Strngl" },
+    { BL_MASK_FOODPOIS, " FoodPois" },
+    { BL_MASK_TERMILL, " TermIll" },
+    { BL_MASK_BLIND, " Blind" },
+    { BL_MASK_DEAF, " Deaf" },
+    { BL_MASK_STUN, " Stun" },
+    { BL_MASK_CONF, " Conf" },
+    { BL_MASK_HALLU, " Hallu" },
+    { BL_MASK_LEV, " Lev" },
+    { BL_MASK_FLY, " Fly" },
+    { BL_MASK_RIDE, " Ride" }
+};
+
+
 extern winid WIN_STATUS;
 
 #ifdef STATUS_HILITES
@@ -2792,15 +2808,62 @@ status_init()   -- core calls this to notify the window port that a status
 void
 mswin_status_init(void)
 {
-    int i;
     logDebug("mswin_status_init()\n");
-    for (i = 0; i < MAXBLSTATS; ++i) {
-        _status_vals[i] = (char *) alloc(BUFSZ);
-        *_status_vals[i] = '\0';
-        _status_activefields[i] = FALSE;
-        _status_fieldfmt[i] = (const char *) 0;
-        _status_colors[i] = CLR_MAX; /* no color */
-        _status_percents[i] = 0;
+
+    for (int i = 0; i < SIZE(_status_fields); i++) {
+        mswin_status_field * status_field = &_status_fields[i];
+        status_field->field_index = i;
+        status_field->enabled = FALSE;
+    }
+
+    for (int i = 0; i < SIZE(_condition_fields); i++) {
+        mswin_condition_field * condition_field = &_condition_fields[i];
+        nhassert(condition_field->mask == (1 << i));
+        condition_field->bit_position = i;
+    }
+
+    for (int i = 0; i < SIZE(_status_strings); i++) {
+        mswin_status_string * status_string = &_status_strings[i];
+        status_string->str = NULL;
+    }
+
+    for (int i = 0; i < SIZE(_condition_strings); i++) {
+        mswin_status_string * status_string = &_condition_strings[i];
+        status_string->str = NULL;
+    }
+
+    for (int lineIndex = 0; lineIndex < SIZE(_status_lines.lines); lineIndex++) {
+        mswin_status_line * line = &_status_lines.lines[lineIndex];
+
+        mswin_status_fields * status_fields = &line->status_fields;
+        status_fields->count = 0;
+
+        mswin_status_strings * status_strings = &line->status_strings;
+        status_strings->count = 0;
+
+        for (int i = 0; i < fieldcounts[lineIndex]; i++) {
+            int field_index = fieldorders[lineIndex][i];
+            nhassert(field_index <= SIZE(_status_fields));
+
+            nhassert(status_fields->count <= SIZE(status_fields->status_fields));
+            status_fields->status_fields[status_fields->count++] = &_status_fields[field_index];
+
+            nhassert(status_strings->count <= SIZE(status_strings->status_strings));
+            status_strings->status_strings[status_strings->count++] =
+                &_status_strings[field_index];
+
+            if (field_index == BL_CONDITION) {
+                for (int j = 0; j < BL_MASK_BITS; j++) {
+                    nhassert(status_strings->count <= SIZE(status_strings->status_strings));
+                    status_strings->status_strings[status_strings->count++] =
+                        &_condition_strings[j];
+                }
+            }
+        }
+    }
+
+
+    for (int i = 0; i < MAXBLSTATS; ++i) {
 #ifdef STATUS_HILITES
         _status_hilites[i].thresholdtype = 0;
         _status_hilites[i].behavior = BL_TH_NONE;
@@ -2820,17 +2883,7 @@ status_finish() -- called when it is time for the window port to tear down
 void
 mswin_status_finish(void)
 {
-    /* tear down routine */
-    int i;
-
     logDebug("mswin_status_finish()\n");
-
-    /* free alloc'd memory here */
-    for (i = 0; i < MAXBLSTATS; ++i) {
-        if (_status_vals[i])
-            free((genericptr_t) _status_vals[i]);
-        _status_vals[i] = (char *) 0;
-    }
 }
 
 /*
@@ -2853,9 +2906,41 @@ mswin_status_enablefield(int fieldidx, const char *nm, const char *fmt,
 {
     logDebug("mswin_status_enablefield(%d, %s, %s, %d)\n", fieldidx, nm, fmt,
              (int) enable);
-    _status_fieldfmt[fieldidx] = fmt;
-    _status_fieldnm[fieldidx] = nm;
-    _status_activefields[fieldidx] = enable;
+
+    nhassert(fieldidx <= SIZE(_status_fields));
+    mswin_status_field * field = &_status_fields[fieldidx];
+
+    nhassert(fieldidx <= SIZE(_status_strings));
+    mswin_status_string * string = &_status_strings[fieldidx];
+
+    if (field != NULL) {
+        field->format = fmt;
+        field->name = nm;
+        field->enabled = enable;
+
+        string->str = (field->enabled ? field->string : NULL);
+
+        if (field->field_index == BL_CONDITION)
+            string->str = NULL;
+
+        string->draw_bar = (field->enabled && field->field_index == BL_TITLE);
+    }
+}
+
+/* TODO: turn this into a commmon helper; multiple identical implementations */
+static int
+mswin_condcolor(bm, bmarray)
+long bm;
+unsigned long *bmarray;
+{
+    int i;
+
+    if (bm && bmarray)
+        for (i = 0; i < CLR_MAX; ++i) {
+            if ((bm & bmarray[i]) != 0)
+                return i;
+        }
+    return NO_COLOR;
 }
 
 /*
@@ -2910,11 +2995,10 @@ mswin_status_update(int idx, genericptr_t ptr, int chg, int percent, int color,
     MSNHMsgUpdateStatus update_cmd_data;
     int ocolor, ochar;
     unsigned ospecial;
-    long value = -1;
-    boolean reset_state = FALSE;
 
     logDebug("mswin_status_update(%d, %p, %d, %d, %x, %p)\n", idx, ptr, chg, percent, color, colormasks);
 
+#if 0 // TODO: this code was dead ... do we need to respond to these updates?
     switch (idx) {
         case BL_RESET:
             reset_state = TRUE;
@@ -2924,42 +3008,44 @@ mswin_status_update(int idx, genericptr_t ptr, int chg, int percent, int color,
         default:
             break;
     }
+#endif
 
     if (idx >= 0) {
-        if (!_status_activefields[idx])
+
+        nhassert(idx <= SIZE(_status_fields));
+        mswin_status_field * status_field = &_status_fields[idx];
+        nhassert(status_field->field_index == idx);
+
+        nhassert(idx <= SIZE(_status_strings));
+        mswin_status_string * status_string = &_status_strings[idx];
+
+        if (!status_field->enabled) {
+            nhassert(status_string->str == NULL);
             return;
-        _status_percents[idx] = percent;
+        }
+
+        // TODO: is color actualy color and attribute OR not?
+        status_field->color = color & 0xff;
+        status_string->color = color & 0xff;
+
         switch (idx) {
         case BL_CONDITION: {
+            mswin_condition_field * condition_field = _condition_fields;
+
+            nhassert(status_string->str == NULL);
+
             cond = *condptr;
-            *_status_vals[idx] = '\0';
-            if (cond & BL_MASK_STONE)
-                Strcat(_status_vals[idx], " Stone");
-            if (cond & BL_MASK_SLIME)
-                Strcat(_status_vals[idx], " Slime");
-            if (cond & BL_MASK_STRNGL)
-                Strcat(_status_vals[idx], " Strngl");
-            if (cond & BL_MASK_FOODPOIS)
-                Strcat(_status_vals[idx], " FoodPois");
-            if (cond & BL_MASK_TERMILL)
-                Strcat(_status_vals[idx], " TermIll");
-            if (cond & BL_MASK_BLIND)
-                Strcat(_status_vals[idx], " Blind");
-            if (cond & BL_MASK_DEAF)
-                Strcat(_status_vals[idx], " Deaf");
-            if (cond & BL_MASK_STUN)
-                Strcat(_status_vals[idx], " Stun");
-            if (cond & BL_MASK_CONF)
-                Strcat(_status_vals[idx], " Conf");
-            if (cond & BL_MASK_HALLU)
-                Strcat(_status_vals[idx], " Hallu");
-            if (cond & BL_MASK_LEV)
-                Strcat(_status_vals[idx], " Lev");
-            if (cond & BL_MASK_FLY)
-                Strcat(_status_vals[idx], " Fly");
-            if (cond & BL_MASK_RIDE)
-                Strcat(_status_vals[idx], " Ride");
-            value = cond;
+
+            for (int i = 0; i < BL_MASK_BITS; i++, condition_field++) {
+                status_string = &_condition_strings[i];
+
+                if (condition_field->mask & cond) {
+                    status_string->str = condition_field->name;
+                    status_string->color = mswin_condcolor(condition_field->mask, colormasks);
+                }
+                else
+                    status_string->str = NULL;
+            }
         } break;
         case BL_GOLD: {
             char buf[BUFSZ];
@@ -2971,33 +3057,34 @@ mswin_status_update(int idx, genericptr_t ptr, int chg, int percent, int color,
             p = strchr(text, ':');
             if (p) {
                 strncpy(buf + 1, p, sizeof(buf) - 2);
-                value = atol(p + 1);
             } else {
                 buf[1] = ':';
                 strncpy(buf + 2, text, sizeof(buf) - 2);
-                value = atol(text);
             }
-            Sprintf(_status_vals[idx],
-                    _status_fieldfmt[idx] ? _status_fieldfmt[idx] : "%s",
-                    buf);
+
+            Sprintf(status_field->string, status_field->format ? status_field->format : "%s", buf);
+            nhassert(status_string->str == status_field->string);
         } break;
         default: {
-            value = atol(text);
-            Sprintf(_status_vals[idx],
-                    _status_fieldfmt[idx] ? _status_fieldfmt[idx] : "%s",
+            Sprintf(status_field->string, status_field->format ? status_field->format : "%s",
                     text);
+            nhassert(status_string->str == status_field->string);
         } break;
         }
 
-        _status_colors[idx] = color;
+        /* if we received an update for the hp field, we must update the
+         * bar percent and bar color for the title string */
+        if (idx == BL_HP) {
+            mswin_status_string * title_string = &_status_strings[BL_TITLE];
+
+            title_string->bar_color = color;
+            title_string->bar_percent = percent;
+
+        }
 
         /* 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;
+        update_cmd_data.status_lines = &_status_lines;
         SendMessage(mswin_hwnd_from_winid(WIN_STATUS), WM_MSNH_COMMAND,
                 (WPARAM) MSNH_MSG_UPDATE_STATUS, (LPARAM) &update_cmd_data);
     }