1 /* NetHack 3.6 mhstatus.c $NHDT-Date: 1432512810 2015/05/25 00:13:30 $ $NHDT-Branch: master $:$NHDT-Revision: 1.22 $ */
2 /* Copyright (C) 2001 by Alex Kompel */
3 /* NetHack may be freely redistributed. See license for details. */
12 #define MAXWINDOWTEXT BUFSZ
14 extern COLORREF nhcolor_to_RGB(int c); /* from mhmap */
16 typedef struct back_buffer {
25 void back_buffer_free(back_buffer_t * back_buffer)
27 if (back_buffer->bm != NULL) {
28 SelectObject(back_buffer->hdc, back_buffer->orig_bm);
29 DeleteObject(back_buffer->bm);
30 back_buffer->bm = NULL;
34 void back_buffer_allocate(back_buffer_t * back_buffer, int width, int height)
36 HDC hdc = GetDC(back_buffer->hWnd);
37 back_buffer->bm = CreateCompatibleBitmap(hdc, width, height);
38 back_buffer->orig_bm = SelectObject(back_buffer->hdc, back_buffer->bm);
39 back_buffer->width = width;
40 back_buffer->height = height;
41 ReleaseDC(back_buffer->hWnd, hdc);
44 void back_buffer_size(back_buffer_t * back_buffer, int width, int height)
46 if (back_buffer->bm == NULL || back_buffer->width != width
47 || back_buffer->height != height) {
48 back_buffer_free(back_buffer);
49 back_buffer_allocate(back_buffer, width, height);
53 void back_buffer_init(back_buffer_t * back_buffer, HWND hWnd, int width, int height)
55 back_buffer->hWnd = hWnd;
56 back_buffer->hdc = CreateCompatibleDC(NULL);
57 back_buffer->bm = NULL;
59 back_buffer_size(back_buffer, width, height);
62 typedef struct mswin_nethack_status_window {
64 char window_text[NHSW_LINES][MAXWINDOWTEXT + 1];
67 boolean *activefields;
70 back_buffer_t back_buffer;
71 } NHStatusWindow, *PNHStatusWindow;
73 static int fieldorder1[] = { BL_TITLE, BL_STR, BL_DX, BL_CO, BL_IN,
74 BL_WI, BL_CH, BL_ALIGN, BL_SCORE, -1 };
75 static int fieldorder2[] = { BL_LEVELDESC, BL_GOLD, BL_HP, BL_HPMAX,
76 BL_ENE, BL_ENEMAX, BL_AC, BL_XP,
77 BL_EXP, BL_HD, BL_TIME, BL_HUNGER,
78 BL_CAP, BL_CONDITION, -1 };
79 static int *fieldorders[] = { fieldorder1, fieldorder2, NULL };
81 static TCHAR szStatusWindowClass[] = TEXT("MSNHStatusWndClass");
82 LRESULT CALLBACK StatusWndProc(HWND, UINT, WPARAM, LPARAM);
83 static void register_status_window_class(void);
84 static LRESULT onWMPaint(HWND hWnd, WPARAM wParam, LPARAM lParam);
86 #define DEFAULT_COLOR_BG_STATUS COLOR_WINDOW
87 #define DEFAULT_COLOR_FG_STATUS COLOR_WINDOWTEXT
90 mswin_init_status_window()
92 static int run_once = 0;
99 register_status_window_class();
103 /* get window position */
104 if (GetNHApp()->bAutoLayout) {
105 SetRect(&rt, 0, 0, 0, 0);
107 mswin_get_window_placement(NHW_STATUS, &rt);
110 /* create status window object */
111 width = rt.right - rt.left;
112 height = rt.bottom - rt.top;
113 ret = CreateWindow(szStatusWindowClass, NULL,
114 WS_CHILD | WS_CLIPSIBLINGS | WS_SIZEBOX,
115 rt.left, /* horizontal position of window */
116 rt.top, /* vertical position of window */
117 width, /* window width */
118 height, /* window height */
119 GetNHApp()->hMainWnd, NULL, GetNHApp()->hApp, NULL);
121 panic("Cannot create status window");
123 /* Set window caption */
124 SetWindowText(ret, "Status");
126 /* create window data */
127 data = (PNHStatusWindow) malloc(sizeof(NHStatusWindow));
129 panic("out of memory");
131 ZeroMemory(data, sizeof(NHStatusWindow));
132 SetWindowLongPtr(ret, GWLP_USERDATA, (LONG_PTR) data);
134 back_buffer_init(&data->back_buffer, ret, width, height);
136 mswin_apply_window_style(ret);
138 if (status_bg_brush == NULL) {
139 status_bg_color = (COLORREF)GetSysColor(DEFAULT_COLOR_BG_STATUS);
140 status_bg_brush = CreateSolidBrush(status_bg_color);
143 if (status_fg_brush == NULL) {
144 status_fg_color = (COLORREF)GetSysColor(DEFAULT_COLOR_FG_STATUS);
145 status_fg_brush = CreateSolidBrush(status_fg_color);
152 register_status_window_class()
155 ZeroMemory(&wcex, sizeof(wcex));
157 wcex.style = CS_NOCLOSE;
158 wcex.lpfnWndProc = (WNDPROC) StatusWndProc;
161 wcex.hInstance = GetNHApp()->hApp;
163 wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
164 wcex.hbrBackground = NULL;
165 wcex.lpszMenuName = NULL;
166 wcex.lpszClassName = szStatusWindowClass;
168 RegisterClass(&wcex);
172 StatusWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
174 PNHStatusWindow data;
176 data = (PNHStatusWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA);
178 case WM_MSNH_COMMAND: {
180 case MSNH_MSG_PUTSTR: {
181 PMSNHMsgPutstr msg_data = (PMSNHMsgPutstr) lParam;
182 strncpy(data->window_text[data->index], msg_data->text,
184 data->index = (data->index + 1) % NHSW_LINES;
185 InvalidateRect(hWnd, NULL, TRUE);
188 case MSNH_MSG_CLEAR_WINDOW: {
190 ZeroMemory(data->window_text, sizeof(data->window_text));
191 InvalidateRect(hWnd, NULL, TRUE);
194 case MSNH_MSG_GETTEXT: {
195 PMSNHMsgGetText msg_data = (PMSNHMsgGetText) lParam;
196 #ifdef STATUS_HILITES
200 msg_data->buffer[0] = '\0';
201 if (data->n_fields > 0) {
202 for (fop = fieldorders; *fop; fop++) {
203 for (f = *fop; *f != -1; f++) {
204 if (data->activefields[*f])
205 strncat(msg_data->buffer, data->vals[*f],
207 - strlen(msg_data->buffer));
209 strncat(msg_data->buffer, "\r\n",
210 msg_data->max_size - strlen(msg_data->buffer));
214 strncpy(msg_data->buffer, data->window_text[0],
216 strncat(msg_data->buffer, "\r\n",
217 msg_data->max_size - strlen(msg_data->buffer));
218 strncat(msg_data->buffer, data->window_text[1],
219 msg_data->max_size - strlen(msg_data->buffer));
223 case MSNH_MSG_UPDATE_STATUS: {
224 PMSNHMsgUpdateStatus msg_data = (PMSNHMsgUpdateStatus) lParam;
225 data->n_fields = msg_data->n_fields;
226 data->vals = msg_data->vals;
227 data->activefields = msg_data->activefields;
228 data->percents = msg_data->percents;
229 data->colors = msg_data->colors;
230 InvalidateRect(hWnd, NULL, TRUE);
232 } /* end switch( wParam ) { */
236 return onWMPaint(hWnd, wParam, lParam);
240 GetWindowRect(hWnd, &rt);
241 ScreenToClient(GetNHApp()->hMainWnd, (LPPOINT) &rt);
242 ScreenToClient(GetNHApp()->hMainWnd, ((LPPOINT) &rt) + 1);
243 mswin_update_window_placement(NHW_STATUS, &rt);
249 GetWindowRect(hWnd, &rt);
250 ScreenToClient(GetNHApp()->hMainWnd, (LPPOINT) &rt);
251 ScreenToClient(GetNHApp()->hMainWnd, ((LPPOINT) &rt) + 1);
252 mswin_update_window_placement(NHW_STATUS, &rt);
258 SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) 0);
262 SetFocus(GetNHApp()->hMainWnd);
266 return DefWindowProc(hWnd, message, wParam, lParam);
271 #ifdef STATUS_HILITES
273 onWMPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
275 int hpbar_percent = 100;
276 int hpbar_color = NO_COLOR;
280 HGDIOBJ normalFont, boldFont;
285 PNHStatusWindow data;
288 HDC front_buffer_hdc;
290 data = (PNHStatusWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA);
292 front_buffer_hdc = BeginPaint(hWnd, &ps);
293 GetClientRect(hWnd, &rt);
295 width = rt.right - rt.left;
296 height = rt.bottom - rt.top;
298 back_buffer_size(&data->back_buffer, width, height);
300 hdc = data->back_buffer.hdc;
302 normalFont = mswin_get_font(NHW_STATUS, ATR_NONE, hdc, FALSE);
303 boldFont = mswin_get_font(NHW_STATUS, ATR_BOLD, hdc, FALSE);
305 SelectObject(hdc, normalFont);
307 SetBkColor(hdc, status_bg_color);
308 SetTextColor(hdc, status_fg_color);
310 if (iflags.wc2_hitpointbar && BL_HP < data->n_fields
311 && data->activefields[BL_HP]) {
312 hpbar_percent = data->percents[BL_HP];
313 hpbar_color = data->colors[BL_HP] & 0x00ff;
318 clear_rect.right = width;
319 clear_rect.bottom = height;
321 FillRect(hdc, &clear_rect, status_bg_brush);
323 for (fop = fieldorders; *fop; fop++) {
327 for (f = *fop; *f != -1; f++) {
329 int fntatr = ATR_NONE;
333 if (((*f) >= data->n_fields) || (!data->activefields[*f]))
335 clr = data->colors[*f] & 0x00ff;
336 atr = (data->colors[*f] & 0xff00) >> 8;
337 vlen = strlen(data->vals[*f]);
338 NH_A2W(data->vals[*f], wbuf, SIZE(wbuf));
342 else if (atr & HL_INVERSE)
343 fntatr = ATR_INVERSE;
344 else if (atr & HL_ULINE)
346 else if (atr & HL_BLINK)
348 else if (atr & HL_DIM)
350 fnt = mswin_get_font(NHW_STATUS, fntatr, hdc, FALSE);
351 nFg = (clr == NO_COLOR ? status_fg_color
352 : ((clr >= 0 && clr < CLR_MAX) ? nhcolor_to_RGB(clr)
354 nBg = status_bg_color;
357 if (*f == BL_TITLE && iflags.wc2_hitpointbar) {
358 HBRUSH back_brush = CreateSolidBrush(nhcolor_to_RGB(hpbar_color));
361 /* prepare for drawing */
362 SelectObject(hdc, fnt);
363 SetBkMode(hdc, OPAQUE);
364 SetBkColor(hdc, status_bg_color);
365 SetTextColor(hdc, nhcolor_to_RGB(hpbar_color));
367 /* get bounding rectangle */
368 GetTextExtentPoint32(hdc, wbuf, vlen, &sz);
370 /* first draw title normally */
371 DrawText(hdc, wbuf, vlen, &rt, DT_LEFT);
373 /* calc bar length */
374 barrect.left = rt.left;
375 barrect.top = rt.top;
376 barrect.bottom = sz.cy;
377 if (hpbar_percent > 0)
378 barrect.right = (int)((hpbar_percent * sz.cx) / 100);
380 barrect.right = sz.cx;
382 /* then draw hpbar on top of title */
383 FillRect(hdc, &barrect, back_brush);
384 SetBkMode(hdc, TRANSPARENT);
385 SetTextColor(hdc, nBg);
386 DrawText(hdc, wbuf, vlen, &barrect, DT_LEFT);
388 DeleteObject(back_brush);
390 if (atr & HL_INVERSE) {
396 /* prepare for drawing */
397 SelectObject(hdc, fnt);
398 SetBkMode(hdc, OPAQUE);
399 SetBkColor(hdc, nBg);
400 SetTextColor(hdc, nFg);
402 /* get bounding rectangle */
403 GetTextExtentPoint32(hdc, wbuf, vlen, &sz);
406 DrawText(hdc, wbuf, vlen, &rt, DT_LEFT);
418 BitBlt(front_buffer_hdc, 0, 0, width, height, hdc, 0, 0, SRCCOPY);
426 onWMPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
432 COLORREF OldBg, OldFg;
436 PNHStatusWindow data;
438 data = (PNHStatusWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA);
440 hdc = BeginPaint(hWnd, &ps);
441 GetClientRect(hWnd, &rt);
444 SelectObject(hdc, mswin_get_font(NHW_STATUS, ATR_NONE, hdc, FALSE));
446 OldBg = SetBkColor(hdc, status_bg_brush ? status_bg_color
447 : (COLORREF) GetSysColor(
448 DEFAULT_COLOR_BG_STATUS));
449 OldFg = SetTextColor(hdc, status_fg_brush ? status_fg_color
450 : (COLORREF) GetSysColor(
451 DEFAULT_COLOR_FG_STATUS));
453 for (i = 0; i < NHSW_LINES; i++) {
454 int wlen = strlen(data->window_text[i]);
455 NH_A2W(data->window_text[i], wbuf, SIZE(wbuf));
456 GetTextExtentPoint32(hdc, wbuf, wlen, &sz);
457 DrawText(hdc, wbuf, wlen, &rt, DT_LEFT | DT_END_ELLIPSIS);
461 SelectObject(hdc, oldFont);
462 SetTextColor(hdc, OldFg);
463 SetBkColor(hdc, OldBg);
468 #endif /* !STATUS_HILITES */
471 mswin_status_window_size(HWND hWnd, LPSIZE sz)
476 PNHStatusWindow data;
480 GetClientRect(hWnd, &rt);
482 data = (PNHStatusWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA);
485 saveFont = SelectObject(
486 hdc, mswin_get_font(NHW_STATUS, ATR_NONE, hdc, FALSE));
487 GetTextExtentPoint32(hdc, _T("W"), 1, &text_sz);
488 GetTextMetrics(hdc, &tm);
490 rt.bottom = rt.top + text_sz.cy * NHSW_LINES;
492 SelectObject(hdc, saveFont);
493 ReleaseDC(hWnd, hdc);
495 AdjustWindowRect(&rt, GetWindowLong(hWnd, GWL_STYLE), FALSE);
496 sz->cx = rt.right - rt.left;
497 sz->cy = rt.bottom - rt.top;