Added support for color condition hilites to tile mode.

Code is complete but might take another pass over the code to simplify
where we can.
This commit is contained in:
Bart House
2018-11-25 21:04:30 -08:00
parent 95e701cd01
commit c44c0d3e01
5 changed files with 283 additions and 136 deletions

View 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

View 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

View 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; */

View 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);

View 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);
}