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
#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
} 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
#include "mhmsg.h"
#include "mhfont.h"
-#define NHSW_LINES 2
#define MAXWINDOWTEXT BUFSZ
extern COLORREF nhcolor_to_RGB(int c); /* from mhmap */
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);
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);
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 ) { */
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];
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;
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;
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 */
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 */
/* 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; */
#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);
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
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;
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;
- }
}
/*
{
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;
}
/*
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;
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];
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);
}