1 /* NetHack 3.6 mhmain.c $NHDT-Date: 1432512811 2015/05/25 00:13:31 $ $NHDT-Branch: master $:$NHDT-Revision: 1.62 $ */
2 /* Copyright (C) 2001 by Alex Kompel */
3 /* NetHack may be freely redistributed. See license for details. */
8 #include "patchlevel.h"
18 typedef struct mswin_nethack_main_window {
20 } NHMainWindow, *PNHMainWindow;
22 extern winid WIN_STATUS;
24 static TCHAR szMainWindowClass[] = TEXT("MSNHMainWndClass");
25 static TCHAR szTitle[MAX_LOADSTRING];
26 extern void mswin_display_splash_window(BOOL);
28 LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);
29 LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
30 static LRESULT onWMCommand(HWND hWnd, WPARAM wParam, LPARAM lParam);
31 static void onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam);
32 static void register_main_window_class(void);
33 static int menuid2mapmode(int menuid);
34 static int mapmode2menuid(int map_mode);
35 static void nhlock_windows(BOOL lock);
36 static char *nh_compose_ascii_screenshot();
37 // returns strdup() created pointer - callee assumes the ownership
40 mswin_init_main_window()
42 static int run_once = 0;
46 /* register window class */
48 LoadString(GetNHApp()->hApp, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
49 register_main_window_class();
53 /* create the main window */
55 CreateWindow(szMainWindowClass, /* registered class name */
56 szTitle, /* window name */
57 WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, /* window style */
58 CW_USEDEFAULT, /* horizontal position of window */
59 CW_USEDEFAULT, /* vertical position of window */
60 CW_USEDEFAULT, /* window width */
61 CW_USEDEFAULT, /* window height */
62 NULL, /* handle to parent or owner window */
63 NULL, /* menu handle or child identifier */
64 GetNHApp()->hApp, /* handle to application instance */
65 NULL /* window-creation data */
69 panic("Cannot create main window");
71 if (GetNHApp()->regMainMinX != CW_USEDEFAULT) {
72 wp.length = sizeof(wp);
73 wp.showCmd = GetNHApp()->regMainShowState;
75 wp.ptMinPosition.x = GetNHApp()->regMainMinX;
76 wp.ptMinPosition.y = GetNHApp()->regMainMinY;
78 wp.ptMaxPosition.x = GetNHApp()->regMainMaxX;
79 wp.ptMaxPosition.y = GetNHApp()->regMainMaxY;
81 wp.rcNormalPosition.left = GetNHApp()->regMainLeft;
82 wp.rcNormalPosition.top = GetNHApp()->regMainTop;
83 wp.rcNormalPosition.right = GetNHApp()->regMainRight;
84 wp.rcNormalPosition.bottom = GetNHApp()->regMainBottom;
85 SetWindowPlacement(ret, &wp);
87 ShowWindow(ret, SW_SHOWDEFAULT);
94 register_main_window_class()
98 ZeroMemory(&wcex, sizeof(wcex));
99 wcex.style = CS_HREDRAW | CS_VREDRAW;
100 wcex.lpfnWndProc = (WNDPROC) MainWndProc;
103 wcex.hInstance = GetNHApp()->hApp;
104 wcex.hIcon = LoadIcon(GetNHApp()->hApp, (LPCTSTR) IDI_NETHACKW);
105 wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
106 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
107 wcex.lpszMenuName = (TCHAR *) IDC_NETHACKW;
108 wcex.lpszClassName = szMainWindowClass;
110 RegisterClass(&wcex);
114 * Keypad keys are translated to the normal values below.
115 * Shifted keypad keys are translated to the
116 * shift values below.
136 static const unsigned char
137 /* normal, shift, control */
138 keypad[KEY_LAST][3] =
140 { 'y', 'Y', C('y') }, /* 7 */
141 { 'k', 'K', C('k') }, /* 8 */
142 { 'u', 'U', C('u') }, /* 9 */
143 { 'm', C('p'), C('p') }, /* - */
144 { 'h', 'H', C('h') }, /* 4 */
145 { 'g', 'G', 'g' }, /* 5 */
146 { 'l', 'L', C('l') }, /* 6 */
147 { '+', 'P', C('p') }, /* + */
148 { 'b', 'B', C('b') }, /* 1 */
149 { 'j', 'J', C('j') }, /* 2 */
150 { 'n', 'N', C('n') }, /* 3 */
151 { 'i', 'I', C('i') }, /* Ins */
152 { '.', ':', ':' } /* Del */
154 numpad[KEY_LAST][3] = {
155 { '7', M('7'), '7' }, /* 7 */
156 { '8', M('8'), '8' }, /* 8 */
157 { '9', M('9'), '9' }, /* 9 */
158 { 'm', C('p'), C('p') }, /* - */
159 { '4', M('4'), '4' }, /* 4 */
160 { '5', M('5'), '5' }, /* 5 */
161 { '6', M('6'), '6' }, /* 6 */
162 { '+', 'P', C('p') }, /* + */
163 { '1', M('1'), '1' }, /* 1 */
164 { '2', M('2'), '2' }, /* 2 */
165 { '3', M('3'), '3' }, /* 3 */
166 { '0', M('0'), '0' }, /* Ins */
167 { '.', ':', ':' } /* Del */
170 #define STATEON(x) ((GetKeyState(x) & 0xFFFE) != 0)
171 #define KEYTABLE_REGULAR(x) ((iflags.num_pad ? numpad : keypad)[x][0])
172 #define KEYTABLE_SHIFT(x) ((iflags.num_pad ? numpad : keypad)[x][1])
173 #define KEYTABLE(x) \
174 (STATEON(VK_SHIFT) ? KEYTABLE_SHIFT(x) : KEYTABLE_REGULAR(x))
176 static const char *extendedlist = "acdefijlmnopqrstuvw?2";
179 static const char scanmap[] = {
181 '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 0, 0, 0, 0, 'q', 'w',
182 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', 0, 'a', 's', 'd',
183 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', 0, '\\', 'z', 'x', 'c', 'v',
184 'b', 'n', 'm', ',', '.', '?' /* ... */
188 // FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
190 // PURPOSE: Processes messages for the main window.
193 MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
199 /* set window data */
200 data = (PNHMainWindow) malloc(sizeof(NHMainWindow));
202 panic("out of memory");
203 ZeroMemory(data, sizeof(NHMainWindow));
204 data->mapAcsiiModeSave = MAP_MODE_ASCII12x16;
205 SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) data);
207 /* update menu items */
209 GetMenu(hWnd), IDM_SETTING_LOCKWINDOWS,
211 | (GetNHApp()->bWindowsLocked ? MF_CHECKED : MF_UNCHECKED));
213 CheckMenuItem(GetMenu(hWnd), IDM_SETTING_AUTOLAYOUT,
214 GetNHApp()->bAutoLayout ? MF_CHECKED : MF_UNCHECKED);
216 /* store handle to the mane menu in the application record */
217 GetNHApp()->hMainWnd = hWnd;
220 case WM_MSNH_COMMAND:
221 onMSNHCommand(hWnd, wParam, lParam);
225 data = (PNHMainWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA);
227 /* translate arrow keys into nethack commands */
230 if (STATEON(VK_CONTROL)) {
231 /* scroll map window one line left */
232 SendMessage(mswin_hwnd_from_winid(WIN_MAP), WM_HSCROLL,
233 MAKEWPARAM(SB_LINEUP, 0), (LPARAM) NULL);
235 NHEVENT_KBD(KEYTABLE(KEY_W));
240 if (STATEON(VK_CONTROL)) {
241 /* scroll map window one line right */
242 SendMessage(mswin_hwnd_from_winid(WIN_MAP), WM_HSCROLL,
243 MAKEWPARAM(SB_LINEDOWN, 0), (LPARAM) NULL);
245 NHEVENT_KBD(KEYTABLE(KEY_E));
250 if (STATEON(VK_CONTROL)) {
251 /* scroll map window one line up */
252 SendMessage(mswin_hwnd_from_winid(WIN_MAP), WM_VSCROLL,
253 MAKEWPARAM(SB_LINEUP, 0), (LPARAM) NULL);
255 NHEVENT_KBD(KEYTABLE(KEY_N));
260 if (STATEON(VK_CONTROL)) {
261 /* scroll map window one line down */
262 SendMessage(mswin_hwnd_from_winid(WIN_MAP), WM_VSCROLL,
263 MAKEWPARAM(SB_LINEDOWN, 0), (LPARAM) NULL);
265 NHEVENT_KBD(KEYTABLE(KEY_S));
270 if (STATEON(VK_CONTROL)) {
271 /* scroll map window to upper left corner */
272 SendMessage(mswin_hwnd_from_winid(WIN_MAP), WM_VSCROLL,
273 MAKEWPARAM(SB_THUMBTRACK, 0), (LPARAM) NULL);
275 SendMessage(mswin_hwnd_from_winid(WIN_MAP), WM_HSCROLL,
276 MAKEWPARAM(SB_THUMBTRACK, 0), (LPARAM) NULL);
278 NHEVENT_KBD(KEYTABLE(KEY_NW));
283 if (STATEON(VK_CONTROL)) {
284 /* scroll map window to lower right corner */
285 SendMessage(mswin_hwnd_from_winid(WIN_MAP), WM_VSCROLL,
286 MAKEWPARAM(SB_THUMBTRACK, ROWNO), (LPARAM) NULL);
288 SendMessage(mswin_hwnd_from_winid(WIN_MAP), WM_HSCROLL,
289 MAKEWPARAM(SB_THUMBTRACK, COLNO), (LPARAM) NULL);
291 NHEVENT_KBD(KEYTABLE(KEY_SW));
296 if (STATEON(VK_CONTROL)) {
297 /* scroll map window one page up */
298 SendMessage(mswin_hwnd_from_winid(WIN_MAP), WM_VSCROLL,
299 MAKEWPARAM(SB_PAGEUP, 0), (LPARAM) NULL);
301 NHEVENT_KBD(KEYTABLE(KEY_NE));
306 if (STATEON(VK_CONTROL)) {
307 /* scroll map window one page down */
308 SendMessage(mswin_hwnd_from_winid(WIN_MAP), WM_VSCROLL,
309 MAKEWPARAM(SB_PAGEDOWN, 0), (LPARAM) NULL);
311 NHEVENT_KBD(KEYTABLE(KEY_SE));
317 NHEVENT_KBD(KEYTABLE(KEY_WAITLOOK));
321 NHEVENT_KBD(KEYTABLE(KEY_INV));
325 NHEVENT_KBD(KEYTABLE(KEY_MINUS));
329 NHEVENT_KBD(KEYTABLE(KEY_PLUS));
332 case VK_CLEAR: /* This is the '5' key */
333 NHEVENT_KBD(KEYTABLE(KEY_GOINTERESTING));
337 if (IS_MAP_FIT_TO_SCREEN(iflags.wc_map_mode)) {
338 mswin_select_map_mode(IS_MAP_ASCII(iflags.wc_map_mode)
339 ? data->mapAcsiiModeSave
342 mswin_select_map_mode(IS_MAP_ASCII(iflags.wc_map_mode)
343 ? MAP_MODE_ASCII_FIT_TO_SCREEN
344 : MAP_MODE_TILES_FIT_TO_SCREEN);
349 if (IS_MAP_ASCII(iflags.wc_map_mode)) {
350 if (IS_MAP_FIT_TO_SCREEN(iflags.wc_map_mode)) {
351 mswin_select_map_mode(MAP_MODE_TILES_FIT_TO_SCREEN);
353 mswin_select_map_mode(MAP_MODE_TILES);
356 if (IS_MAP_FIT_TO_SCREEN(iflags.wc_map_mode)) {
357 mswin_select_map_mode(MAP_MODE_ASCII_FIT_TO_SCREEN);
359 mswin_select_map_mode(data->mapAcsiiModeSave);
369 ZeroMemory(kbd_state, sizeof(kbd_state));
370 GetKeyboardState(kbd_state);
372 if (ToAscii(wParam, (lParam >> 16) & 0xFF, kbd_state, &c, 0)) {
373 NHEVENT_KBD(c & 0xFF);
383 case WM_SYSCHAR: /* Alt-char pressed */
386 If not nethackmode, don't handle Alt-keys here.
387 If no Alt-key pressed it can never be an extended command
389 if (GetNHApp()->regNetHackMode && ((lParam & 1 << 29) != 0)) {
390 unsigned char c = (unsigned char) (wParam & 0xFF);
391 unsigned char scancode = (lParam >> 16) & 0xFF;
392 if (index(extendedlist, tolower(c)) != 0) {
393 NHEVENT_KBD(M(tolower(c)));
394 } else if (scancode == (SCANLO + SIZE(scanmap)) - 1) {
399 return DefWindowProc(hWnd, message, wParam, lParam);
403 /* process commands - menu commands mostly */
404 if (onWMCommand(hWnd, wParam, lParam))
405 return DefWindowProc(hWnd, message, wParam, lParam);
413 mswin_layout_main_window(NULL);
415 wp.length = sizeof(wp);
416 if (GetWindowPlacement(hWnd, &wp)) {
417 GetNHApp()->regMainShowState =
418 (wp.showCmd == SW_SHOWMAXIMIZED ? SW_SHOWMAXIMIZED
421 GetNHApp()->regMainMinX = wp.ptMinPosition.x;
422 GetNHApp()->regMainMinY = wp.ptMinPosition.y;
424 GetNHApp()->regMainMaxX = wp.ptMaxPosition.x;
425 GetNHApp()->regMainMaxY = wp.ptMaxPosition.y;
427 GetNHApp()->regMainLeft = wp.rcNormalPosition.left;
428 GetNHApp()->regMainTop = wp.rcNormalPosition.top;
429 GetNHApp()->regMainRight = wp.rcNormalPosition.right;
430 GetNHApp()->regMainBottom = wp.rcNormalPosition.bottom;
435 /* if there is a menu window out there -
436 transfer input focus to it */
437 if (IsWindow(GetNHApp()->hPopupWnd)) {
438 SetFocus(GetNHApp()->hPopupWnd);
443 /* exit gracefully */
444 if (program_state.gameover) {
445 /* assume the user really meant this, as the game is already
447 /* to make sure we still save bones, just set stop printing flag
449 program_state.stopprint++;
451 '\033'); /* and send keyboard input as if user pressed ESC */
452 /* additional code for this is done in menu and rip windows */
453 } else if (!program_state.something_worth_saving) {
454 /* User exited before the game started, e.g. during splash display
459 /* prompt user for action */
460 switch (NHMessageBox(hWnd, TEXT("Save?"),
461 MB_YESNOCANCEL | MB_ICONQUESTION)) {
464 /* destroy popup window - it has its own loop and we need to
465 return control to NetHack core at this point */
466 if (IsWindow(GetNHApp()->hPopupWnd))
467 SendMessage(GetNHApp()->hPopupWnd, WM_COMMAND, IDCANCEL,
470 /* tell NetHack core that "hangup" is requested */
489 /* apparently we never get here
490 TODO: work on exit routines - need to send
494 free((PNHMainWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA));
495 SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) 0);
497 // PostQuitMessage(0);
502 return DefWindowProc(hWnd, message, wParam, lParam);
508 onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
510 UNREFERENCED_PARAMETER(hWnd);
511 UNREFERENCED_PARAMETER(wParam);
512 UNREFERENCED_PARAMETER(lParam);
515 /* new window was just added */
516 case MSNH_MSG_ADDWND: {
517 PMSNHMsgAddWnd msg_param = (PMSNHMsgAddWnd) lParam;
520 if (GetNHApp()->windowlist[msg_param->wid].type == NHW_MAP)
521 mswin_select_map_mode(iflags.wc_map_mode);
523 child = GetNHApp()->windowlist[msg_param->wid].win;
528 /* adjust windows to fit main window layout
529 ---------------------------
531 +-------------------------+
537 +-------------------------+
539 ---------------------------
542 mswin_layout_main_window(HWND changed_child)
545 RECT client_rt, wnd_rect;
553 HWND wnd_status, wnd_msg;
556 if (GetNHApp()->bAutoLayout) {
557 GetClientRect(GetNHApp()->hMainWnd, &client_rt);
558 data = (PNHMainWindow) GetWindowLongPtr(GetNHApp()->hMainWnd,
561 /* get sizes of child windows */
562 wnd_status = mswin_hwnd_from_winid(WIN_STATUS);
563 if (IsWindow(wnd_status)) {
564 mswin_status_window_size(wnd_status, &status_size);
566 status_size.cx = status_size.cy = 0;
569 wnd_msg = mswin_hwnd_from_winid(WIN_MESSAGE);
570 if (IsWindow(wnd_msg)) {
571 mswin_message_window_size(wnd_msg, &msg_size);
573 msg_size.cx = msg_size.cy = 0;
576 /* find all menu windows and calculate the size */
577 menu_size.cx = menu_size.cy = 0;
578 for (i = 0; i < MAXWINDOWS; i++) {
580 if (GetNHApp()->windowlist[i].win
581 && !GetNHApp()->windowlist[i].dead
582 && GetNHApp()->windowlist[i].type == NHW_MENU) {
583 mswin_menu_window_size(GetNHApp()->windowlist[i].win,
585 menu_size.cx = max(menu_size.cx, tmp_size.cx);
586 menu_size.cy = max(menu_size.cy, tmp_size.cy);
590 /* set window positions */
591 SetRect(&wnd_rect, client_rt.left, client_rt.top, client_rt.right,
593 switch (iflags.wc_align_status) {
595 status_size.cx = (wnd_rect.right - wnd_rect.left) / 4;
597 (wnd_rect.bottom - wnd_rect.top); // that won't look good
598 status_org.x = wnd_rect.left;
599 status_org.y = wnd_rect.top;
600 wnd_rect.left += status_size.cx;
604 status_size.cx = (wnd_rect.right - wnd_rect.left) / 4;
606 (wnd_rect.bottom - wnd_rect.top); // that won't look good
607 status_org.x = wnd_rect.right - status_size.cx;
608 status_org.y = wnd_rect.top;
609 wnd_rect.right -= status_size.cx;
613 status_size.cx = (wnd_rect.right - wnd_rect.left);
614 status_org.x = wnd_rect.left;
615 status_org.y = wnd_rect.top;
616 wnd_rect.top += status_size.cy;
621 status_size.cx = (wnd_rect.right - wnd_rect.left);
622 status_org.x = wnd_rect.left;
623 status_org.y = wnd_rect.bottom - status_size.cy;
624 wnd_rect.bottom -= status_size.cy;
628 switch (iflags.wc_align_message) {
630 msg_size.cx = (wnd_rect.right - wnd_rect.left) / 4;
631 msg_size.cy = (wnd_rect.bottom - wnd_rect.top);
632 msg_org.x = wnd_rect.left;
633 msg_org.y = wnd_rect.top;
634 wnd_rect.left += msg_size.cx;
638 msg_size.cx = (wnd_rect.right - wnd_rect.left) / 4;
639 msg_size.cy = (wnd_rect.bottom - wnd_rect.top);
640 msg_org.x = wnd_rect.right - msg_size.cx;
641 msg_org.y = wnd_rect.top;
642 wnd_rect.right -= msg_size.cx;
646 msg_size.cx = (wnd_rect.right - wnd_rect.left);
647 msg_org.x = wnd_rect.left;
648 msg_org.y = wnd_rect.top;
649 wnd_rect.top += msg_size.cy;
654 msg_size.cx = (wnd_rect.right - wnd_rect.left);
655 msg_org.x = wnd_rect.left;
656 msg_org.y = wnd_rect.bottom - msg_size.cy;
657 wnd_rect.bottom -= msg_size.cy;
662 map_org.x = wnd_rect.left;
663 map_org.y = wnd_rect.top;
664 map_size.cx = wnd_rect.right - wnd_rect.left;
665 map_size.cy = wnd_rect.bottom - wnd_rect.top;
667 GetNHApp()->rtStatusWindow.left = status_org.x;
668 GetNHApp()->rtStatusWindow.top = status_org.y;
669 GetNHApp()->rtStatusWindow.right = status_org.x + status_size.cx;
670 GetNHApp()->rtStatusWindow.bottom = status_org.y + status_size.cy;
672 GetNHApp()->rtTextWindow.left = map_org.x;
673 GetNHApp()->rtTextWindow.top = map_org.y;
674 GetNHApp()->rtTextWindow.right =
675 map_org.x + (wnd_rect.right - wnd_rect.left);
676 GetNHApp()->rtTextWindow.bottom = map_org.y + map_size.cy;
678 GetNHApp()->rtMapWindow.left = map_org.x;
679 GetNHApp()->rtMapWindow.top = map_org.y;
680 GetNHApp()->rtMapWindow.right = map_org.x + map_size.cx;
681 GetNHApp()->rtMapWindow.bottom = map_org.y + map_size.cy;
683 GetNHApp()->rtMsgWindow.left = msg_org.x;
684 GetNHApp()->rtMsgWindow.top = msg_org.y;
685 GetNHApp()->rtMsgWindow.right = msg_org.x + msg_size.cx;
686 GetNHApp()->rtMsgWindow.bottom = msg_org.y + msg_size.cy;
688 /* map_width/4 < menu_width < map_width*2/3 */
689 GetNHApp()->rtMenuWindow.left =
690 GetNHApp()->rtMapWindow.right
691 - min(map_size.cx * 2 / 3, max(map_size.cx / 4, menu_size.cx));
692 GetNHApp()->rtMenuWindow.top = GetNHApp()->rtMapWindow.top;
693 GetNHApp()->rtMenuWindow.right = GetNHApp()->rtMapWindow.right;
694 GetNHApp()->rtMenuWindow.bottom = GetNHApp()->rtMapWindow.bottom;
696 GetNHApp()->rtInvenWindow.left = GetNHApp()->rtMenuWindow.left;
697 GetNHApp()->rtInvenWindow.top = GetNHApp()->rtMenuWindow.top;
698 GetNHApp()->rtInvenWindow.right = GetNHApp()->rtMenuWindow.right;
699 GetNHApp()->rtInvenWindow.bottom = GetNHApp()->rtMenuWindow.bottom;
701 /* adjust map window size only if perm_invent is set */
702 if (flags.perm_invent)
703 GetNHApp()->rtMapWindow.right = GetNHApp()->rtMenuWindow.left;
706 /* go through the windows list and adjust sizes */
707 for (i = 0; i < MAXWINDOWS; i++) {
708 if (GetNHApp()->windowlist[i].win
709 && !GetNHApp()->windowlist[i].dead) {
711 /* kludge - inventory window should have its own type (same as
713 as a matter of fact) */
714 if (flags.perm_invent && i == WIN_INVEN)
715 mswin_get_window_placement(NHW_INVEN, &rt);
717 mswin_get_window_placement(GetNHApp()->windowlist[i].type,
720 MoveWindow(GetNHApp()->windowlist[i].win, rt.left, rt.top,
721 rt.right - rt.left, rt.bottom - rt.top, TRUE);
724 if (IsWindow(changed_child))
725 SetForegroundWindow(changed_child);
729 onWMCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
734 UNREFERENCED_PARAMETER(lParam);
736 data = (PNHMainWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA);
737 wmId = LOWORD(wParam);
738 wmEvent = HIWORD(wParam);
740 // Parse the menu selections:
743 mswin_display_splash_window(TRUE);
751 if (!program_state.gameover && !program_state.done_hup)
758 case IDM_MAP_ASCII4X6:
759 case IDM_MAP_ASCII6X8:
760 case IDM_MAP_ASCII8X8:
761 case IDM_MAP_ASCII16X8:
762 case IDM_MAP_ASCII7X12:
763 case IDM_MAP_ASCII8X12:
764 case IDM_MAP_ASCII12X16:
765 case IDM_MAP_ASCII16X12:
766 case IDM_MAP_ASCII10X18:
767 mswin_select_map_mode(menuid2mapmode(wmId));
770 case IDM_MAP_FIT_TO_SCREEN:
771 if (IS_MAP_FIT_TO_SCREEN(iflags.wc_map_mode)) {
772 mswin_select_map_mode(IS_MAP_ASCII(iflags.wc_map_mode)
773 ? data->mapAcsiiModeSave
776 mswin_select_map_mode(IS_MAP_ASCII(iflags.wc_map_mode)
777 ? MAP_MODE_ASCII_FIT_TO_SCREEN
778 : MAP_MODE_TILES_FIT_TO_SCREEN);
782 case IDM_SETTING_SCREEN_TO_CLIPBOARD: {
788 p = nh_compose_ascii_screenshot();
793 if (!OpenClipboard(hWnd)) {
794 NHMessageBox(hWnd, TEXT("Cannot open clipboard"),
795 MB_OK | MB_ICONERROR);
801 hglbCopy = GlobalAlloc(GMEM_MOVEABLE, (len + 1) * sizeof(char));
802 if (hglbCopy == NULL) {
807 p_copy = (char *) GlobalLock(hglbCopy);
808 strncpy(p_copy, p, len);
809 p_copy[len] = 0; // null character
810 GlobalUnlock(hglbCopy);
812 SetClipboardData(SYMHANDLING(H_IBM) ? CF_OEMTEXT : CF_TEXT, hglbCopy);
819 case IDM_SETTING_SCREEN_TO_FILE: {
821 TCHAR filename[1024];
822 TCHAR whackdir[MAX_PATH];
828 ZeroMemory(filename, sizeof(filename));
829 ZeroMemory(&ofn, sizeof(ofn));
830 ofn.lStructSize = sizeof(OPENFILENAME);
831 ofn.hwndOwner = hWnd;
832 ofn.hInstance = GetNHApp()->hApp;
833 ofn.lpstrFilter = TEXT("Text Files (*.txt)\x0*.txt\x0")
834 TEXT("All Files (*.*)\x0*.*\x0") TEXT("\x0\x0");
835 ofn.lpstrCustomFilter = NULL;
836 ofn.nMaxCustFilter = 0;
837 ofn.nFilterIndex = 1;
838 ofn.lpstrFile = filename;
839 ofn.nMaxFile = SIZE(filename);
840 ofn.lpstrFileTitle = NULL;
841 ofn.nMaxFileTitle = 0;
842 ofn.lpstrInitialDir = NH_A2W(hackdir, whackdir, MAX_PATH);
843 ofn.lpstrTitle = NULL;
844 ofn.Flags = OFN_LONGNAMES | OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST;
846 ofn.nFileExtension = 0;
847 ofn.lpstrDefExt = TEXT("txt");
850 ofn.lpTemplateName = 0;
852 if (!GetSaveFileName(&ofn))
855 text = nh_compose_ascii_screenshot();
859 pFile = _tfopen(filename, TEXT("wt+,ccs=UTF-8"));
862 _stprintf(buf, TEXT("Cannot open %s for writing!"), filename);
863 NHMessageBox(hWnd, buf, MB_OK | MB_ICONERROR);
869 wtext = (wchar_t *) malloc(tlen * sizeof(wchar_t));
871 panic("out of memory");
872 MultiByteToWideChar(NH_CODEPAGE, 0, text, -1, wtext, tlen);
873 fwrite(wtext, tlen * sizeof(wchar_t), 1, pFile);
880 GetNHApp()->regNetHackMode = GetNHApp()->regNetHackMode ? 0 : 1;
881 mswin_menu_check_intf_mode();
884 case IDM_CLEARSETTINGS: {
886 /* Notify the user that windows settings will not be saved this time.
888 NHMessageBox(GetNHApp()->hMainWnd,
889 TEXT("Your Windows Settings will not be stored when you "
891 MB_OK | MB_ICONINFORMATION);
895 case IDM_SETTING_AUTOLAYOUT:
896 GetNHApp()->bAutoLayout = !GetNHApp()->bAutoLayout;
897 mswin_layout_main_window(NULL);
899 /* Update menu item check-mark */
900 CheckMenuItem(GetMenu(GetNHApp()->hMainWnd), IDM_SETTING_AUTOLAYOUT,
901 GetNHApp()->bAutoLayout ? MF_CHECKED : MF_UNCHECKED);
904 case IDM_SETTING_LOCKWINDOWS:
905 nhlock_windows(!GetNHApp()->bWindowsLocked);
909 display_file(HELP, TRUE);
912 case IDM_HELP_COMMANDS:
913 display_file(SHELP, TRUE);
916 case IDM_HELP_HISTORY:
920 case IDM_HELP_INFO_CHAR:
924 case IDM_HELP_INFO_KEY:
928 case IDM_HELP_OPTIONS:
932 case IDM_HELP_OPTIONS_LONG:
933 display_file(OPTIONFILE, TRUE);
936 case IDM_HELP_EXTCMD:
940 case IDM_HELP_LICENSE:
941 display_file(LICENSE, TRUE);
944 case IDM_HELP_PORTHELP:
945 display_file(PORT_HELP, TRUE);
954 // Mesage handler for about box.
956 About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
960 RECT main_rt, dlg_rt;
963 UNREFERENCED_PARAMETER(lParam);
967 getversionstring(buf);
968 SetDlgItemText(hDlg, IDC_ABOUT_VERSION,
969 NH_A2W(buf, wbuf, sizeof(wbuf)));
971 SetDlgItemText(hDlg, IDC_ABOUT_COPYRIGHT,
972 NH_A2W(COPYRIGHT_BANNER_A "\n" COPYRIGHT_BANNER_B
973 "\n" COPYRIGHT_BANNER_C
974 "\n" COPYRIGHT_BANNER_D,
977 /* center dialog in the main window */
978 GetWindowRect(GetNHApp()->hMainWnd, &main_rt);
979 GetWindowRect(hDlg, &dlg_rt);
980 dlg_sz.cx = dlg_rt.right - dlg_rt.left;
981 dlg_sz.cy = dlg_rt.bottom - dlg_rt.top;
983 dlg_rt.left = (main_rt.left + main_rt.right - dlg_sz.cx) / 2;
984 dlg_rt.right = dlg_rt.left + dlg_sz.cx;
985 dlg_rt.top = (main_rt.top + main_rt.bottom - dlg_sz.cy) / 2;
986 dlg_rt.bottom = dlg_rt.top + dlg_sz.cy;
987 MoveWindow(hDlg, (main_rt.left + main_rt.right - dlg_sz.cx) / 2,
988 (main_rt.top + main_rt.bottom - dlg_sz.cy) / 2, dlg_sz.cx,
994 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
995 EndDialog(hDlg, LOWORD(wParam));
1004 mswin_menu_check_intf_mode()
1006 HMENU hMenu = GetMenu(GetNHApp()->hMainWnd);
1008 if (GetNHApp()->regNetHackMode)
1009 CheckMenuItem(hMenu, IDM_NHMODE, MF_CHECKED);
1011 CheckMenuItem(hMenu, IDM_NHMODE, MF_UNCHECKED);
1015 mswin_select_map_mode(int mode)
1022 (PNHMainWindow) GetWindowLongPtr(GetNHApp()->hMainWnd, GWLP_USERDATA);
1024 /* override for Rogue level */
1025 if (Is_rogue_level(&u.uz) && !IS_MAP_ASCII(mode))
1028 /* set map mode menu mark */
1029 if (IS_MAP_ASCII(mode)) {
1031 GetMenu(GetNHApp()->hMainWnd), IDM_MAP_TILES, IDM_MAP_ASCII10X18,
1032 mapmode2menuid(IS_MAP_FIT_TO_SCREEN(mode) ? data->mapAcsiiModeSave
1036 CheckMenuRadioItem(GetMenu(GetNHApp()->hMainWnd), IDM_MAP_TILES,
1037 IDM_MAP_ASCII10X18, mapmode2menuid(MAP_MODE_TILES),
1041 /* set fit-to-screen mode mark */
1042 CheckMenuItem(GetMenu(GetNHApp()->hMainWnd), IDM_MAP_FIT_TO_SCREEN,
1043 MF_BYCOMMAND | (IS_MAP_FIT_TO_SCREEN(mode) ? MF_CHECKED
1046 if (IS_MAP_ASCII(iflags.wc_map_mode)
1047 && !IS_MAP_FIT_TO_SCREEN(iflags.wc_map_mode)) {
1048 data->mapAcsiiModeSave = iflags.wc_map_mode;
1051 iflags.wc_map_mode = mode;
1054 ** first, check if WIN_MAP has been inialized.
1055 ** If not - attempt to retrieve it by type, then check it again
1057 if (map_id == WIN_ERR)
1058 map_id = mswin_winid_from_type(NHW_MAP);
1059 if (map_id != WIN_ERR)
1060 mswin_map_mode(mswin_hwnd_from_winid(map_id), mode);
1063 static struct t_menu2mapmode {
1066 } _menu2mapmode[] = { { IDM_MAP_TILES, MAP_MODE_TILES },
1067 { IDM_MAP_ASCII4X6, MAP_MODE_ASCII4x6 },
1068 { IDM_MAP_ASCII6X8, MAP_MODE_ASCII6x8 },
1069 { IDM_MAP_ASCII8X8, MAP_MODE_ASCII8x8 },
1070 { IDM_MAP_ASCII16X8, MAP_MODE_ASCII16x8 },
1071 { IDM_MAP_ASCII7X12, MAP_MODE_ASCII7x12 },
1072 { IDM_MAP_ASCII8X12, MAP_MODE_ASCII8x12 },
1073 { IDM_MAP_ASCII12X16, MAP_MODE_ASCII12x16 },
1074 { IDM_MAP_ASCII16X12, MAP_MODE_ASCII16x12 },
1075 { IDM_MAP_ASCII10X18, MAP_MODE_ASCII10x18 },
1076 { IDM_MAP_FIT_TO_SCREEN, MAP_MODE_ASCII_FIT_TO_SCREEN },
1080 menuid2mapmode(int menuid)
1082 struct t_menu2mapmode *p;
1083 for (p = _menu2mapmode; p->mapMode != -1; p++)
1084 if (p->menuID == menuid)
1090 mapmode2menuid(int map_mode)
1092 struct t_menu2mapmode *p;
1093 for (p = _menu2mapmode; p->mapMode != -1; p++)
1094 if (p->mapMode == map_mode)
1100 nhlock_windows(BOOL lock)
1104 /* go through the windows list and adjust sizes */
1105 for (i = 0; i < MAXWINDOWS; i++) {
1106 if (IsWindow(GetNHApp()->windowlist[i].win)
1107 && !GetNHApp()->windowlist[i].dead) {
1109 style = GetWindowLong(GetNHApp()->windowlist[i].win, GWL_STYLE);
1111 style &= ~WS_CAPTION;
1113 style |= WS_CAPTION;
1114 SetWindowLong(GetNHApp()->windowlist[i].win, GWL_STYLE, style);
1115 SetWindowPos(GetNHApp()->windowlist[i].win, NULL, 0, 0, 0, 0,
1116 SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER
1117 | SWP_FRAMECHANGED);
1122 GetNHApp()->bWindowsLocked = lock;
1123 CheckMenuItem(GetMenu(GetNHApp()->hMainWnd), IDM_SETTING_LOCKWINDOWS,
1124 MF_BYCOMMAND | (lock ? MF_CHECKED : MF_UNCHECKED));
1127 // returns strdup() created pointer - callee assumes the ownership
1128 #define TEXT_BUFFER_SIZE 4096
1130 nh_compose_ascii_screenshot()
1133 PMSNHMsgGetText text;
1135 retval = (char *) malloc(3 * TEXT_BUFFER_SIZE);
1138 (PMSNHMsgGetText) malloc(sizeof(MSNHMsgGetText) + TEXT_BUFFER_SIZE);
1141 - 1; /* make sure we always have 0 at the end of the buffer */
1143 ZeroMemory(text->buffer, TEXT_BUFFER_SIZE);
1144 SendMessage(mswin_hwnd_from_winid(WIN_MESSAGE), WM_MSNH_COMMAND,
1145 (WPARAM) MSNH_MSG_GETTEXT, (LPARAM) text);
1146 strcpy(retval, text->buffer);
1148 ZeroMemory(text->buffer, TEXT_BUFFER_SIZE);
1149 SendMessage(mswin_hwnd_from_winid(WIN_MAP), WM_MSNH_COMMAND,
1150 (WPARAM) MSNH_MSG_GETTEXT, (LPARAM) text);
1151 strcat(retval, text->buffer);
1153 ZeroMemory(text->buffer, TEXT_BUFFER_SIZE);
1154 SendMessage(mswin_hwnd_from_winid(WIN_STATUS), WM_MSNH_COMMAND,
1155 (WPARAM) MSNH_MSG_GETTEXT, (LPARAM) text);
1156 strcat(retval, text->buffer);