1 /* aNetHack 0.0.1 mhmap.c $ANH-Date: 1435002695 2015/06/22 19:51:35 $ $ANH-Branch: master $:$ANH-Revision: 1.56 $ */
2 /* Copyright (C) 2001 by Alex Kompel */
3 /* aNetHack may be freely redistributed. See license for details. */
13 #include "patchlevel.h"
15 #define NHMAP_FONT_NAME TEXT("Terminal")
16 #define MAXWINDOWTEXT 255
18 extern short glyph2tile
[];
20 #define TILEBMP_X(ntile) ((ntile % GetNHApp()->mapTilesPerLine) * GetNHApp()->mapTile_X)
21 #define TILEBMP_Y(ntile) ((ntile / GetNHApp()->mapTilesPerLine) * GetNHApp()->mapTile_Y)
24 typedef struct mswin_anethack_map_window
{
25 int map
[COLNO
][ROWNO
]; /* glyph map */
26 int bkmap
[COLNO
][ROWNO
]; /* backround glyph map */
28 int mapMode
; /* current map mode */
29 boolean bAsciiMode
; /* switch ASCII/tiled mode */
30 boolean bFitToScreenMode
; /* switch Fit map to screen mode on/off */
31 int xPos
, yPos
; /* scroll position */
32 int xPageSize
, yPageSize
; /* scroll page size */
33 int xCur
, yCur
; /* position of the cursor */
34 int xScrTile
, yScrTile
; /* size of display tile */
35 POINT map_orig
; /* map origin point */
37 HFONT hMapFont
; /* font for ASCII mode */
38 } NHMapWindow
, *PNHMapWindow
;
40 static TCHAR szNHMapWindowClass
[] = TEXT("MSNethackMapWndClass");
41 LRESULT CALLBACK
MapWndProc(HWND
, UINT
, WPARAM
, LPARAM
);
42 static void register_map_window_class(void);
43 static void onMSNHCommand(HWND hWnd
, WPARAM wParam
, LPARAM lParam
);
44 static void onMSNH_VScroll(HWND hWnd
, WPARAM wParam
, LPARAM lParam
);
45 static void onMSNH_HScroll(HWND hWnd
, WPARAM wParam
, LPARAM lParam
);
46 static void onPaint(HWND hWnd
);
47 static void onCreate(HWND hWnd
, WPARAM wParam
, LPARAM lParam
);
48 static void nhcoord2display(PNHMapWindow data
, int x
, int y
, LPRECT lpOut
);
49 #if (VERSION_MAJOR < 4) && (VERSION_MINOR < 4) && (PATCHLEVEL < 2)
50 static void nhglyph2charcolor(short glyph
, uchar
*ch
, int *color
);
54 mswin_init_map_window()
56 static int run_once
= 0;
61 register_map_window_class();
65 /* get window position */
66 if (GetNHApp()->bAutoLayout
) {
67 SetRect(&rt
, 0, 0, 0, 0);
69 mswin_get_window_placement(NHW_MAP
, &rt
);
72 /* create map window object */
74 szNHMapWindowClass
, /* registered class name */
75 NULL
, /* window name */
76 WS_CHILD
| WS_HSCROLL
| WS_VSCROLL
| WS_CLIPSIBLINGS
77 | WS_SIZEBOX
, /* window style */
78 rt
.left
, /* horizontal position of window */
79 rt
.top
, /* vertical position of window */
80 rt
.right
- rt
.left
, /* window width */
81 rt
.bottom
- rt
.top
, /* window height */
82 GetNHApp()->hMainWnd
, /* handle to parent or owner window */
83 NULL
, /* menu handle or child identifier */
84 GetNHApp()->hApp
, /* handle to application instance */
85 NULL
); /* window-creation data */
87 panic("Cannot create map window");
90 /* Set window caption */
91 SetWindowText(ret
, "Map");
93 mswin_apply_window_style(ret
);
99 mswin_map_stretch(HWND hWnd
, LPSIZE lpsz
, BOOL redraw
)
107 /* check arguments */
108 if (!IsWindow(hWnd
) || !lpsz
|| lpsz
->cx
<= 0 || lpsz
->cy
<= 0)
111 /* calculate window size */
112 GetClientRect(hWnd
, &client_rt
);
113 wnd_size
.cx
= client_rt
.right
- client_rt
.left
;
114 wnd_size
.cy
= client_rt
.bottom
- client_rt
.top
;
116 /* set new screen tile size */
117 data
= (PNHMapWindow
) GetWindowLongPtr(hWnd
, GWLP_USERDATA
);
119 max(1, (data
->bFitToScreenMode
? wnd_size
.cx
: lpsz
->cx
) / COLNO
);
121 max(1, (data
->bFitToScreenMode
? wnd_size
.cy
: lpsz
->cy
) / ROWNO
);
123 /* set map origin point */
125 max(0, client_rt
.left
+ (wnd_size
.cx
- data
->xScrTile
* COLNO
) / 2);
127 max(0, client_rt
.top
+ (wnd_size
.cy
- data
->yScrTile
* ROWNO
) / 2);
129 data
->map_orig
.x
-= data
->map_orig
.x
% data
->xScrTile
;
130 data
->map_orig
.y
-= data
->map_orig
.y
% data
->yScrTile
;
132 /* adjust horizontal scroll bar */
133 if (data
->bFitToScreenMode
)
134 data
->xPageSize
= COLNO
+ 1; /* disable scroll bar */
136 data
->xPageSize
= wnd_size
.cx
/ data
->xScrTile
;
138 if (data
->xPageSize
>= COLNO
) {
140 GetNHApp()->bNoHScroll
= TRUE
;
142 GetNHApp()->bNoHScroll
= FALSE
;
144 0, min(COLNO
- data
->xPageSize
+ 1, u
.ux
- data
->xPageSize
/ 2));
147 si
.cbSize
= sizeof(si
);
148 si
.fMask
= SIF_RANGE
| SIF_PAGE
| SIF_POS
;
151 si
.nPage
= data
->xPageSize
;
152 si
.nPos
= data
->xPos
;
153 SetScrollInfo(hWnd
, SB_HORZ
, &si
, TRUE
);
155 /* adjust vertical scroll bar */
156 if (data
->bFitToScreenMode
)
157 data
->yPageSize
= ROWNO
+ 1; /* disable scroll bar */
159 data
->yPageSize
= wnd_size
.cy
/ data
->yScrTile
;
161 if (data
->yPageSize
>= ROWNO
) {
163 GetNHApp()->bNoVScroll
= TRUE
;
165 GetNHApp()->bNoVScroll
= FALSE
;
167 0, min(ROWNO
- data
->yPageSize
+ 1, u
.uy
- data
->yPageSize
/ 2));
170 si
.cbSize
= sizeof(si
);
171 si
.fMask
= SIF_RANGE
| SIF_PAGE
| SIF_POS
;
174 si
.nPage
= data
->yPageSize
;
175 si
.nPos
= data
->yPos
;
176 SetScrollInfo(hWnd
, SB_VERT
, &si
, TRUE
);
180 DeleteObject(data
->hMapFont
);
181 ZeroMemory(&lgfnt
, sizeof(lgfnt
));
182 lgfnt
.lfHeight
= -data
->yScrTile
; // height of font
183 lgfnt
.lfWidth
= -data
->xScrTile
; // average character width
184 lgfnt
.lfEscapement
= 0; // angle of escapement
185 lgfnt
.lfOrientation
= 0; // base-line orientation angle
186 lgfnt
.lfWeight
= FW_NORMAL
; // font weight
187 lgfnt
.lfItalic
= FALSE
; // italic attribute option
188 lgfnt
.lfUnderline
= FALSE
; // underline attribute option
189 lgfnt
.lfStrikeOut
= FALSE
; // strikeout attribute option
190 lgfnt
.lfCharSet
= mswin_charset(); // character set identifier
191 lgfnt
.lfOutPrecision
= OUT_DEFAULT_PRECIS
; // output precision
192 lgfnt
.lfClipPrecision
= CLIP_DEFAULT_PRECIS
; // clipping precision
193 lgfnt
.lfQuality
= DEFAULT_QUALITY
; // output quality
194 if (iflags
.wc_font_map
&& *iflags
.wc_font_map
) {
195 lgfnt
.lfPitchAndFamily
= DEFAULT_PITCH
; // pitch and family
196 NH_A2W(iflags
.wc_font_map
, lgfnt
.lfFaceName
, LF_FACESIZE
);
198 lgfnt
.lfPitchAndFamily
= FIXED_PITCH
; // pitch and family
199 NH_A2W(NHMAP_FONT_NAME
, lgfnt
.lfFaceName
, LF_FACESIZE
);
201 data
->hMapFont
= CreateFontIndirect(&lgfnt
);
203 mswin_cliparound(data
->xCur
, data
->yCur
);
206 InvalidateRect(hWnd
, NULL
, TRUE
);
211 mswin_map_mode(HWND hWnd
, int mode
)
217 data
= (PNHMapWindow
) GetWindowLongPtr(hWnd
, GWLP_USERDATA
);
218 if (mode
== data
->mapMode
)
221 oldMode
= data
->mapMode
;
222 data
->mapMode
= mode
;
224 switch (data
->mapMode
) {
225 case MAP_MODE_ASCII4x6
:
226 data
->bAsciiMode
= TRUE
;
227 data
->bFitToScreenMode
= FALSE
;
228 mapSize
.cx
= 4 * COLNO
;
229 mapSize
.cy
= 6 * ROWNO
;
232 case MAP_MODE_ASCII6x8
:
233 data
->bAsciiMode
= TRUE
;
234 data
->bFitToScreenMode
= FALSE
;
235 mapSize
.cx
= 6 * COLNO
;
236 mapSize
.cy
= 8 * ROWNO
;
239 case MAP_MODE_ASCII8x8
:
240 data
->bAsciiMode
= TRUE
;
241 data
->bFitToScreenMode
= FALSE
;
242 mapSize
.cx
= 8 * COLNO
;
243 mapSize
.cy
= 8 * ROWNO
;
246 case MAP_MODE_ASCII16x8
:
247 data
->bAsciiMode
= TRUE
;
248 data
->bFitToScreenMode
= FALSE
;
249 mapSize
.cx
= 16 * COLNO
;
250 mapSize
.cy
= 8 * ROWNO
;
253 case MAP_MODE_ASCII7x12
:
254 data
->bAsciiMode
= TRUE
;
255 data
->bFitToScreenMode
= FALSE
;
256 mapSize
.cx
= 7 * COLNO
;
257 mapSize
.cy
= 12 * ROWNO
;
260 case MAP_MODE_ASCII8x12
:
261 data
->bAsciiMode
= TRUE
;
262 data
->bFitToScreenMode
= FALSE
;
263 mapSize
.cx
= 8 * COLNO
;
264 mapSize
.cy
= 12 * ROWNO
;
267 case MAP_MODE_ASCII16x12
:
268 data
->bAsciiMode
= TRUE
;
269 data
->bFitToScreenMode
= FALSE
;
270 mapSize
.cx
= 16 * COLNO
;
271 mapSize
.cy
= 12 * ROWNO
;
274 case MAP_MODE_ASCII12x16
:
275 data
->bAsciiMode
= TRUE
;
276 data
->bFitToScreenMode
= FALSE
;
277 mapSize
.cx
= 12 * COLNO
;
278 mapSize
.cy
= 16 * ROWNO
;
281 case MAP_MODE_ASCII10x18
:
282 data
->bAsciiMode
= TRUE
;
283 data
->bFitToScreenMode
= FALSE
;
284 mapSize
.cx
= 10 * COLNO
;
285 mapSize
.cy
= 18 * ROWNO
;
288 case MAP_MODE_ASCII_FIT_TO_SCREEN
: {
290 GetClientRect(hWnd
, &client_rt
);
291 mapSize
.cx
= client_rt
.right
- client_rt
.left
;
292 mapSize
.cy
= client_rt
.bottom
- client_rt
.top
;
294 data
->bAsciiMode
= TRUE
;
295 data
->bFitToScreenMode
= TRUE
;
298 case MAP_MODE_TILES_FIT_TO_SCREEN
: {
300 GetClientRect(hWnd
, &client_rt
);
301 mapSize
.cx
= client_rt
.right
- client_rt
.left
;
302 mapSize
.cy
= client_rt
.bottom
- client_rt
.top
;
304 data
->bAsciiMode
= FALSE
;
305 data
->bFitToScreenMode
= TRUE
;
310 data
->bAsciiMode
= FALSE
;
311 data
->bFitToScreenMode
= FALSE
;
312 mapSize
.cx
= GetNHApp()->mapTile_X
* COLNO
;
313 mapSize
.cy
= GetNHApp()->mapTile_Y
* ROWNO
;
317 mswin_map_stretch(hWnd
, &mapSize
, TRUE
);
319 mswin_update_inventory(); /* for perm_invent to hide/show tiles */
324 /* register window class for map window */
326 register_map_window_class()
329 ZeroMemory(&wcex
, sizeof(wcex
));
332 wcex
.style
= CS_NOCLOSE
| CS_DBLCLKS
;
333 wcex
.lpfnWndProc
= (WNDPROC
) MapWndProc
;
336 wcex
.hInstance
= GetNHApp()->hApp
;
338 wcex
.hCursor
= LoadCursor(NULL
, IDC_ARROW
);
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 */
351 MapWndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
355 data
= (PNHMapWindow
) GetWindowLongPtr(hWnd
, GWLP_USERDATA
);
358 onCreate(hWnd
, wParam
, lParam
);
361 case WM_MSNH_COMMAND
:
362 onMSNHCommand(hWnd
, wParam
, lParam
);
370 /* transfer focus back to the main window */
371 SetFocus(GetNHApp()->hMainWnd
);
375 onMSNH_HScroll(hWnd
, wParam
, lParam
);
379 onMSNH_VScroll(hWnd
, wParam
, lParam
);
386 if (data
->bFitToScreenMode
) {
387 size
.cx
= LOWORD(lParam
);
388 size
.cy
= HIWORD(lParam
);
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
);
397 /* update window placement */
398 GetWindowRect(hWnd
, &rt
);
399 ScreenToClient(GetNHApp()->hMainWnd
, (LPPOINT
) &rt
);
400 ScreenToClient(GetNHApp()->hMainWnd
, ((LPPOINT
) &rt
) + 1);
401 mswin_update_window_placement(NHW_MAP
, &rt
);
406 GetWindowRect(hWnd
, &rt
);
407 ScreenToClient(GetNHApp()->hMainWnd
, (LPPOINT
) &rt
);
408 ScreenToClient(GetNHApp()->hMainWnd
, ((LPPOINT
) &rt
) + 1);
409 mswin_update_window_placement(NHW_MAP
, &rt
);
415 max(0, min(COLNO
, data
->xPos
416 + (LOWORD(lParam
) - data
->map_orig
.x
)
418 max(0, min(ROWNO
, data
->yPos
419 + (HIWORD(lParam
) - data
->map_orig
.y
)
423 case WM_LBUTTONDBLCLK
:
426 max(0, min(COLNO
, data
->xPos
427 + (LOWORD(lParam
) - data
->map_orig
.x
)
429 max(0, min(ROWNO
, data
->yPos
430 + (HIWORD(lParam
) - data
->map_orig
.y
)
436 DeleteObject(data
->hMapFont
);
438 SetWindowLongPtr(hWnd
, GWLP_USERDATA
, (LONG_PTR
) 0);
442 return DefWindowProc(hWnd
, message
, wParam
, lParam
);
449 onMSNHCommand(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
454 data
= (PNHMapWindow
) GetWindowLongPtr(hWnd
, GWLP_USERDATA
);
456 case MSNH_MSG_PRINT_GLYPH
: {
457 PMSNHMsgPrintGlyph msg_data
= (PMSNHMsgPrintGlyph
) lParam
;
458 if ((data
->map
[msg_data
->x
][msg_data
->y
] != msg_data
->glyph
)
459 || (data
->bkmap
[msg_data
->x
][msg_data
->y
] != msg_data
->bkglyph
)) {
460 data
->map
[msg_data
->x
][msg_data
->y
] = msg_data
->glyph
;
461 data
->bkmap
[msg_data
->x
][msg_data
->y
] = msg_data
->bkglyph
;
463 /* invalidate the update area. Erase backround if there
464 is nothing to paint or we are in text mode */
465 nhcoord2display(data
, msg_data
->x
, msg_data
->y
, &rt
);
466 InvalidateRect(hWnd
, &rt
,
467 (((msg_data
->glyph
== NO_GLYPH
) && (msg_data
->bkglyph
== NO_GLYPH
))
469 || Is_rogue_level(&u
.uz
)));
473 case MSNH_MSG_CLIPAROUND
: {
474 PMSNHMsgClipAround msg_data
= (PMSNHMsgClipAround
) lParam
;
476 BOOL scroll_x
, scroll_y
;
477 int mcam
= iflags
.wc_scroll_margin
;
479 /* calculate if you should clip around */
481 !GetNHApp()->bNoHScroll
482 && (msg_data
->x
< (data
->xPos
+ mcam
)
483 || msg_data
->x
> (data
->xPos
+ data
->xPageSize
- mcam
));
485 !GetNHApp()->bNoVScroll
486 && (msg_data
->y
< (data
->yPos
+ mcam
)
487 || msg_data
->y
> (data
->yPos
+ data
->yPageSize
- mcam
));
489 mcam
+= iflags
.wc_scroll_amount
- 1;
490 /* get page size and center horizontally on x-position */
492 if (data
->xPageSize
<= 2 * mcam
) {
493 x
= max(0, min(COLNO
, msg_data
->x
- data
->xPageSize
/ 2));
494 } else if (msg_data
->x
< data
->xPos
+ data
->xPageSize
/ 2) {
495 x
= max(0, min(COLNO
, msg_data
->x
- mcam
));
497 x
= max(0, min(COLNO
, msg_data
->x
- data
->xPageSize
+ mcam
));
499 SendMessage(hWnd
, WM_HSCROLL
, (WPARAM
) MAKELONG(SB_THUMBTRACK
, x
),
503 /* get page size and center vertically on y-position */
505 if (data
->yPageSize
<= 2 * mcam
) {
506 y
= max(0, min(ROWNO
, msg_data
->y
- data
->yPageSize
/ 2));
507 } else if (msg_data
->y
< data
->yPos
+ data
->yPageSize
/ 2) {
508 y
= max(0, min(ROWNO
, msg_data
->y
- mcam
));
510 y
= max(0, min(ROWNO
, msg_data
->y
- data
->yPageSize
+ mcam
));
512 SendMessage(hWnd
, WM_VSCROLL
, (WPARAM
) MAKELONG(SB_THUMBTRACK
, y
),
517 case MSNH_MSG_CLEAR_WINDOW
: {
519 for (i
= 0; i
< COLNO
; i
++)
520 for (j
= 0; j
< ROWNO
; j
++) {
521 data
->map
[i
][j
] = NO_GLYPH
;
522 data
->bkmap
[i
][j
] = NO_GLYPH
;
524 InvalidateRect(hWnd
, NULL
, TRUE
);
527 case MSNH_MSG_CURSOR
: {
528 PMSNHMsgCursor msg_data
= (PMSNHMsgCursor
) lParam
;
532 /* move focus rectangle at the cursor postion */
535 nhcoord2display(data
, data
->xCur
, data
->yCur
, &rt
);
536 if (data
->bAsciiMode
) {
537 PatBlt(hdc
, rt
.left
, rt
.top
, rt
.right
- rt
.left
,
538 rt
.bottom
- rt
.top
, DSTINVERT
);
540 DrawFocusRect(hdc
, &rt
);
543 data
->xCur
= msg_data
->x
;
544 data
->yCur
= msg_data
->y
;
546 nhcoord2display(data
, data
->xCur
, data
->yCur
, &rt
);
547 if (data
->bAsciiMode
) {
548 PatBlt(hdc
, rt
.left
, rt
.top
, rt
.right
- rt
.left
,
549 rt
.bottom
- rt
.top
, DSTINVERT
);
551 DrawFocusRect(hdc
, &rt
);
554 ReleaseDC(hWnd
, hdc
);
557 case MSNH_MSG_GETTEXT
: {
558 PMSNHMsgGetText msg_data
= (PMSNHMsgGetText
) lParam
;
566 for (row
= 0; row
< ROWNO
; row
++) {
567 for (col
= 0; col
< COLNO
; col
++) {
568 if (index
>= msg_data
->max_size
)
570 if (data
->map
[col
][row
] == NO_GLYPH
) {
573 (void) mapglyph(data
->map
[col
][row
], &mgch
, &color
,
576 msg_data
->buffer
[index
] = mgch
;
579 if (index
>= msg_data
->max_size
- 1)
581 msg_data
->buffer
[index
++] = '\r';
582 msg_data
->buffer
[index
++] = '\n';
586 } /* end switch(wParam) */
591 onCreate(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
596 UNREFERENCED_PARAMETER(wParam
);
597 UNREFERENCED_PARAMETER(lParam
);
599 /* set window data */
600 data
= (PNHMapWindow
) malloc(sizeof(NHMapWindow
));
602 panic("out of memory");
604 ZeroMemory(data
, sizeof(NHMapWindow
));
605 for (i
= 0; i
< COLNO
; i
++)
606 for (j
= 0; j
< ROWNO
; j
++) {
607 data
->map
[i
][j
] = NO_GLYPH
;
608 data
->bkmap
[i
][j
] = NO_GLYPH
;
611 data
->bAsciiMode
= FALSE
;
613 data
->xScrTile
= GetNHApp()->mapTile_X
;
614 data
->yScrTile
= GetNHApp()->mapTile_Y
;
616 SetWindowLongPtr(hWnd
, GWLP_USERDATA
, (LONG_PTR
) data
);
631 /* get window data */
632 data
= (PNHMapWindow
) GetWindowLongPtr(hWnd
, GWLP_USERDATA
);
634 hDC
= BeginPaint(hWnd
, &ps
);
636 /* calculate paint rectangle */
637 if (!IsRectEmpty(&ps
.rcPaint
)) {
638 /* calculate paint rectangle */
641 + (ps
.rcPaint
.left
- data
->map_orig
.x
) / data
->xScrTile
,
644 data
->yPos
+ (ps
.rcPaint
.top
- data
->map_orig
.y
) / data
->yScrTile
,
646 paint_rt
.right
= min(
648 + (ps
.rcPaint
.right
- data
->map_orig
.x
) / data
->xScrTile
+ 1,
650 paint_rt
.bottom
= min(
652 + (ps
.rcPaint
.bottom
- data
->map_orig
.y
) / data
->yScrTile
+ 1,
655 if (data
->bAsciiMode
|| Is_rogue_level(&u
.uz
)) {
656 /* You enter a VERY primitive world! */
659 oldFont
= SelectObject(hDC
, data
->hMapFont
);
660 SetBkMode(hDC
, TRANSPARENT
);
663 for (i
= paint_rt
.left
; i
< paint_rt
.right
; i
++)
664 for (j
= paint_rt
.top
; j
< paint_rt
.bottom
; j
++)
665 if (data
->map
[i
][j
] >= 0) {
675 nhcoord2display(data
, i
, j
, &glyph_rect
);
677 #if (VERSION_MAJOR < 4) && (VERSION_MINOR < 4) && (PATCHLEVEL < 2)
678 nhglyph2charcolor(data
->map
[i
][j
], &ch
, &color
);
679 OldFg
= SetTextColor(hDC
, nhcolor_to_RGB(color
));
681 /* rely on aNetHack core helper routine */
682 (void) mapglyph(data
->map
[i
][j
], &mgch
, &color
,
685 if (((special
& MG_PET
) && iflags
.hilite_pet
)
686 || ((special
& (MG_DETECT
| MG_BW_LAVA
))
687 && iflags
.use_inverse
)) {
689 CreateSolidBrush(nhcolor_to_RGB(CLR_GRAY
));
690 FillRect(hDC
, &glyph_rect
, back_brush
);
691 DeleteObject(back_brush
);
695 OldFg
= SetTextColor(
696 hDC
, nhcolor_to_RGB(CLR_BLACK
));
700 SetTextColor(hDC
, nhcolor_to_RGB(color
));
703 OldFg
= SetTextColor(hDC
, nhcolor_to_RGB(color
));
707 DrawText(hDC
, NH_A2W(&ch
, &wch
, 1), 1, &glyph_rect
,
708 DT_CENTER
| DT_VCENTER
| DT_NOPREFIX
);
709 SetTextColor(hDC
, OldFg
);
711 SelectObject(hDC
, oldFont
);
723 /* prepare tiles DC for mapping */
724 tileDC
= CreateCompatibleDC(hDC
);
725 saveBmp
= SelectObject(tileDC
, GetNHApp()->bmpMapTiles
);
728 for (i
= paint_rt
.left
; i
< paint_rt
.right
; i
++)
729 for (j
= paint_rt
.top
; j
< paint_rt
.bottom
; j
++) {
731 glyph
= data
->map
[i
][j
];
732 bkglyph
= data
->bkmap
[i
][j
];
734 if (bkglyph
!= NO_GLYPH
) {
735 ntile
= glyph2tile
[bkglyph
];
736 t_x
= TILEBMP_X(ntile
);
737 t_y
= TILEBMP_Y(ntile
);
738 nhcoord2display(data
, i
, j
, &glyph_rect
);
740 StretchBlt(hDC
, glyph_rect
.left
, glyph_rect
.top
,
741 data
->xScrTile
, data
->yScrTile
, tileDC
,
742 t_x
, t_y
, GetNHApp()->mapTile_X
,
743 GetNHApp()->mapTile_Y
, SRCCOPY
);
747 if ((glyph
!= NO_GLYPH
) && (glyph
!= bkglyph
)) {
748 ntile
= glyph2tile
[glyph
];
749 t_x
= TILEBMP_X(ntile
);
750 t_y
= TILEBMP_Y(ntile
);
751 nhcoord2display(data
, i
, j
, &glyph_rect
);
754 (*GetNHApp()->lpfnTransparentBlt
)(
755 hDC
, glyph_rect
.left
, glyph_rect
.top
,
756 data
->xScrTile
, data
->yScrTile
, tileDC
,
757 t_x
, t_y
, GetNHApp()->mapTile_X
,
758 GetNHApp()->mapTile_Y
, TILE_BK_COLOR
);
760 StretchBlt(hDC
, glyph_rect
.left
, glyph_rect
.top
,
761 data
->xScrTile
, data
->yScrTile
, tileDC
,
762 t_x
, t_y
, GetNHApp()->mapTile_X
,
763 GetNHApp()->mapTile_Y
, SRCCOPY
);
770 /* rely on aNetHack core helper routine */
771 (void) mapglyph(data
->map
[i
][j
], &mgch
, &color
,
773 if ((glyph
!= NO_GLYPH
) && (special
& MG_PET
)
775 if ((glyph
!= NO_GLYPH
) && glyph_is_pet(glyph
)
777 && iflags
.wc_hilite_pet
) {
778 /* apply pet mark transparently over
781 HBITMAP bmPetMarkOld
;
783 /* this is DC for petmark bitmap */
784 hdcPetMark
= CreateCompatibleDC(hDC
);
785 bmPetMarkOld
= SelectObject(
786 hdcPetMark
, GetNHApp()->bmpPetMark
);
788 (*GetNHApp()->lpfnTransparentBlt
)(
789 hDC
, glyph_rect
.left
, glyph_rect
.top
,
790 data
->xScrTile
, data
->yScrTile
, hdcPetMark
, 0,
791 0, TILE_X
, TILE_Y
, TILE_BK_COLOR
);
792 SelectObject(hdcPetMark
, bmPetMarkOld
);
793 DeleteDC(hdcPetMark
);
796 if ((glyph
!= NO_GLYPH
)
797 && (special
& MG_OBJPILE
) && iflags
.hilite_pile
) {
798 /* apply pilemark transparently over other image */
800 HBITMAP bmPileMarkOld
;
802 /* this is DC for pilemark bitmap */
803 hdcPileMark
= CreateCompatibleDC(hDC
);
804 bmPileMarkOld
= SelectObject(
805 hdcPileMark
, GetNHApp()->bmpPileMark
);
807 (*GetNHApp()->lpfnTransparentBlt
)(
808 hDC
, glyph_rect
.left
, glyph_rect
.top
,
809 data
->xScrTile
, data
->yScrTile
, hdcPileMark
, 0,
810 0, TILE_X
, TILE_Y
, TILE_BK_COLOR
);
811 SelectObject(hdcPileMark
, bmPileMarkOld
);
812 DeleteDC(hdcPileMark
);
817 SelectObject(tileDC
, saveBmp
);
821 /* draw focus rect */
822 nhcoord2display(data
, data
->xCur
, data
->yCur
, &paint_rt
);
823 if (data
->bAsciiMode
) {
824 PatBlt(hDC
, paint_rt
.left
, paint_rt
.top
,
825 paint_rt
.right
- paint_rt
.left
,
826 paint_rt
.bottom
- paint_rt
.top
, DSTINVERT
);
828 DrawFocusRect(hDC
, &paint_rt
);
836 onMSNH_VScroll(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
843 UNREFERENCED_PARAMETER(lParam
);
845 /* get window data */
846 data
= (PNHMapWindow
) GetWindowLongPtr(hWnd
, GWLP_USERDATA
);
848 switch (LOWORD(wParam
)) {
849 /* User clicked shaft left of the scroll box. */
851 yNewPos
= data
->yPos
- data
->yPageSize
;
854 /* User clicked shaft right of the scroll box. */
856 yNewPos
= data
->yPos
+ data
->yPageSize
;
859 /* User clicked the left arrow. */
861 yNewPos
= data
->yPos
- 1;
864 /* User clicked the right arrow. */
866 yNewPos
= data
->yPos
+ 1;
869 /* User dragged the scroll box. */
871 yNewPos
= HIWORD(wParam
);
875 yNewPos
= data
->yPos
;
878 yNewPos
= max(0, min(ROWNO
- data
->yPageSize
+ 1, yNewPos
));
879 if (yNewPos
== data
->yPos
)
882 yDelta
= yNewPos
- data
->yPos
;
883 data
->yPos
= yNewPos
;
885 ScrollWindowEx(hWnd
, 0, -data
->yScrTile
* yDelta
, (CONST RECT
*) NULL
,
886 (CONST RECT
*) NULL
, (HRGN
) NULL
, (LPRECT
) NULL
,
887 SW_INVALIDATE
| SW_ERASE
);
889 si
.cbSize
= sizeof(si
);
891 si
.nPos
= data
->yPos
;
892 SetScrollInfo(hWnd
, SB_VERT
, &si
, TRUE
);
897 onMSNH_HScroll(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
904 UNREFERENCED_PARAMETER(lParam
);
906 /* get window data */
907 data
= (PNHMapWindow
) GetWindowLongPtr(hWnd
, GWLP_USERDATA
);
909 switch (LOWORD(wParam
)) {
910 /* User clicked shaft left of the scroll box. */
912 xNewPos
= data
->xPos
- data
->xPageSize
;
915 /* User clicked shaft right of the scroll box. */
917 xNewPos
= data
->xPos
+ data
->xPageSize
;
920 /* User clicked the left arrow. */
922 xNewPos
= data
->xPos
- 1;
925 /* User clicked the right arrow. */
927 xNewPos
= data
->xPos
+ 1;
930 /* User dragged the scroll box. */
932 xNewPos
= HIWORD(wParam
);
936 xNewPos
= data
->xPos
;
939 xNewPos
= max(0, min(COLNO
- data
->xPageSize
+ 1, xNewPos
));
940 if (xNewPos
== data
->xPos
)
943 xDelta
= xNewPos
- data
->xPos
;
944 data
->xPos
= xNewPos
;
946 ScrollWindowEx(hWnd
, -data
->xScrTile
* xDelta
, 0, (CONST RECT
*) NULL
,
947 (CONST RECT
*) NULL
, (HRGN
) NULL
, (LPRECT
) NULL
,
948 SW_INVALIDATE
| SW_ERASE
);
950 si
.cbSize
= sizeof(si
);
952 si
.nPos
= data
->xPos
;
953 SetScrollInfo(hWnd
, SB_HORZ
, &si
, TRUE
);
956 /* map anethack map coordinates to the screen location */
958 nhcoord2display(PNHMapWindow data
, int x
, int y
, LPRECT lpOut
)
960 lpOut
->left
= (x
- data
->xPos
) * data
->xScrTile
+ data
->map_orig
.x
;
961 lpOut
->top
= (y
- data
->yPos
) * data
->yScrTile
+ data
->map_orig
.y
;
962 lpOut
->right
= lpOut
->left
+ data
->xScrTile
;
963 lpOut
->bottom
= lpOut
->top
+ data
->yScrTile
;
966 #if (VERSION_MAJOR < 4) && (VERSION_MINOR < 4) && (PATCHLEVEL < 2)
967 /* map glyph to character/color combination */
969 nhglyph2charcolor(short g
, uchar
*ch
, int *color
)
974 #define zap_color(n) *color = iflags.use_color ? zapcolors[n] : NO_COLOR
975 #define cmap_color(n) *color = iflags.use_color ? defsyms[n].color : NO_COLOR
976 #define obj_color(n) \
977 *color = iflags.use_color ? objects[n].oc_color : NO_COLOR
978 #define mon_color(n) *color = iflags.use_color ? mons[n].mcolor : NO_COLOR
979 #define pet_color(n) *color = iflags.use_color ? mons[n].mcolor : NO_COLOR
980 #define warn_color(n) \
981 *color = iflags.use_color ? def_warnsyms[n].color : NO_COLOR
983 #else /* no text color */
986 #define cmap_color(n)
990 #define warn_color(c)
994 if ((offset
= (g
- GLYPH_WARNING_OFF
)) >= 0) { /* a warning flash */
995 *ch
= showsyms
[offset
+ SYM_OFF_W
];
997 } else if ((offset
= (g
- GLYPH_SWALLOW_OFF
)) >= 0) { /* swallow */
998 /* see swallow_to_glyph() in display.c */
999 *ch
= (uchar
) showsyms
[(S_sw_tl
+ (offset
& 0x7)) + SYM_OFF_P
];
1000 mon_color(offset
>> 3);
1001 } else if ((offset
= (g
- GLYPH_ZAP_OFF
)) >= 0) { /* zap beam */
1002 /* see zapdir_to_glyph() in display.c */
1003 *ch
= showsyms
[(S_vbeam
+ (offset
& 0x3)) + SYM_OFF_P
];
1004 zap_color((offset
>> 2));
1005 } else if ((offset
= (g
- GLYPH_CMAP_OFF
)) >= 0) { /* cmap */
1006 *ch
= showsyms
[offset
+ SYM_OFF_P
];
1008 } else if ((offset
= (g
- GLYPH_OBJ_OFF
)) >= 0) { /* object */
1009 *ch
= showsyms
[(int) objects
[offset
].oc_class
+ SYM_OFF_O
];
1011 } else if ((offset
= (g
- GLYPH_BODY_OFF
)) >= 0) { /* a corpse */
1012 *ch
= showsyms
[(int) objects
[CORPSE
].oc_class
+ SYM_OFF_O
];
1014 } else if ((offset
= (g
- GLYPH_PET_OFF
)) >= 0) { /* a pet */
1015 *ch
= showsyms
[(int) mons
[offset
].mlet
+ SYM_OFF_M
];
1017 } else { /* a monster */
1018 *ch
= showsyms
[(int) mons
[g
].mlet
+ SYM_OFF_M
];
1021 // end of wintty code
1025 /* map anethack color to RGB */
1027 nhcolor_to_RGB(int c
)
1029 if (c
>= 0 && c
< CLR_MAX
)
1030 return GetNHApp()->regMapColors
[c
];
1031 return RGB(0x00, 0x00, 0x00);