NHDT->ANH, nethack->anethack, nhdat->anhdat
[aNetHack.git] / sys / wince / mhmap.c
blob29da40027115b36cc09ea95fea3e8bc66190e72b
1 /* aNetHack 0.0.1 mhmap.c $ANH-Date: 1432512799 2015/05/25 00:13:19 $ $ANH-Branch: master $:$ANH-Revision: 1.40 $ */
2 /* Copyright (C) 2001 by Alex Kompel */
3 /* aNetHack may be freely redistributed. See license for details. */
5 #include "winMS.h"
6 #include "mhmap.h"
7 #include "mhmsg.h"
8 #include "mhinput.h"
9 #include "mhfont.h"
11 #include "patchlevel.h"
13 #define NHMAP_FONT_NAME TEXT("Terminal")
14 #define MAXWINDOWTEXT 255
16 extern short glyph2tile[];
18 /* map window data */
19 typedef struct mswin_anethack_map_window {
20 int map[COLNO][ROWNO]; /* glyph map */
22 int mapMode; /* current map mode */
23 boolean bAsciiMode; /* switch ASCII/tiled mode */
24 boolean bFitToScreenMode; /* switch Fit map to screen mode on/off */
25 int xPos, yPos; /* scroll position */
26 int xPageSize, yPageSize; /* scroll page size */
27 int xCur, yCur; /* position of the cursor */
28 int xScrTile, yScrTile; /* size of display tile */
29 POINT map_orig; /* map origin point */
30 HFONT hMapFont; /* font for ASCII mode */
31 int xLastMouseClick, yLastMouseClick; /* last mouse click */
32 } NHMapWindow, *PNHMapWindow;
34 static TCHAR szNHMapWindowClass[] = TEXT("MSNethackMapWndClass");
35 LRESULT CALLBACK MapWndProc(HWND, UINT, WPARAM, LPARAM);
36 static void register_map_window_class(void);
37 static void onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam);
38 static void onMSNH_VScroll(HWND hWnd, WPARAM wParam, LPARAM lParam);
39 static void onMSNH_HScroll(HWND hWnd, WPARAM wParam, LPARAM lParam);
40 static void onPaint(HWND hWnd);
41 static void onCreate(HWND hWnd, WPARAM wParam, LPARAM lParam);
42 static void nhcoord2display(PNHMapWindow data, int x, int y, LPRECT lpOut);
43 #if (VERSION_MAJOR < 4) && (VERSION_MINOR < 4) && (PATCHLEVEL < 2)
44 static void nhglyph2charcolor(short glyph, uchar *ch, int *color);
45 #endif
46 static COLORREF nhcolor_to_RGB(int c);
48 HWND
49 mswin_init_map_window()
51 static int run_once = 0;
52 HWND ret;
53 DWORD styles;
55 if (!run_once) {
56 register_map_window_class();
57 run_once = 1;
60 styles = WS_CHILD | WS_CLIPSIBLINGS;
61 if (!GetNHApp()->bHideScrollBars)
62 styles |= WS_HSCROLL | WS_VSCROLL;
63 ret = CreateWindow(
64 szNHMapWindowClass, /* registered class name */
65 NULL, /* window name */
66 styles, /* window style */
67 0, /* horizontal position of window - set it later */
68 0, /* vertical position of window - set it later */
69 0, /* window width - set it later */
70 0, /* window height - set it later*/
71 GetNHApp()->hMainWnd, /* handle to parent or owner window */
72 NULL, /* menu handle or child identifier */
73 GetNHApp()->hApp, /* handle to application instance */
74 NULL); /* window-creation data */
75 if (!ret) {
76 panic("Cannot create map window");
78 return ret;
81 void
82 mswin_map_stretch(HWND hWnd, LPSIZE lpsz, BOOL redraw)
84 PNHMapWindow data;
85 RECT client_rt;
86 SCROLLINFO si;
87 SIZE wnd_size;
88 LOGFONT lgfnt;
90 /* check arguments */
91 if (!IsWindow(hWnd) || !lpsz || lpsz->cx <= 0 || lpsz->cy <= 0)
92 return;
94 /* calculate window size */
95 GetClientRect(hWnd, &client_rt);
96 wnd_size.cx = client_rt.right - client_rt.left;
97 wnd_size.cy = client_rt.bottom - client_rt.top;
99 /* set new screen tile size */
100 data = (PNHMapWindow) GetWindowLong(hWnd, GWL_USERDATA);
101 data->xScrTile =
102 max(1, (data->bFitToScreenMode ? wnd_size.cx : lpsz->cx) / COLNO);
103 data->yScrTile =
104 max(1, (data->bFitToScreenMode ? wnd_size.cy : lpsz->cy) / ROWNO);
106 /* set map origin point */
107 data->map_orig.x =
108 max(0, client_rt.left + (wnd_size.cx - data->xScrTile * COLNO) / 2);
109 data->map_orig.y =
110 max(0, client_rt.top + (wnd_size.cy - data->yScrTile * ROWNO) / 2);
112 data->map_orig.x -= data->map_orig.x % data->xScrTile;
113 data->map_orig.y -= data->map_orig.y % data->yScrTile;
115 /* adjust horizontal scroll bar */
116 if (data->bFitToScreenMode)
117 data->xPageSize = COLNO + 1; /* disable scroll bar */
118 else
119 data->xPageSize = wnd_size.cx / data->xScrTile;
121 if (data->xPageSize >= COLNO) {
122 data->xPos = 0;
123 GetNHApp()->bNoHScroll = TRUE;
124 } else {
125 GetNHApp()->bNoHScroll = FALSE;
126 data->xPos = max(
127 0, min(COLNO - data->xPageSize + 1, u.ux - data->xPageSize / 2));
130 if (!GetNHApp()->bHideScrollBars) {
131 si.cbSize = sizeof(si);
132 si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
133 si.nMin = 0;
134 si.nMax = COLNO;
135 si.nPage = data->xPageSize;
136 si.nPos = data->xPos;
137 SetScrollInfo(hWnd, SB_HORZ, &si, TRUE);
140 /* adjust vertical scroll bar */
141 if (data->bFitToScreenMode)
142 data->yPageSize = ROWNO + 1; /* disable scroll bar */
143 else
144 data->yPageSize = wnd_size.cy / data->yScrTile;
146 if (data->yPageSize >= ROWNO) {
147 data->yPos = 0;
148 GetNHApp()->bNoVScroll = TRUE;
149 } else {
150 GetNHApp()->bNoVScroll = FALSE;
151 data->yPos = max(
152 0, min(ROWNO - data->yPageSize + 1, u.uy - data->yPageSize / 2));
155 if (!GetNHApp()->bHideScrollBars) {
156 si.cbSize = sizeof(si);
157 si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
158 si.nMin = 0;
159 si.nMax = ROWNO;
160 si.nPage = data->yPageSize;
161 si.nPos = data->yPos;
162 SetScrollInfo(hWnd, SB_VERT, &si, TRUE);
165 /* create font */
166 if (data->hMapFont)
167 DeleteObject(data->hMapFont);
168 ZeroMemory(&lgfnt, sizeof(lgfnt));
169 lgfnt.lfHeight = -data->yScrTile; // height of font
170 lgfnt.lfWidth = -data->xScrTile; // average character width
171 lgfnt.lfEscapement = 0; // angle of escapement
172 lgfnt.lfOrientation = 0; // base-line orientation angle
173 lgfnt.lfWeight = FW_NORMAL; // font weight
174 lgfnt.lfItalic = FALSE; // italic attribute option
175 lgfnt.lfUnderline = FALSE; // underline attribute option
176 lgfnt.lfStrikeOut = FALSE; // strikeout attribute option
177 lgfnt.lfCharSet = mswin_charset(); // character set identifier
178 lgfnt.lfOutPrecision = OUT_DEFAULT_PRECIS; // output precision
179 lgfnt.lfClipPrecision = CLIP_DEFAULT_PRECIS; // clipping precision
180 lgfnt.lfQuality = DEFAULT_QUALITY; // output quality
181 if (iflags.wc_font_map && *iflags.wc_font_map) {
182 lgfnt.lfPitchAndFamily = DEFAULT_PITCH; // pitch and family
183 NH_A2W(iflags.wc_font_map, lgfnt.lfFaceName, LF_FACESIZE);
184 } else {
185 lgfnt.lfPitchAndFamily = FIXED_PITCH; // pitch and family
186 _tcsncpy(lgfnt.lfFaceName, NHMAP_FONT_NAME, LF_FACESIZE);
188 data->hMapFont = CreateFontIndirect(&lgfnt);
190 mswin_cliparound(data->xCur, data->yCur);
192 if (redraw)
193 InvalidateRect(hWnd, NULL, TRUE);
196 /* set map mode */
198 mswin_map_mode(HWND hWnd, int mode)
200 PNHMapWindow data;
201 int oldMode;
202 SIZE mapSize;
204 data = (PNHMapWindow) GetWindowLong(hWnd, GWL_USERDATA);
205 if (mode == data->mapMode)
206 return mode;
208 oldMode = data->mapMode;
209 data->mapMode = mode;
211 switch (data->mapMode) {
212 case MAP_MODE_ASCII4x6:
213 data->bAsciiMode = TRUE;
214 data->bFitToScreenMode = FALSE;
215 mapSize.cx = 4 * COLNO;
216 mapSize.cy = 6 * ROWNO;
217 break;
219 case MAP_MODE_ASCII6x8:
220 data->bAsciiMode = TRUE;
221 data->bFitToScreenMode = FALSE;
222 mapSize.cx = 6 * COLNO;
223 mapSize.cy = 8 * ROWNO;
224 break;
226 case MAP_MODE_ASCII8x8:
227 data->bAsciiMode = TRUE;
228 data->bFitToScreenMode = FALSE;
229 mapSize.cx = 8 * COLNO;
230 mapSize.cy = 8 * ROWNO;
231 break;
233 case MAP_MODE_ASCII16x8:
234 data->bAsciiMode = TRUE;
235 data->bFitToScreenMode = FALSE;
236 mapSize.cx = 16 * COLNO;
237 mapSize.cy = 8 * ROWNO;
238 break;
240 case MAP_MODE_ASCII7x12:
241 data->bAsciiMode = TRUE;
242 data->bFitToScreenMode = FALSE;
243 mapSize.cx = 7 * COLNO;
244 mapSize.cy = 12 * ROWNO;
245 break;
247 case MAP_MODE_ASCII8x12:
248 data->bAsciiMode = TRUE;
249 data->bFitToScreenMode = FALSE;
250 mapSize.cx = 8 * COLNO;
251 mapSize.cy = 12 * ROWNO;
252 break;
254 case MAP_MODE_ASCII16x12:
255 data->bAsciiMode = TRUE;
256 data->bFitToScreenMode = FALSE;
257 mapSize.cx = 16 * COLNO;
258 mapSize.cy = 12 * ROWNO;
259 break;
261 case MAP_MODE_ASCII12x16:
262 data->bAsciiMode = TRUE;
263 data->bFitToScreenMode = FALSE;
264 mapSize.cx = 12 * COLNO;
265 mapSize.cy = 16 * ROWNO;
266 break;
268 case MAP_MODE_ASCII10x18:
269 data->bAsciiMode = TRUE;
270 data->bFitToScreenMode = FALSE;
271 mapSize.cx = 10 * COLNO;
272 mapSize.cy = 18 * ROWNO;
273 break;
275 case MAP_MODE_ASCII_FIT_TO_SCREEN: {
276 RECT client_rt;
277 GetClientRect(hWnd, &client_rt);
278 mapSize.cx = client_rt.right - client_rt.left;
279 mapSize.cy = client_rt.bottom - client_rt.top;
281 data->bAsciiMode = TRUE;
282 data->bFitToScreenMode = TRUE;
283 } break;
285 case MAP_MODE_TILES_FIT_TO_SCREEN: {
286 RECT client_rt;
287 GetClientRect(hWnd, &client_rt);
288 mapSize.cx = client_rt.right - client_rt.left;
289 mapSize.cy = client_rt.bottom - client_rt.top;
291 data->bAsciiMode = FALSE;
292 data->bFitToScreenMode = TRUE;
293 } break;
295 case MAP_MODE_TILES:
296 default:
297 data->bAsciiMode = FALSE;
298 data->bFitToScreenMode = FALSE;
299 mapSize.cx = GetNHApp()->mapTile_X * COLNO;
300 mapSize.cy = GetNHApp()->mapTile_Y * ROWNO;
301 break;
304 mswin_map_stretch(hWnd, &mapSize, TRUE);
306 return oldMode;
309 /* retrieve cursor position */
310 void
311 mswin_map_get_cursor(HWND hWnd, int *x, int *y)
313 PNHMapWindow data;
315 data = (PNHMapWindow) GetWindowLong(hWnd, GWL_USERDATA);
316 if (!data)
317 panic("mswin_map_get_cursor: no window data");
318 if (x)
319 *x = data->xCur;
320 if (y)
321 *y = data->yCur;
324 /* register window class for map window */
325 void
326 register_map_window_class()
328 WNDCLASS wcex;
329 ZeroMemory(&wcex, sizeof(wcex));
331 /* window class */
332 wcex.style = CS_NOCLOSE | CS_DBLCLKS;
333 wcex.lpfnWndProc = (WNDPROC) MapWndProc;
334 wcex.cbClsExtra = 0;
335 wcex.cbWndExtra = 0;
336 wcex.hInstance = GetNHApp()->hApp;
337 wcex.hIcon = NULL;
338 wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
339 wcex.hbrBackground =
340 CreateSolidBrush(RGB(0, 0, 0)); /* set backgroup here */
341 wcex.lpszMenuName = NULL;
342 wcex.lpszClassName = szNHMapWindowClass;
344 if (!RegisterClass(&wcex)) {
345 panic("cannot register Map window class");
349 /* map window procedure */
350 LRESULT CALLBACK
351 MapWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
353 PNHMapWindow data;
354 int x, y;
356 data = (PNHMapWindow) GetWindowLong(hWnd, GWL_USERDATA);
357 switch (message) {
358 case WM_CREATE:
359 onCreate(hWnd, wParam, lParam);
360 break;
362 case WM_MSNH_COMMAND:
363 onMSNHCommand(hWnd, wParam, lParam);
364 break;
366 case WM_PAINT:
367 onPaint(hWnd);
368 break;
370 case WM_SETFOCUS:
371 /* transfer focus back to the main window */
372 SetFocus(GetNHApp()->hMainWnd);
373 break;
375 case WM_HSCROLL:
376 onMSNH_HScroll(hWnd, wParam, lParam);
377 break;
379 case WM_VSCROLL:
380 onMSNH_VScroll(hWnd, wParam, lParam);
381 break;
383 case WM_SIZE: {
384 SIZE size;
386 if (data->bFitToScreenMode) {
387 size.cx = LOWORD(lParam);
388 size.cy = HIWORD(lParam);
389 } else {
390 /* mapping factor is unchaged we just need to adjust scroll bars
392 size.cx = data->xScrTile * COLNO;
393 size.cy = data->yScrTile * ROWNO;
395 mswin_map_stretch(hWnd, &size, TRUE);
396 } break;
398 case WM_LBUTTONDOWN:
399 x = max(0, min(COLNO, data->xPos
400 + (LOWORD(lParam) - data->map_orig.x)
401 / data->xScrTile));
402 y = max(0, min(ROWNO, data->yPos
403 + (HIWORD(lParam) - data->map_orig.y)
404 / data->yScrTile));
406 NHEVENT_MS(CLICK_1, x, y);
408 data->xLastMouseClick = x;
409 data->yLastMouseClick = y;
410 return 0;
412 case WM_LBUTTONDBLCLK:
413 x = max(0, min(COLNO, data->xPos
414 + (LOWORD(lParam) - data->map_orig.x)
415 / data->xScrTile));
416 y = max(0, min(ROWNO, data->yPos
417 + (HIWORD(lParam) - data->map_orig.y)
418 / data->yScrTile));
420 /* if map has scrolled since the last mouse click - ignore
421 * double-click message */
422 if (data->xLastMouseClick == x && data->yLastMouseClick == y) {
423 NHEVENT_MS(CLICK_1, x, y);
425 return 0;
427 case WM_DESTROY:
428 if (data->hMapFont)
429 DeleteObject(data->hMapFont);
430 free(data);
431 SetWindowLong(hWnd, GWL_USERDATA, (LONG) 0);
432 break;
434 default:
435 return DefWindowProc(hWnd, message, wParam, lParam);
437 return 0;
440 /* on WM_COMMAND */
441 void
442 onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
444 PNHMapWindow data;
445 RECT rt;
447 data = (PNHMapWindow) GetWindowLong(hWnd, GWL_USERDATA);
448 switch (wParam) {
449 case MSNH_MSG_PRINT_GLYPH: {
450 PMSNHMsgPrintGlyph msg_data = (PMSNHMsgPrintGlyph) lParam;
451 data->map[msg_data->x][msg_data->y] = msg_data->glyph;
453 /* invalidate the update area */
454 nhcoord2display(data, msg_data->x, msg_data->y, &rt);
455 InvalidateRect(hWnd, &rt, TRUE);
456 } break;
458 case MSNH_MSG_CLIPAROUND: {
459 PMSNHMsgClipAround msg_data = (PMSNHMsgClipAround) lParam;
460 int x, y;
461 BOOL scroll_x, scroll_y;
462 int mcam = iflags.wc_scroll_margin;
464 /* calculate if you should clip around */
465 scroll_x =
466 !GetNHApp()->bNoHScroll
467 && (msg_data->x < (data->xPos + mcam)
468 || msg_data->x > (data->xPos + data->xPageSize - mcam));
469 scroll_y =
470 !GetNHApp()->bNoVScroll
471 && (msg_data->y < (data->yPos + mcam)
472 || msg_data->y > (data->yPos + data->yPageSize - mcam));
474 mcam += iflags.wc_scroll_amount - 1;
475 /* get page size and center horizontally on x-position */
476 if (scroll_x) {
477 if (data->xPageSize <= 2 * mcam) {
478 x = max(0, min(COLNO, msg_data->x - data->xPageSize / 2));
479 } else if (msg_data->x < data->xPos + data->xPageSize / 2) {
480 x = max(0, min(COLNO, msg_data->x - mcam));
481 } else {
482 x = max(0, min(COLNO, msg_data->x - data->xPageSize + mcam));
484 SendMessage(hWnd, WM_HSCROLL, (WPARAM) MAKELONG(SB_THUMBTRACK, x),
485 (LPARAM) NULL);
488 /* get page size and center vertically on y-position */
489 if (scroll_y) {
490 if (data->yPageSize <= 2 * mcam) {
491 y = max(0, min(ROWNO, msg_data->y - data->yPageSize / 2));
492 } else if (msg_data->y < data->yPos + data->yPageSize / 2) {
493 y = max(0, min(ROWNO, msg_data->y - mcam));
494 } else {
495 y = max(0, min(ROWNO, msg_data->y - data->yPageSize + mcam));
497 SendMessage(hWnd, WM_VSCROLL, (WPARAM) MAKELONG(SB_THUMBTRACK, y),
498 (LPARAM) NULL);
500 } break;
502 case MSNH_MSG_CLEAR_WINDOW: {
503 int i, j;
504 for (i = 0; i < COLNO; i++)
505 for (j = 0; j < ROWNO; j++) {
506 data->map[i][j] = -1;
508 InvalidateRect(hWnd, NULL, TRUE);
509 } break;
511 case MSNH_MSG_CURSOR: {
512 PMSNHMsgCursor msg_data = (PMSNHMsgCursor) lParam;
513 HDC hdc;
514 RECT rt;
516 /* move focus rectangle at the cursor postion */
517 hdc = GetDC(hWnd);
519 nhcoord2display(data, data->xCur, data->yCur, &rt);
520 if (data->bAsciiMode) {
521 PatBlt(hdc, rt.left, rt.top, rt.right - rt.left,
522 rt.bottom - rt.top, DSTINVERT);
523 } else {
524 DrawFocusRect(hdc, &rt);
527 data->xCur = msg_data->x;
528 data->yCur = msg_data->y;
530 nhcoord2display(data, data->xCur, data->yCur, &rt);
531 if (data->bAsciiMode) {
532 PatBlt(hdc, rt.left, rt.top, rt.right - rt.left,
533 rt.bottom - rt.top, DSTINVERT);
534 } else {
535 DrawFocusRect(hdc, &rt);
538 ReleaseDC(hWnd, hdc);
539 } break;
543 /* on WM_CREATE */
544 void
545 onCreate(HWND hWnd, WPARAM wParam, LPARAM lParam)
547 PNHMapWindow data;
548 int i, j;
550 /* set window data */
551 data = (PNHMapWindow) malloc(sizeof(NHMapWindow));
552 if (!data)
553 panic("out of memory");
555 ZeroMemory(data, sizeof(NHMapWindow));
556 for (i = 0; i < COLNO; i++)
557 for (j = 0; j < ROWNO; j++) {
558 data->map[i][j] = -1;
561 data->bAsciiMode = FALSE;
563 data->xScrTile = GetNHApp()->mapTile_X;
564 data->yScrTile = GetNHApp()->mapTile_Y;
566 data->xLastMouseClick = data->yLastMouseClick = -1;
568 SetWindowLong(hWnd, GWL_USERDATA, (LONG) data);
571 /* on WM_PAINT */
572 void
573 onPaint(HWND hWnd)
575 PNHMapWindow data;
576 PAINTSTRUCT ps;
577 HDC hDC;
578 HDC tileDC;
579 HGDIOBJ saveBmp;
580 RECT paint_rt;
581 int i, j;
583 /* get window data */
584 data = (PNHMapWindow) GetWindowLong(hWnd, GWL_USERDATA);
586 hDC = BeginPaint(hWnd, &ps);
588 /* calculate paint rectangle */
589 if (!IsRectEmpty(&ps.rcPaint)) {
590 /* calculate paint rectangle */
591 paint_rt.left =
592 max(data->xPos
593 + (ps.rcPaint.left - data->map_orig.x) / data->xScrTile,
595 paint_rt.top = max(
596 data->yPos + (ps.rcPaint.top - data->map_orig.y) / data->yScrTile,
598 paint_rt.right = min(
599 data->xPos
600 + (ps.rcPaint.right - data->map_orig.x) / data->xScrTile + 1,
601 COLNO);
602 paint_rt.bottom = min(
603 data->yPos
604 + (ps.rcPaint.bottom - data->map_orig.y) / data->yScrTile + 1,
605 ROWNO);
607 if (data->bAsciiMode || Is_rogue_level(&u.uz)) {
608 /* You enter a VERY primitive world! */
609 HGDIOBJ oldFont;
611 oldFont = SelectObject(hDC, data->hMapFont);
612 SetBkMode(hDC, TRANSPARENT);
614 /* draw the map */
615 for (i = paint_rt.left; i < paint_rt.right; i++)
616 for (j = paint_rt.top; j < paint_rt.bottom; j++)
617 if (data->map[i][j] >= 0) {
618 char ch;
619 TCHAR wch;
620 RECT glyph_rect;
621 int color;
622 unsigned special;
623 int mgch;
624 HBRUSH back_brush;
625 COLORREF OldFg;
627 nhcoord2display(data, i, j, &glyph_rect);
629 #if (VERSION_MAJOR < 4) && (VERSION_MINOR < 4) && (PATCHLEVEL < 2)
630 nhglyph2charcolor(data->map[i][j], &ch, &color);
631 OldFg = SetTextColor(hDC, nhcolor_to_RGB(color));
632 #else
633 /* rely on aNetHack core helper routine */
634 (void) mapglyph(data->map[i][j], &mgch, &color,
635 &special, i, j);
636 ch = (char) mgch;
637 if (((special & MG_PET) && iflags.hilite_pet)
638 || ((special & MG_DETECT)
639 && iflags.use_inverse)) {
640 back_brush =
641 CreateSolidBrush(nhcolor_to_RGB(CLR_GRAY));
642 FillRect(hDC, &glyph_rect, back_brush);
643 DeleteObject(back_brush);
644 switch (color) {
645 case CLR_GRAY:
646 case CLR_WHITE:
647 OldFg = SetTextColor(
648 hDC, nhcolor_to_RGB(CLR_BLACK));
649 break;
650 default:
651 OldFg =
652 SetTextColor(hDC, nhcolor_to_RGB(color));
654 } else {
655 OldFg = SetTextColor(hDC, nhcolor_to_RGB(color));
657 #endif
659 DrawText(hDC, NH_A2W(&ch, &wch, 1), 1, &glyph_rect,
660 DT_CENTER | DT_VCENTER | DT_NOPREFIX);
661 SetTextColor(hDC, OldFg);
663 SelectObject(hDC, oldFont);
664 } else {
665 /* prepare tiles DC for mapping */
666 tileDC = CreateCompatibleDC(hDC);
667 saveBmp = SelectObject(tileDC, GetNHApp()->bmpMapTiles);
669 /* draw the map */
670 for (i = paint_rt.left; i < paint_rt.right; i++)
671 for (j = paint_rt.top; j < paint_rt.bottom; j++)
672 if (data->map[i][j] >= 0) {
673 short ntile;
674 int t_x, t_y;
675 RECT glyph_rect;
677 ntile = glyph2tile[data->map[i][j]];
678 t_x = (ntile % GetNHApp()->mapTilesPerLine)
679 * GetNHApp()->mapTile_X;
680 t_y = (ntile / GetNHApp()->mapTilesPerLine)
681 * GetNHApp()->mapTile_Y;
683 nhcoord2display(data, i, j, &glyph_rect);
685 StretchBlt(hDC, glyph_rect.left, glyph_rect.top,
686 data->xScrTile, data->yScrTile, tileDC,
687 t_x, t_y, GetNHApp()->mapTile_X,
688 GetNHApp()->mapTile_Y, SRCCOPY);
689 if (glyph_is_pet(data->map[i][j])
690 && iflags.wc_hilite_pet) {
691 /* apply pet mark transparently over
692 pet image */
693 HDC hdcPetMark;
694 HBITMAP bmPetMarkOld;
696 /* this is DC for petmark bitmap */
697 hdcPetMark = CreateCompatibleDC(hDC);
698 bmPetMarkOld = SelectObject(
699 hdcPetMark, GetNHApp()->bmpPetMark);
701 nhapply_image_transparent(
702 hDC, glyph_rect.left, glyph_rect.top,
703 data->xScrTile, data->yScrTile, hdcPetMark, 0,
704 0, TILE_X, TILE_Y, TILE_BK_COLOR);
705 SelectObject(hdcPetMark, bmPetMarkOld);
706 DeleteDC(hdcPetMark);
709 SelectObject(tileDC, saveBmp);
710 DeleteDC(tileDC);
713 /* draw focus rect */
714 nhcoord2display(data, data->xCur, data->yCur, &paint_rt);
715 if (data->bAsciiMode) {
716 PatBlt(hDC, paint_rt.left, paint_rt.top,
717 paint_rt.right - paint_rt.left,
718 paint_rt.bottom - paint_rt.top, DSTINVERT);
719 } else {
720 DrawFocusRect(hDC, &paint_rt);
723 EndPaint(hWnd, &ps);
726 /* on WM_VSCROLL */
727 void
728 onMSNH_VScroll(HWND hWnd, WPARAM wParam, LPARAM lParam)
730 PNHMapWindow data;
731 SCROLLINFO si;
732 int yNewPos;
733 int yDelta;
735 /* get window data */
736 data = (PNHMapWindow) GetWindowLong(hWnd, GWL_USERDATA);
738 switch (LOWORD(wParam)) {
739 /* User clicked shaft left of the scroll box. */
740 case SB_PAGEUP:
741 yNewPos = data->yPos - data->yPageSize;
742 break;
744 /* User clicked shaft right of the scroll box. */
745 case SB_PAGEDOWN:
746 yNewPos = data->yPos + data->yPageSize;
747 break;
749 /* User clicked the left arrow. */
750 case SB_LINEUP:
751 yNewPos = data->yPos - 1;
752 break;
754 /* User clicked the right arrow. */
755 case SB_LINEDOWN:
756 yNewPos = data->yPos + 1;
757 break;
759 /* User dragged the scroll box. */
760 case SB_THUMBTRACK:
761 yNewPos = HIWORD(wParam);
762 break;
764 default:
765 yNewPos = data->yPos;
768 yNewPos = max(0, min(ROWNO - data->yPageSize + 1, yNewPos));
769 if (yNewPos == data->yPos)
770 return;
772 yDelta = yNewPos - data->yPos;
773 data->yPos = yNewPos;
775 ScrollWindowEx(hWnd, 0, -data->yScrTile * yDelta, (CONST RECT *) NULL,
776 (CONST RECT *) NULL, (HRGN) NULL, (LPRECT) NULL,
777 SW_INVALIDATE | SW_ERASE);
779 if (!GetNHApp()->bHideScrollBars) {
780 si.cbSize = sizeof(si);
781 si.fMask = SIF_POS;
782 si.nPos = data->yPos;
783 SetScrollInfo(hWnd, SB_VERT, &si, TRUE);
787 /* on WM_HSCROLL */
788 void
789 onMSNH_HScroll(HWND hWnd, WPARAM wParam, LPARAM lParam)
791 PNHMapWindow data;
792 SCROLLINFO si;
793 int xNewPos;
794 int xDelta;
796 /* get window data */
797 data = (PNHMapWindow) GetWindowLong(hWnd, GWL_USERDATA);
799 switch (LOWORD(wParam)) {
800 /* User clicked shaft left of the scroll box. */
801 case SB_PAGEUP:
802 xNewPos = data->xPos - data->xPageSize;
803 break;
805 /* User clicked shaft right of the scroll box. */
806 case SB_PAGEDOWN:
807 xNewPos = data->xPos + data->xPageSize;
808 break;
810 /* User clicked the left arrow. */
811 case SB_LINEUP:
812 xNewPos = data->xPos - 1;
813 break;
815 /* User clicked the right arrow. */
816 case SB_LINEDOWN:
817 xNewPos = data->xPos + 1;
818 break;
820 /* User dragged the scroll box. */
821 case SB_THUMBTRACK:
822 xNewPos = HIWORD(wParam);
823 break;
825 default:
826 xNewPos = data->xPos;
829 xNewPos = max(0, min(COLNO - data->xPageSize + 1, xNewPos));
830 if (xNewPos == data->xPos)
831 return;
833 xDelta = xNewPos - data->xPos;
834 data->xPos = xNewPos;
836 ScrollWindowEx(hWnd, -data->xScrTile * xDelta, 0, (CONST RECT *) NULL,
837 (CONST RECT *) NULL, (HRGN) NULL, (LPRECT) NULL,
838 SW_INVALIDATE | SW_ERASE);
840 if (!GetNHApp()->bHideScrollBars) {
841 si.cbSize = sizeof(si);
842 si.fMask = SIF_POS;
843 si.nPos = data->xPos;
844 SetScrollInfo(hWnd, SB_HORZ, &si, TRUE);
848 /* map anethack map coordinates to the screen location */
849 void
850 nhcoord2display(PNHMapWindow data, int x, int y, LPRECT lpOut)
852 lpOut->left = (x - data->xPos) * data->xScrTile + data->map_orig.x;
853 lpOut->top = (y - data->yPos) * data->yScrTile + data->map_orig.y;
854 lpOut->right = lpOut->left + data->xScrTile;
855 lpOut->bottom = lpOut->top + data->yScrTile;
858 #if (VERSION_MAJOR < 4) && (VERSION_MINOR < 4) && (PATCHLEVEL < 2)
859 /* map glyph to character/color combination */
860 void
861 nhglyph2charcolor(short g, uchar *ch, int *color)
863 int offset;
864 #ifdef TEXTCOLOR
866 #define zap_color(n) *color = iflags.use_color ? zapcolors[n] : NO_COLOR
867 #define cmap_color(n) *color = iflags.use_color ? defsyms[n].color : NO_COLOR
868 #define obj_color(n) \
869 *color = iflags.use_color ? objects[n].oc_color : NO_COLOR
870 #define mon_color(n) *color = iflags.use_color ? mons[n].mcolor : NO_COLOR
871 #define pet_color(n) *color = iflags.use_color ? mons[n].mcolor : NO_COLOR
872 #define warn_color(n) \
873 *color = iflags.use_color ? def_warnsyms[n].color : NO_COLOR
875 #else /* no text color */
877 #define zap_color(n)
878 #define cmap_color(n)
879 #define obj_color(n)
880 #define mon_color(n)
881 #define pet_color(c)
882 #define warn_color(c)
883 *color = CLR_WHITE;
884 #endif
886 if ((offset = (g - GLYPH_WARNING_OFF)) >= 0) { /* a warning flash */
887 *ch = showsyms[offset + SYM_OFF_W];
888 warn_color(offset);
889 } else if ((offset = (g - GLYPH_SWALLOW_OFF)) >= 0) { /* swallow */
890 /* see swallow_to_glyph() in display.c */
891 *ch = (uchar) showsyms[(S_sw_tl + (offset & 0x7)) + SYM_OFF_P];
892 mon_color(offset >> 3);
893 } else if ((offset = (g - GLYPH_ZAP_OFF)) >= 0) { /* zap beam */
894 /* see zapdir_to_glyph() in display.c */
895 *ch = showsyms[(S_vbeam + (offset & 0x3)) + SYM_OFF_P];
896 zap_color((offset >> 2));
897 } else if ((offset = (g - GLYPH_CMAP_OFF)) >= 0) { /* cmap */
898 *ch = showsyms[offset + SYM_OFF_P];
899 cmap_color(offset);
900 } else if ((offset = (g - GLYPH_OBJ_OFF)) >= 0) { /* object */
901 *ch = showsyms[(int) objects[offset].oc_class + SYM_OFF_O];
902 obj_color(offset);
903 } else if ((offset = (g - GLYPH_BODY_OFF)) >= 0) { /* a corpse */
904 *ch = showsyms[(int) objects[CORPSE].oc_class + SYM_OFF_O];
905 mon_color(offset);
906 } else if ((offset = (g - GLYPH_PET_OFF)) >= 0) { /* a pet */
907 *ch = showsyms[(int) mons[offset].mlet + SYM_OFF_M];
908 pet_color(offset);
909 } else { /* a monster */
910 *ch = showsyms[(int) mons[g].mlet + SYM_OFF_M];
911 mon_color(g);
913 // end of wintty code
915 #endif
917 /* map anethack color to RGB */
918 COLORREF
919 nhcolor_to_RGB(int c)
921 switch (c) {
922 case CLR_BLACK:
923 return RGB(0x55, 0x55, 0x55);
924 case CLR_RED:
925 return RGB(0xFF, 0x00, 0x00);
926 case CLR_GREEN:
927 return RGB(0x00, 0x80, 0x00);
928 case CLR_BROWN:
929 return RGB(0xA5, 0x2A, 0x2A);
930 case CLR_BLUE:
931 return RGB(0x00, 0x00, 0xFF);
932 case CLR_MAGENTA:
933 return RGB(0xFF, 0x00, 0xFF);
934 case CLR_CYAN:
935 return RGB(0x00, 0xFF, 0xFF);
936 case CLR_GRAY:
937 return RGB(0xC0, 0xC0, 0xC0);
938 case NO_COLOR:
939 return RGB(0xFF, 0xFF, 0xFF);
940 case CLR_ORANGE:
941 return RGB(0xFF, 0xA5, 0x00);
942 case CLR_BRIGHT_GREEN:
943 return RGB(0x00, 0xFF, 0x00);
944 case CLR_YELLOW:
945 return RGB(0xFF, 0xFF, 0x00);
946 case CLR_BRIGHT_BLUE:
947 return RGB(0x00, 0xC0, 0xFF);
948 case CLR_BRIGHT_MAGENTA:
949 return RGB(0xFF, 0x80, 0xFF);
950 case CLR_BRIGHT_CYAN:
951 return RGB(0x80, 0xFF, 0xFF); /* something close to aquamarine */
952 case CLR_WHITE:
953 return RGB(0xFF, 0xFF, 0xFF);
954 default:
955 return RGB(0x00, 0x00, 0x00); /* black */
959 /* apply bitmap pointed by sourceDc transparently over
960 bitmap pointed by hDC */
961 void
962 nhapply_image_transparent(HDC hDC, int x, int y, int width, int height,
963 HDC sourceDC, int s_x, int s_y, int s_width,
964 int s_height, COLORREF cTransparent)
966 TransparentImage(hDC, x, y, width, height, sourceDC, s_x, s_y, s_width,
967 s_height, cTransparent);