1 /* NetHack 3.6 mhmap.c $NHDT-Date: 1435002695 2015/06/22 19:51:35 $ $NHDT-Branch: master $:$NHDT-Revision: 1.56 $ */
2 /* Copyright (C) 2001 by Alex Kompel */
3 /* NetHack 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_nethack_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 NetHack 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 NetHack 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 nethack 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 nethack 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);