From: Alex Kompel Date: Sat, 18 Apr 2015 05:14:04 +0000 (-0700) Subject: win32_gui: implement STATUS_VIA_WINDOWPORT and STATUS_HILITES X-Git-Tag: NetHack-3.6.0_RC01~414^2~23^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=09d64059cbb5990e8f674735134e656677c2e509;p=nethack win32_gui: implement STATUS_VIA_WINDOWPORT and STATUS_HILITES --- diff --git a/src/botl.c b/src/botl.c index 99fad4a32..976c1aca8 100644 --- a/src/botl.c +++ b/src/botl.c @@ -925,7 +925,7 @@ assign_hilite(sa,sb,sc,sd) char *sa, *sb, *sc, *sd; { char *tmp, *how; - int i, dt, idx = -1; + int i = -1, dt = -1, idx = -1; int coloridx[2] = {-1, -1}; boolean inverse[2] = {FALSE, FALSE}; boolean bold[2] = {FALSE, FALSE}; diff --git a/win/win32/mhfont.c b/win/win32/mhfont.c index 7cebb921b..d7a34ba41 100644 --- a/win/win32/mhfont.c +++ b/win/win32/mhfont.c @@ -77,11 +77,12 @@ HGDIOBJ mswin_get_font(int win_type, int attr, HDC hdc, BOOL replace) switch(win_type) { case NHW_STATUS: - lgfnt.lfHeight = -iflags.wc_fontsiz_status*GetDeviceCaps(hdc, LOGPIXELSY)/72; // height of font + font_size = (attr==ATR_BOLD)? iflags.wc_fontsiz_status+1 : iflags.wc_fontsiz_status; + lgfnt.lfHeight = -font_size*GetDeviceCaps(hdc, LOGPIXELSY)/72; // height of font lgfnt.lfWidth = 0; // average character width lgfnt.lfEscapement = 0; // angle of escapement lgfnt.lfOrientation = 0; // base-line orientation angle - lgfnt.lfWeight = FW_BOLD; // font weight + lgfnt.lfWeight = (attr==ATR_BOLD)? FW_BOLD : FW_NORMAL; // font weight lgfnt.lfItalic = FALSE; // italic attribute option lgfnt.lfUnderline = FALSE; // underline attribute option lgfnt.lfStrikeOut = FALSE; // strikeout attribute option diff --git a/win/win32/mhmsg.h b/win/win32/mhmsg.h index 8e48a3b01..4999f9855 100644 --- a/win/win32/mhmsg.h +++ b/win/win32/mhmsg.h @@ -22,6 +22,7 @@ #define MSNH_MSG_DIED 109 #define MSNH_MSG_CARET 110 #define MSNH_MSG_GETTEXT 111 +#define MSNH_MSG_UPDATE_STATUS 112 typedef struct mswin_nhmsg_add_wnd { winid wid; @@ -68,5 +69,12 @@ typedef struct mswin_nhmsg_get_text { char buffer[]; } MSNHMsgGetText, *PMSNHMsgGetText; +typedef struct mswin_nhmsg_update_status { + int n_fields; + const char** vals; + boolean* activefields; + int* colors; +} MSNHMsgUpdateStatus, *PMSNHMsgUpdateStatus; + #endif diff --git a/win/win32/mhstatus.c b/win/win32/mhstatus.c index 05a4c57e8..05f3836a0 100644 --- a/win/win32/mhstatus.c +++ b/win/win32/mhstatus.c @@ -11,14 +11,34 @@ #define NHSW_LINES 2 #define MAXWINDOWTEXT BUFSZ +extern COLORREF nhcolor_to_RGB (int c); /* from mhmap */ + typedef struct mswin_nethack_status_window { - int index; - char window_text[NHSW_LINES][MAXWINDOWTEXT+1]; + int index; + char window_text[NHSW_LINES][MAXWINDOWTEXT+1]; + int n_fields; + const char** vals; + boolean* activefields; + 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, + 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}; +#endif /* STATUS_VIA_WINDOWPORT */ + static TCHAR szStatusWindowClass[] = TEXT("MSNHStatusWndClass"); LRESULT CALLBACK StatusWndProc(HWND, UINT, WPARAM, LPARAM); static void register_status_window_class(void); +static LRESULT onWMPaint(HWND hWnd, WPARAM wParam, LPARAM lParam); #define DEFAULT_COLOR_BG_STATUS COLOR_WINDOW #define DEFAULT_COLOR_FG_STATUS COLOR_WINDOWTEXT @@ -91,9 +111,6 @@ void register_status_window_class() LRESULT CALLBACK StatusWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { - RECT rt; - PAINTSTRUCT ps; - HDC hdc; PNHStatusWindow data; data = (PNHStatusWindow)GetWindowLongPtr(hWnd, GWLP_USERDATA); @@ -118,43 +135,39 @@ LRESULT CALLBACK StatusWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lP case MSNH_MSG_GETTEXT: { PMSNHMsgGetText msg_data = (PMSNHMsgGetText)lParam; +#ifdef STATUS_VIA_WINDOWPORT + 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) ); + } + } +#else /* STATUS_VIA_WINDOWPORT */ 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 */ + } break; + + 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->colors = msg_data->colors; + InvalidateRect(hWnd, NULL, TRUE); } break; - } /* end switch( wParam ) { */ } break; - case WM_PAINT: { - int i; - SIZE sz; - HGDIOBJ oldFont; - TCHAR wbuf[BUFSZ]; - COLORREF OldBg, OldFg; - - hdc = BeginPaint(hWnd, &ps); - GetClientRect(hWnd, &rt); - - oldFont = SelectObject(hdc, mswin_get_font(NHW_STATUS, ATR_NONE, hdc, FALSE)); - - OldBg = SetBkColor(hdc, status_bg_brush - ? status_bg_color : (COLORREF)GetSysColor(DEFAULT_COLOR_BG_STATUS)); - OldFg = SetTextColor(hdc, status_fg_brush - ? status_fg_color : (COLORREF)GetSysColor(DEFAULT_COLOR_FG_STATUS)); - - for(i=0; iwindow_text[i], wbuf, sizeof(wbuf)), strlen(data->window_text[i]), &sz); - NH_A2W(data->window_text[i], wbuf, BUFSZ); - DrawText(hdc, wbuf, strlen(data->window_text[i]), &rt, DT_LEFT | DT_END_ELLIPSIS); - rt.top += sz.cy; - } - - SelectObject(hdc, oldFont); - SetTextColor (hdc, OldFg); - SetBkColor (hdc, OldBg); - EndPaint(hWnd, &ps); - } break; + case WM_PAINT: + return onWMPaint(hWnd, wParam, lParam); case WM_SIZE: { RECT rt; @@ -187,6 +200,125 @@ LRESULT CALLBACK StatusWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lP return 0; } +#ifdef STATUS_VIA_WINDOWPORT +static LRESULT onWMPaint(HWND hWnd, WPARAM wParam, LPARAM lParam) +{ + int* f; + int** fop; + SIZE sz; + HGDIOBJ oldFont, normalFont, boldFont; + TCHAR wbuf[BUFSZ]; + COLORREF OldBg, OldFg, Bg, Fg; + RECT rt; + PAINTSTRUCT ps; + HDC hdc; + PNHStatusWindow data; + + data = (PNHStatusWindow)GetWindowLongPtr(hWnd, GWLP_USERDATA); + + hdc = BeginPaint(hWnd, &ps); + GetClientRect(hWnd, &rt); + + normalFont = mswin_get_font(NHW_STATUS, ATR_NONE, hdc, FALSE); + boldFont = mswin_get_font(NHW_STATUS, ATR_BOLD, hdc, FALSE); + oldFont = SelectObject(hdc, normalFont); + + Bg = status_bg_brush? status_bg_color : (COLORREF)GetSysColor(DEFAULT_COLOR_BG_STATUS); + OldBg = SetBkColor(hdc, Bg); + + Fg = status_fg_brush? status_fg_color : (COLORREF)GetSysColor(DEFAULT_COLOR_FG_STATUS); + OldFg = SetTextColor(hdc, Fg); + + for(fop = fieldorders; *fop; fop++) { + LONG left = rt.left; + LONG cy = 0; + int vlen; + for(f=*fop; *f!=-1; f++) { + if( ((*f)>= data->n_fields) || (!data->activefields[*f])) continue; + vlen = strlen(data->vals[*f]); + NH_A2W(data->vals[*f], wbuf, SIZE(wbuf)); + + 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); + SetBkColor(hdc, Bg); + SetTextColor(hdc, Fg); + } else { + SelectObject(hdc, normalFont); + SetBkColor(hdc, Bg); + SetTextColor(hdc, Fg); + } + + GetTextExtentPoint32(hdc, wbuf, vlen, &sz); + DrawText(hdc, wbuf, vlen, &rt, DT_LEFT); + + rt.left += sz.cx; + cy = max(cy, sz.cy); + } + rt.left = left; + rt.top += cy; + } + + SelectObject(hdc, oldFont); + SetTextColor (hdc, OldFg); + SetBkColor (hdc, OldBg); + EndPaint(hWnd, &ps); + + return 0; +} +#else +static LRESULT onWMPaint(HWND hWnd, WPARAM wParam, LPARAM lParam) +{ + int i; + SIZE sz; + HGDIOBJ oldFont; + TCHAR wbuf[BUFSZ]; + COLORREF OldBg, OldFg; + RECT rt; + PAINTSTRUCT ps; + HDC hdc; + PNHStatusWindow data; + + data = (PNHStatusWindow)GetWindowLongPtr(hWnd, GWLP_USERDATA); + + hdc = BeginPaint(hWnd, &ps); + GetClientRect(hWnd, &rt); + + oldFont = SelectObject(hdc, mswin_get_font(NHW_STATUS, ATR_NONE, hdc, FALSE)); + + OldBg = SetBkColor(hdc, status_bg_brush + ? status_bg_color : (COLORREF)GetSysColor(DEFAULT_COLOR_BG_STATUS)); + OldFg = SetTextColor(hdc, status_fg_brush + ? status_fg_color : (COLORREF)GetSysColor(DEFAULT_COLOR_FG_STATUS)); + + for(i=0; iwindow_text[i]); + NH_A2W(data->window_text[i], wbuf, SIZE(wbuf)); + GetTextExtentPoint32(hdc, wbuf, wlen, &sz); + DrawText(hdc, wbuf, wlen, &rt, DT_LEFT | DT_END_ELLIPSIS); + rt.top += sz.cy; + } + + SelectObject(hdc, oldFont); + SetTextColor (hdc, OldFg); + SetBkColor (hdc, OldBg); + EndPaint(hWnd, &ps); + + return 0; +} +#endif /*STATUS_VIA_WINDOWPORT*/ + void mswin_status_window_size (HWND hWnd, LPSIZE sz) { TEXTMETRIC tm; diff --git a/win/win32/mswproc.c b/win/win32/mswproc.c index b612f79aa..5cdd4bd5d 100644 --- a/win/win32/mswproc.c +++ b/win/win32/mswproc.c @@ -12,6 +12,7 @@ #include "dlb.h" #include "func_tab.h" /* for extended commands */ #include "winMS.h" +#include #include "mhmap.h" #include "mhstatus.h" #include "mhtext.h" @@ -29,8 +30,6 @@ #define LLEN 128 -extern winid WIN_STATUS; - #define NHTRACE_LOG "nhtrace.log" #ifdef _DEBUG @@ -129,12 +128,12 @@ struct window_procs mswin_procs = { mswin_getmsghistory, mswin_putmsghistory, #ifdef STATUS_VIA_WINDOWPORT - genl_status_init, - genl_status_finish, - genl_status_enablefield, - genl_status_update, + mswin_status_init, + mswin_status_finish, + mswin_status_enablefield, + mswin_status_update, # ifdef STATUS_HILITES - genl_status_threshold, + mswin_status_threshold, # endif #endif genl_can_suspend_yes, @@ -1823,7 +1822,8 @@ void mswin_outrip(winid wid, int how, time_t when) void mswin_preference_update(const char *pref) { HDC hdc; - + int i; + if( stricmp( pref, "font_menu")==0 || stricmp( pref, "font_size_menu")==0 ) { if( iflags.wc_fontsiz_menuhMainWnd, hdc); - InvalidateRect(mswin_hwnd_from_winid(WIN_STATUS), NULL, TRUE); + for (i=1; iwindowlist[i].type == NHW_STATUS + && GetNHApp()->windowlist[i].win != NULL) { + InvalidateRect(GetNHApp()->windowlist[i].win, NULL, TRUE); + } + } mswin_layout_main_window(NULL); return; } @@ -2594,3 +2599,274 @@ int 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 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 _status_hilites[MAXBLSTATS]; +#endif /* STATUS_HILITES */ +/* +status_init() -- core calls this to notify the window port that a status + display is required. The window port should perform + the necessary initialization in here, allocate memory, etc. +*/ +void +mswin_status_init(void) +{ + logDebug("mswin_status_init()\n"); + int i; + 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 */ +# ifdef STATUS_HILITES + _status_hilites[i].thresholdtype = 0; + _status_hilites[i].behavior = BL_TH_NONE; + _status_hilites[i].under = BL_HILITE_NONE; + _status_hilites[i].over = BL_HILITE_NONE; +#endif /* STATUS_HILITES */ + } + /* Use a window for the genl version; backward port compatibility */ + WIN_STATUS = create_nhwindow(NHW_STATUS); + display_nhwindow(WIN_STATUS, FALSE); +} + +/* +status_finish() -- called when it is time for the window port to tear down + the status display and free allocated memory, etc. +*/ +void +mswin_status_finish(void) +{ + logDebug("mswin_status_finish()\n"); + /* tear down routine */ + int i; + + /* 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; + } +} + +/* +status_enablefield(int fldindex, char fldname, char fieldfmt, boolean enable) + -- notifies the window port which fields it is authorized to + display. + -- This may be called at any time, and is used + to disable as well as enable fields, depending on the + value of the final argument (TRUE = enable). + -- fldindex could be 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 + -- There are MAXBLSTATS status fields (from botl.h) +*/ +void +mswin_status_enablefield(int fieldidx, const char *nm, const char *fmt, boolean enable) +{ + 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; +} + +# 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 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 */ + + /* 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.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*/ diff --git a/win/win32/winMS.h b/win/win32/winMS.h index b3c33faa7..567503e5f 100644 --- a/win/win32/winMS.h +++ b/win/win32/winMS.h @@ -164,6 +164,17 @@ 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*/ + /* helper function */ HWND mswin_hwnd_from_winid(winid wid); winid mswin_winid_from_type(int type);