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 static void mswin_apply_window_style_all();
38 // returns strdup() created pointer - callee assumes the ownership
41 mswin_init_main_window()
43 static int run_once
= 0;
47 /* register window class */
49 LoadString(GetNHApp()->hApp
, IDS_APP_TITLE
, szTitle
, MAX_LOADSTRING
);
50 register_main_window_class();
54 /* create the main window */
56 CreateWindow(szMainWindowClass
, /* registered class name */
57 szTitle
, /* window name */
58 WS_OVERLAPPEDWINDOW
| WS_CLIPCHILDREN
, /* window style */
59 CW_USEDEFAULT
, /* horizontal position of window */
60 CW_USEDEFAULT
, /* vertical position of window */
61 CW_USEDEFAULT
, /* window width */
62 CW_USEDEFAULT
, /* window height */
63 NULL
, /* handle to parent or owner window */
64 NULL
, /* menu handle or child identifier */
65 GetNHApp()->hApp
, /* handle to application instance */
66 NULL
/* window-creation data */
70 panic("Cannot create main window");
72 if (GetNHApp()->regMainMinX
!= CW_USEDEFAULT
) {
73 wp
.length
= sizeof(wp
);
74 wp
.showCmd
= GetNHApp()->regMainShowState
;
76 wp
.ptMinPosition
.x
= GetNHApp()->regMainMinX
;
77 wp
.ptMinPosition
.y
= GetNHApp()->regMainMinY
;
79 wp
.ptMaxPosition
.x
= GetNHApp()->regMainMaxX
;
80 wp
.ptMaxPosition
.y
= GetNHApp()->regMainMaxY
;
82 wp
.rcNormalPosition
.left
= GetNHApp()->regMainLeft
;
83 wp
.rcNormalPosition
.top
= GetNHApp()->regMainTop
;
84 wp
.rcNormalPosition
.right
= GetNHApp()->regMainRight
;
85 wp
.rcNormalPosition
.bottom
= GetNHApp()->regMainBottom
;
86 SetWindowPlacement(ret
, &wp
);
88 ShowWindow(ret
, SW_SHOWDEFAULT
);
95 register_main_window_class()
99 ZeroMemory(&wcex
, sizeof(wcex
));
100 wcex
.style
= CS_HREDRAW
| CS_VREDRAW
;
101 wcex
.lpfnWndProc
= (WNDPROC
) MainWndProc
;
104 wcex
.hInstance
= GetNHApp()->hApp
;
105 wcex
.hIcon
= LoadIcon(GetNHApp()->hApp
, (LPCTSTR
) IDI_NETHACKW
);
106 wcex
.hCursor
= LoadCursor(NULL
, IDC_ARROW
);
107 wcex
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1);
108 wcex
.lpszMenuName
= (TCHAR
*) IDC_NETHACKW
;
109 wcex
.lpszClassName
= szMainWindowClass
;
111 RegisterClass(&wcex
);
115 * Keypad keys are translated to the normal values below.
116 * Shifted keypad keys are translated to the
117 * shift values below.
137 static const unsigned char
138 /* normal, shift, control */
139 keypad
[KEY_LAST
][3] =
141 { 'y', 'Y', C('y') }, /* 7 */
142 { 'k', 'K', C('k') }, /* 8 */
143 { 'u', 'U', C('u') }, /* 9 */
144 { 'm', C('p'), C('p') }, /* - */
145 { 'h', 'H', C('h') }, /* 4 */
146 { 'g', 'G', 'g' }, /* 5 */
147 { 'l', 'L', C('l') }, /* 6 */
148 { '+', 'P', C('p') }, /* + */
149 { 'b', 'B', C('b') }, /* 1 */
150 { 'j', 'J', C('j') }, /* 2 */
151 { 'n', 'N', C('n') }, /* 3 */
152 { 'i', 'I', C('i') }, /* Ins */
153 { '.', ':', ':' } /* Del */
155 numpad
[KEY_LAST
][3] = {
156 { '7', M('7'), '7' }, /* 7 */
157 { '8', M('8'), '8' }, /* 8 */
158 { '9', M('9'), '9' }, /* 9 */
159 { 'm', C('p'), C('p') }, /* - */
160 { '4', M('4'), '4' }, /* 4 */
161 { '5', M('5'), '5' }, /* 5 */
162 { '6', M('6'), '6' }, /* 6 */
163 { '+', 'P', C('p') }, /* + */
164 { '1', M('1'), '1' }, /* 1 */
165 { '2', M('2'), '2' }, /* 2 */
166 { '3', M('3'), '3' }, /* 3 */
167 { '0', M('0'), '0' }, /* Ins */
168 { '.', ':', ':' } /* Del */
171 #define STATEON(x) ((GetKeyState(x) & 0xFFFE) != 0)
172 #define KEYTABLE_REGULAR(x) ((iflags.num_pad ? numpad : keypad)[x][0])
173 #define KEYTABLE_SHIFT(x) ((iflags.num_pad ? numpad : keypad)[x][1])
174 #define KEYTABLE(x) \
175 (STATEON(VK_SHIFT) ? KEYTABLE_SHIFT(x) : KEYTABLE_REGULAR(x))
177 static const char *extendedlist
= "acdefijlmnopqrstuvw?2";
180 static const char scanmap
[] = {
182 '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 0, 0, 0, 0, 'q', 'w',
183 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', 0, 'a', 's', 'd',
184 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', 0, '\\', 'z', 'x', 'c', 'v',
185 'b', 'n', 'm', ',', '.', '?' /* ... */
189 // FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
191 // PURPOSE: Processes messages for the main window.
194 MainWndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
200 /* set window data */
201 data
= (PNHMainWindow
) malloc(sizeof(NHMainWindow
));
203 panic("out of memory");
204 ZeroMemory(data
, sizeof(NHMainWindow
));
205 data
->mapAcsiiModeSave
= MAP_MODE_ASCII12x16
;
206 SetWindowLongPtr(hWnd
, GWLP_USERDATA
, (LONG_PTR
) data
);
208 /* update menu items */
210 GetMenu(hWnd
), IDM_SETTING_LOCKWINDOWS
,
212 | (GetNHApp()->bWindowsLocked
? MF_CHECKED
: MF_UNCHECKED
));
214 CheckMenuItem(GetMenu(hWnd
), IDM_SETTING_AUTOLAYOUT
,
215 GetNHApp()->bAutoLayout
? MF_CHECKED
: MF_UNCHECKED
);
217 /* store handle to the mane menu in the application record */
218 GetNHApp()->hMainWnd
= hWnd
;
221 case WM_MSNH_COMMAND
:
222 onMSNHCommand(hWnd
, wParam
, lParam
);
226 data
= (PNHMainWindow
) GetWindowLongPtr(hWnd
, GWLP_USERDATA
);
228 /* translate arrow keys into nethack commands */
231 if (STATEON(VK_CONTROL
)) {
232 /* scroll map window one line left */
233 SendMessage(mswin_hwnd_from_winid(WIN_MAP
), WM_HSCROLL
,
234 MAKEWPARAM(SB_LINEUP
, 0), (LPARAM
) NULL
);
236 NHEVENT_KBD(KEYTABLE(KEY_W
));
241 if (STATEON(VK_CONTROL
)) {
242 /* scroll map window one line right */
243 SendMessage(mswin_hwnd_from_winid(WIN_MAP
), WM_HSCROLL
,
244 MAKEWPARAM(SB_LINEDOWN
, 0), (LPARAM
) NULL
);
246 NHEVENT_KBD(KEYTABLE(KEY_E
));
251 if (STATEON(VK_CONTROL
)) {
252 /* scroll map window one line up */
253 SendMessage(mswin_hwnd_from_winid(WIN_MAP
), WM_VSCROLL
,
254 MAKEWPARAM(SB_LINEUP
, 0), (LPARAM
) NULL
);
256 NHEVENT_KBD(KEYTABLE(KEY_N
));
261 if (STATEON(VK_CONTROL
)) {
262 /* scroll map window one line down */
263 SendMessage(mswin_hwnd_from_winid(WIN_MAP
), WM_VSCROLL
,
264 MAKEWPARAM(SB_LINEDOWN
, 0), (LPARAM
) NULL
);
266 NHEVENT_KBD(KEYTABLE(KEY_S
));
271 if (STATEON(VK_CONTROL
)) {
272 /* scroll map window to upper left corner */
273 SendMessage(mswin_hwnd_from_winid(WIN_MAP
), WM_VSCROLL
,
274 MAKEWPARAM(SB_THUMBTRACK
, 0), (LPARAM
) NULL
);
276 SendMessage(mswin_hwnd_from_winid(WIN_MAP
), WM_HSCROLL
,
277 MAKEWPARAM(SB_THUMBTRACK
, 0), (LPARAM
) NULL
);
279 NHEVENT_KBD(KEYTABLE(KEY_NW
));
284 if (STATEON(VK_CONTROL
)) {
285 /* scroll map window to lower right corner */
286 SendMessage(mswin_hwnd_from_winid(WIN_MAP
), WM_VSCROLL
,
287 MAKEWPARAM(SB_THUMBTRACK
, ROWNO
), (LPARAM
) NULL
);
289 SendMessage(mswin_hwnd_from_winid(WIN_MAP
), WM_HSCROLL
,
290 MAKEWPARAM(SB_THUMBTRACK
, COLNO
), (LPARAM
) NULL
);
292 NHEVENT_KBD(KEYTABLE(KEY_SW
));
297 if (STATEON(VK_CONTROL
)) {
298 /* scroll map window one page up */
299 SendMessage(mswin_hwnd_from_winid(WIN_MAP
), WM_VSCROLL
,
300 MAKEWPARAM(SB_PAGEUP
, 0), (LPARAM
) NULL
);
302 NHEVENT_KBD(KEYTABLE(KEY_NE
));
307 if (STATEON(VK_CONTROL
)) {
308 /* scroll map window one page down */
309 SendMessage(mswin_hwnd_from_winid(WIN_MAP
), WM_VSCROLL
,
310 MAKEWPARAM(SB_PAGEDOWN
, 0), (LPARAM
) NULL
);
312 NHEVENT_KBD(KEYTABLE(KEY_SE
));
318 NHEVENT_KBD(KEYTABLE(KEY_WAITLOOK
));
322 NHEVENT_KBD(KEYTABLE(KEY_INV
));
326 NHEVENT_KBD(KEYTABLE(KEY_MINUS
));
330 NHEVENT_KBD(KEYTABLE(KEY_PLUS
));
333 case VK_CLEAR
: /* This is the '5' key */
334 NHEVENT_KBD(KEYTABLE(KEY_GOINTERESTING
));
338 if (IS_MAP_FIT_TO_SCREEN(iflags
.wc_map_mode
)) {
339 mswin_select_map_mode(IS_MAP_ASCII(iflags
.wc_map_mode
)
340 ? data
->mapAcsiiModeSave
343 mswin_select_map_mode(IS_MAP_ASCII(iflags
.wc_map_mode
)
344 ? MAP_MODE_ASCII_FIT_TO_SCREEN
345 : MAP_MODE_TILES_FIT_TO_SCREEN
);
350 if (IS_MAP_ASCII(iflags
.wc_map_mode
)) {
351 if (IS_MAP_FIT_TO_SCREEN(iflags
.wc_map_mode
)) {
352 mswin_select_map_mode(MAP_MODE_TILES_FIT_TO_SCREEN
);
354 mswin_select_map_mode(MAP_MODE_TILES
);
357 if (IS_MAP_FIT_TO_SCREEN(iflags
.wc_map_mode
)) {
358 mswin_select_map_mode(MAP_MODE_ASCII_FIT_TO_SCREEN
);
360 mswin_select_map_mode(data
->mapAcsiiModeSave
);
370 ZeroMemory(kbd_state
, sizeof(kbd_state
));
371 GetKeyboardState(kbd_state
);
373 if (ToAscii(wParam
, (lParam
>> 16) & 0xFF, kbd_state
, &c
, 0)) {
374 NHEVENT_KBD(c
& 0xFF);
384 case WM_SYSCHAR
: /* Alt-char pressed */
387 If not nethackmode, don't handle Alt-keys here.
388 If no Alt-key pressed it can never be an extended command
390 if (GetNHApp()->regNetHackMode
&& ((lParam
& 1 << 29) != 0)) {
391 unsigned char c
= (unsigned char) (wParam
& 0xFF);
392 unsigned char scancode
= (lParam
>> 16) & 0xFF;
393 if (index(extendedlist
, tolower(c
)) != 0) {
394 NHEVENT_KBD(M(tolower(c
)));
395 } else if (scancode
== (SCANLO
+ SIZE(scanmap
)) - 1) {
400 return DefWindowProc(hWnd
, message
, wParam
, lParam
);
404 /* process commands - menu commands mostly */
405 if (onWMCommand(hWnd
, wParam
, lParam
))
406 return DefWindowProc(hWnd
, message
, wParam
, lParam
);
414 mswin_layout_main_window(NULL
);
416 wp
.length
= sizeof(wp
);
417 if (GetWindowPlacement(hWnd
, &wp
)) {
418 GetNHApp()->regMainShowState
=
419 (wp
.showCmd
== SW_SHOWMAXIMIZED
? SW_SHOWMAXIMIZED
422 GetNHApp()->regMainMinX
= wp
.ptMinPosition
.x
;
423 GetNHApp()->regMainMinY
= wp
.ptMinPosition
.y
;
425 GetNHApp()->regMainMaxX
= wp
.ptMaxPosition
.x
;
426 GetNHApp()->regMainMaxY
= wp
.ptMaxPosition
.y
;
428 GetNHApp()->regMainLeft
= wp
.rcNormalPosition
.left
;
429 GetNHApp()->regMainTop
= wp
.rcNormalPosition
.top
;
430 GetNHApp()->regMainRight
= wp
.rcNormalPosition
.right
;
431 GetNHApp()->regMainBottom
= wp
.rcNormalPosition
.bottom
;
436 /* if there is a menu window out there -
437 transfer input focus to it */
438 if (IsWindow(GetNHApp()->hPopupWnd
)) {
439 SetFocus(GetNHApp()->hPopupWnd
);
444 /* exit gracefully */
445 if (program_state
.gameover
) {
446 /* assume the user really meant this, as the game is already
448 /* to make sure we still save bones, just set stop printing flag
450 program_state
.stopprint
++;
452 '\033'); /* and send keyboard input as if user pressed ESC */
453 /* additional code for this is done in menu and rip windows */
454 } else if (!program_state
.something_worth_saving
) {
455 /* User exited before the game started, e.g. during splash display
460 /* prompt user for action */
461 switch (NHMessageBox(hWnd
, TEXT("Save?"),
462 MB_YESNOCANCEL
| MB_ICONQUESTION
)) {
465 /* destroy popup window - it has its own loop and we need to
466 return control to NetHack core at this point */
467 if (IsWindow(GetNHApp()->hPopupWnd
))
468 SendMessage(GetNHApp()->hPopupWnd
, WM_COMMAND
, IDCANCEL
,
471 /* tell NetHack core that "hangup" is requested */
490 /* apparently we never get here
491 TODO: work on exit routines - need to send
495 free((PNHMainWindow
) GetWindowLongPtr(hWnd
, GWLP_USERDATA
));
496 SetWindowLongPtr(hWnd
, GWLP_USERDATA
, (LONG_PTR
) 0);
498 // PostQuitMessage(0);
503 return DefWindowProc(hWnd
, message
, wParam
, lParam
);
509 onMSNHCommand(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
511 UNREFERENCED_PARAMETER(hWnd
);
512 UNREFERENCED_PARAMETER(wParam
);
513 UNREFERENCED_PARAMETER(lParam
);
516 /* new window was just added */
517 case MSNH_MSG_ADDWND
: {
518 PMSNHMsgAddWnd msg_param
= (PMSNHMsgAddWnd
) lParam
;
521 if (GetNHApp()->windowlist
[msg_param
->wid
].type
== NHW_MAP
)
522 mswin_select_map_mode(iflags
.wc_map_mode
);
524 child
= GetNHApp()->windowlist
[msg_param
->wid
].win
;
529 /* adjust windows to fit main window layout
530 ---------------------------
532 +-------------------------+
538 +-------------------------+
540 ---------------------------
543 mswin_layout_main_window(HWND changed_child
)
546 RECT client_rt
, wnd_rect
;
554 HWND wnd_status
, wnd_msg
;
557 if (GetNHApp()->bAutoLayout
) {
558 GetClientRect(GetNHApp()->hMainWnd
, &client_rt
);
559 data
= (PNHMainWindow
) GetWindowLongPtr(GetNHApp()->hMainWnd
,
562 /* get sizes of child windows */
563 wnd_status
= mswin_hwnd_from_winid(WIN_STATUS
);
564 if (IsWindow(wnd_status
)) {
565 mswin_status_window_size(wnd_status
, &status_size
);
567 status_size
.cx
= status_size
.cy
= 0;
570 wnd_msg
= mswin_hwnd_from_winid(WIN_MESSAGE
);
571 if (IsWindow(wnd_msg
)) {
572 mswin_message_window_size(wnd_msg
, &msg_size
);
574 msg_size
.cx
= msg_size
.cy
= 0;
577 /* find all menu windows and calculate the size */
578 menu_size
.cx
= menu_size
.cy
= 0;
579 for (i
= 0; i
< MAXWINDOWS
; i
++) {
581 if (GetNHApp()->windowlist
[i
].win
582 && !GetNHApp()->windowlist
[i
].dead
583 && GetNHApp()->windowlist
[i
].type
== NHW_MENU
) {
584 mswin_menu_window_size(GetNHApp()->windowlist
[i
].win
,
586 menu_size
.cx
= max(menu_size
.cx
, tmp_size
.cx
);
587 menu_size
.cy
= max(menu_size
.cy
, tmp_size
.cy
);
591 /* set window positions */
592 SetRect(&wnd_rect
, client_rt
.left
, client_rt
.top
, client_rt
.right
,
594 switch (iflags
.wc_align_status
) {
596 status_size
.cx
= (wnd_rect
.right
- wnd_rect
.left
) / 4;
598 (wnd_rect
.bottom
- wnd_rect
.top
); // that won't look good
599 status_org
.x
= wnd_rect
.left
;
600 status_org
.y
= wnd_rect
.top
;
601 wnd_rect
.left
+= status_size
.cx
;
605 status_size
.cx
= (wnd_rect
.right
- wnd_rect
.left
) / 4;
607 (wnd_rect
.bottom
- wnd_rect
.top
); // that won't look good
608 status_org
.x
= wnd_rect
.right
- status_size
.cx
;
609 status_org
.y
= wnd_rect
.top
;
610 wnd_rect
.right
-= status_size
.cx
;
614 status_size
.cx
= (wnd_rect
.right
- wnd_rect
.left
);
615 status_org
.x
= wnd_rect
.left
;
616 status_org
.y
= wnd_rect
.top
;
617 wnd_rect
.top
+= status_size
.cy
;
622 status_size
.cx
= (wnd_rect
.right
- wnd_rect
.left
);
623 status_org
.x
= wnd_rect
.left
;
624 status_org
.y
= wnd_rect
.bottom
- status_size
.cy
;
625 wnd_rect
.bottom
-= status_size
.cy
;
629 switch (iflags
.wc_align_message
) {
631 msg_size
.cx
= (wnd_rect
.right
- wnd_rect
.left
) / 4;
632 msg_size
.cy
= (wnd_rect
.bottom
- wnd_rect
.top
);
633 msg_org
.x
= wnd_rect
.left
;
634 msg_org
.y
= wnd_rect
.top
;
635 wnd_rect
.left
+= msg_size
.cx
;
639 msg_size
.cx
= (wnd_rect
.right
- wnd_rect
.left
) / 4;
640 msg_size
.cy
= (wnd_rect
.bottom
- wnd_rect
.top
);
641 msg_org
.x
= wnd_rect
.right
- msg_size
.cx
;
642 msg_org
.y
= wnd_rect
.top
;
643 wnd_rect
.right
-= msg_size
.cx
;
647 msg_size
.cx
= (wnd_rect
.right
- wnd_rect
.left
);
648 msg_org
.x
= wnd_rect
.left
;
649 msg_org
.y
= wnd_rect
.top
;
650 wnd_rect
.top
+= msg_size
.cy
;
655 msg_size
.cx
= (wnd_rect
.right
- wnd_rect
.left
);
656 msg_org
.x
= wnd_rect
.left
;
657 msg_org
.y
= wnd_rect
.bottom
- msg_size
.cy
;
658 wnd_rect
.bottom
-= msg_size
.cy
;
663 map_org
.x
= wnd_rect
.left
;
664 map_org
.y
= wnd_rect
.top
;
665 map_size
.cx
= wnd_rect
.right
- wnd_rect
.left
;
666 map_size
.cy
= wnd_rect
.bottom
- wnd_rect
.top
;
668 GetNHApp()->rtStatusWindow
.left
= status_org
.x
;
669 GetNHApp()->rtStatusWindow
.top
= status_org
.y
;
670 GetNHApp()->rtStatusWindow
.right
= status_org
.x
+ status_size
.cx
;
671 GetNHApp()->rtStatusWindow
.bottom
= status_org
.y
+ status_size
.cy
;
673 GetNHApp()->rtTextWindow
.left
= map_org
.x
;
674 GetNHApp()->rtTextWindow
.top
= map_org
.y
;
675 GetNHApp()->rtTextWindow
.right
=
676 map_org
.x
+ (wnd_rect
.right
- wnd_rect
.left
);
677 GetNHApp()->rtTextWindow
.bottom
= map_org
.y
+ map_size
.cy
;
679 GetNHApp()->rtMapWindow
.left
= map_org
.x
;
680 GetNHApp()->rtMapWindow
.top
= map_org
.y
;
681 GetNHApp()->rtMapWindow
.right
= map_org
.x
+ map_size
.cx
;
682 GetNHApp()->rtMapWindow
.bottom
= map_org
.y
+ map_size
.cy
;
684 GetNHApp()->rtMsgWindow
.left
= msg_org
.x
;
685 GetNHApp()->rtMsgWindow
.top
= msg_org
.y
;
686 GetNHApp()->rtMsgWindow
.right
= msg_org
.x
+ msg_size
.cx
;
687 GetNHApp()->rtMsgWindow
.bottom
= msg_org
.y
+ msg_size
.cy
;
689 /* map_width/4 < menu_width < map_width*2/3 */
690 GetNHApp()->rtMenuWindow
.left
=
691 GetNHApp()->rtMapWindow
.right
692 - min(map_size
.cx
* 2 / 3, max(map_size
.cx
/ 4, menu_size
.cx
));
693 GetNHApp()->rtMenuWindow
.top
= GetNHApp()->rtMapWindow
.top
;
694 GetNHApp()->rtMenuWindow
.right
= GetNHApp()->rtMapWindow
.right
;
695 GetNHApp()->rtMenuWindow
.bottom
= GetNHApp()->rtMapWindow
.bottom
;
697 GetNHApp()->rtInvenWindow
.left
= GetNHApp()->rtMenuWindow
.left
;
698 GetNHApp()->rtInvenWindow
.top
= GetNHApp()->rtMenuWindow
.top
;
699 GetNHApp()->rtInvenWindow
.right
= GetNHApp()->rtMenuWindow
.right
;
700 GetNHApp()->rtInvenWindow
.bottom
= GetNHApp()->rtMenuWindow
.bottom
;
702 /* adjust map window size only if perm_invent is set */
703 if (flags
.perm_invent
)
704 GetNHApp()->rtMapWindow
.right
= GetNHApp()->rtMenuWindow
.left
;
707 /* go through the windows list and adjust sizes */
708 for (i
= 0; i
< MAXWINDOWS
; i
++) {
709 if (GetNHApp()->windowlist
[i
].win
710 && !GetNHApp()->windowlist
[i
].dead
) {
712 /* kludge - inventory window should have its own type (same as
714 as a matter of fact) */
715 if (flags
.perm_invent
&& i
== WIN_INVEN
) {
716 mswin_get_window_placement(NHW_INVEN
, &rt
);
718 mswin_get_window_placement(GetNHApp()->windowlist
[i
].type
,
722 MoveWindow(GetNHApp()->windowlist
[i
].win
, rt
.left
, rt
.top
,
723 rt
.right
- rt
.left
, rt
.bottom
- rt
.top
, TRUE
);
726 if (IsWindow(changed_child
))
727 SetForegroundWindow(changed_child
);
731 onWMCommand(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
736 UNREFERENCED_PARAMETER(lParam
);
738 data
= (PNHMainWindow
) GetWindowLongPtr(hWnd
, GWLP_USERDATA
);
739 wmId
= LOWORD(wParam
);
740 wmEvent
= HIWORD(wParam
);
742 // Parse the menu selections:
745 mswin_display_splash_window(TRUE
);
753 if (!program_state
.gameover
&& !program_state
.done_hup
)
760 case IDM_MAP_ASCII4X6
:
761 case IDM_MAP_ASCII6X8
:
762 case IDM_MAP_ASCII8X8
:
763 case IDM_MAP_ASCII16X8
:
764 case IDM_MAP_ASCII7X12
:
765 case IDM_MAP_ASCII8X12
:
766 case IDM_MAP_ASCII12X16
:
767 case IDM_MAP_ASCII16X12
:
768 case IDM_MAP_ASCII10X18
:
769 mswin_select_map_mode(menuid2mapmode(wmId
));
772 case IDM_MAP_FIT_TO_SCREEN
:
773 if (IS_MAP_FIT_TO_SCREEN(iflags
.wc_map_mode
)) {
774 mswin_select_map_mode(IS_MAP_ASCII(iflags
.wc_map_mode
)
775 ? data
->mapAcsiiModeSave
778 mswin_select_map_mode(IS_MAP_ASCII(iflags
.wc_map_mode
)
779 ? MAP_MODE_ASCII_FIT_TO_SCREEN
780 : MAP_MODE_TILES_FIT_TO_SCREEN
);
784 case IDM_SETTING_SCREEN_TO_CLIPBOARD
: {
790 p
= nh_compose_ascii_screenshot();
795 if (!OpenClipboard(hWnd
)) {
796 NHMessageBox(hWnd
, TEXT("Cannot open clipboard"),
797 MB_OK
| MB_ICONERROR
);
803 hglbCopy
= GlobalAlloc(GMEM_MOVEABLE
, (len
+ 1) * sizeof(char));
804 if (hglbCopy
== NULL
) {
809 p_copy
= (char *) GlobalLock(hglbCopy
);
810 strncpy(p_copy
, p
, len
);
811 p_copy
[len
] = 0; // null character
812 GlobalUnlock(hglbCopy
);
814 SetClipboardData(SYMHANDLING(H_IBM
) ? CF_OEMTEXT
: CF_TEXT
, hglbCopy
);
821 case IDM_SETTING_SCREEN_TO_FILE
: {
823 TCHAR filename
[1024];
824 TCHAR whackdir
[MAX_PATH
];
830 ZeroMemory(filename
, sizeof(filename
));
831 ZeroMemory(&ofn
, sizeof(ofn
));
832 ofn
.lStructSize
= sizeof(OPENFILENAME
);
833 ofn
.hwndOwner
= hWnd
;
834 ofn
.hInstance
= GetNHApp()->hApp
;
835 ofn
.lpstrFilter
= TEXT("Text Files (*.txt)\x0*.txt\x0")
836 TEXT("All Files (*.*)\x0*.*\x0") TEXT("\x0\x0");
837 ofn
.lpstrCustomFilter
= NULL
;
838 ofn
.nMaxCustFilter
= 0;
839 ofn
.nFilterIndex
= 1;
840 ofn
.lpstrFile
= filename
;
841 ofn
.nMaxFile
= SIZE(filename
);
842 ofn
.lpstrFileTitle
= NULL
;
843 ofn
.nMaxFileTitle
= 0;
844 ofn
.lpstrInitialDir
= NH_A2W(hackdir
, whackdir
, MAX_PATH
);
845 ofn
.lpstrTitle
= NULL
;
846 ofn
.Flags
= OFN_LONGNAMES
| OFN_OVERWRITEPROMPT
| OFN_PATHMUSTEXIST
;
848 ofn
.nFileExtension
= 0;
849 ofn
.lpstrDefExt
= TEXT("txt");
852 ofn
.lpTemplateName
= 0;
854 if (!GetSaveFileName(&ofn
))
857 text
= nh_compose_ascii_screenshot();
861 pFile
= _tfopen(filename
, TEXT("wt+,ccs=UTF-8"));
864 _stprintf(buf
, TEXT("Cannot open %s for writing!"), filename
);
865 NHMessageBox(hWnd
, buf
, MB_OK
| MB_ICONERROR
);
871 wtext
= (wchar_t *) malloc(tlen
* sizeof(wchar_t));
873 panic("out of memory");
874 MultiByteToWideChar(NH_CODEPAGE
, 0, text
, -1, wtext
, tlen
);
875 fwrite(wtext
, tlen
* sizeof(wchar_t), 1, pFile
);
882 GetNHApp()->regNetHackMode
= GetNHApp()->regNetHackMode
? 0 : 1;
883 mswin_menu_check_intf_mode();
884 mswin_apply_window_style_all();
887 case IDM_CLEARSETTINGS
: {
889 /* Notify the user that windows settings will not be saved this time.
891 NHMessageBox(GetNHApp()->hMainWnd
,
892 TEXT("Your Windows Settings will not be stored when you "
894 MB_OK
| MB_ICONINFORMATION
);
898 case IDM_SETTING_AUTOLAYOUT
:
899 GetNHApp()->bAutoLayout
= !GetNHApp()->bAutoLayout
;
900 mswin_layout_main_window(NULL
);
902 /* Update menu item check-mark */
903 CheckMenuItem(GetMenu(GetNHApp()->hMainWnd
), IDM_SETTING_AUTOLAYOUT
,
904 GetNHApp()->bAutoLayout
? MF_CHECKED
: MF_UNCHECKED
);
907 case IDM_SETTING_LOCKWINDOWS
:
908 nhlock_windows(!GetNHApp()->bWindowsLocked
);
912 display_file(HELP
, TRUE
);
915 case IDM_HELP_COMMANDS
:
916 display_file(SHELP
, TRUE
);
919 case IDM_HELP_HISTORY
:
923 case IDM_HELP_INFO_CHAR
:
927 case IDM_HELP_INFO_KEY
:
931 case IDM_HELP_OPTIONS
:
935 case IDM_HELP_OPTIONS_LONG
:
936 display_file(OPTIONFILE
, TRUE
);
939 case IDM_HELP_EXTCMD
:
943 case IDM_HELP_LICENSE
:
944 display_file(LICENSE
, TRUE
);
947 case IDM_HELP_PORTHELP
:
948 display_file(PORT_HELP
, TRUE
);
957 // Mesage handler for about box.
959 About(HWND hDlg
, UINT message
, WPARAM wParam
, LPARAM lParam
)
963 RECT main_rt
, dlg_rt
;
966 UNREFERENCED_PARAMETER(lParam
);
970 getversionstring(buf
);
971 SetDlgItemText(hDlg
, IDC_ABOUT_VERSION
,
972 NH_A2W(buf
, wbuf
, sizeof(wbuf
)));
974 SetDlgItemText(hDlg
, IDC_ABOUT_COPYRIGHT
,
975 NH_A2W(COPYRIGHT_BANNER_A
"\n" COPYRIGHT_BANNER_B
976 "\n" COPYRIGHT_BANNER_C
977 "\n" COPYRIGHT_BANNER_D
,
980 /* center dialog in the main window */
981 GetWindowRect(GetNHApp()->hMainWnd
, &main_rt
);
982 GetWindowRect(hDlg
, &dlg_rt
);
983 dlg_sz
.cx
= dlg_rt
.right
- dlg_rt
.left
;
984 dlg_sz
.cy
= dlg_rt
.bottom
- dlg_rt
.top
;
986 dlg_rt
.left
= (main_rt
.left
+ main_rt
.right
- dlg_sz
.cx
) / 2;
987 dlg_rt
.right
= dlg_rt
.left
+ dlg_sz
.cx
;
988 dlg_rt
.top
= (main_rt
.top
+ main_rt
.bottom
- dlg_sz
.cy
) / 2;
989 dlg_rt
.bottom
= dlg_rt
.top
+ dlg_sz
.cy
;
990 MoveWindow(hDlg
, (main_rt
.left
+ main_rt
.right
- dlg_sz
.cx
) / 2,
991 (main_rt
.top
+ main_rt
.bottom
- dlg_sz
.cy
) / 2, dlg_sz
.cx
,
997 if (LOWORD(wParam
) == IDOK
|| LOWORD(wParam
) == IDCANCEL
) {
998 EndDialog(hDlg
, LOWORD(wParam
));
1007 mswin_menu_check_intf_mode()
1009 HMENU hMenu
= GetMenu(GetNHApp()->hMainWnd
);
1011 if (GetNHApp()->regNetHackMode
)
1012 CheckMenuItem(hMenu
, IDM_NHMODE
, MF_CHECKED
);
1014 CheckMenuItem(hMenu
, IDM_NHMODE
, MF_UNCHECKED
);
1018 mswin_select_map_mode(int mode
)
1025 (PNHMainWindow
) GetWindowLongPtr(GetNHApp()->hMainWnd
, GWLP_USERDATA
);
1027 /* override for Rogue level */
1028 if (Is_rogue_level(&u
.uz
) && !IS_MAP_ASCII(mode
))
1031 /* set map mode menu mark */
1032 if (IS_MAP_ASCII(mode
)) {
1034 GetMenu(GetNHApp()->hMainWnd
), IDM_MAP_TILES
, IDM_MAP_ASCII10X18
,
1035 mapmode2menuid(IS_MAP_FIT_TO_SCREEN(mode
) ? data
->mapAcsiiModeSave
1039 CheckMenuRadioItem(GetMenu(GetNHApp()->hMainWnd
), IDM_MAP_TILES
,
1040 IDM_MAP_ASCII10X18
, mapmode2menuid(MAP_MODE_TILES
),
1044 /* set fit-to-screen mode mark */
1045 CheckMenuItem(GetMenu(GetNHApp()->hMainWnd
), IDM_MAP_FIT_TO_SCREEN
,
1046 MF_BYCOMMAND
| (IS_MAP_FIT_TO_SCREEN(mode
) ? MF_CHECKED
1049 if (IS_MAP_ASCII(iflags
.wc_map_mode
)
1050 && !IS_MAP_FIT_TO_SCREEN(iflags
.wc_map_mode
)) {
1051 data
->mapAcsiiModeSave
= iflags
.wc_map_mode
;
1054 iflags
.wc_map_mode
= mode
;
1057 ** first, check if WIN_MAP has been inialized.
1058 ** If not - attempt to retrieve it by type, then check it again
1060 if (map_id
== WIN_ERR
)
1061 map_id
= mswin_winid_from_type(NHW_MAP
);
1062 if (map_id
!= WIN_ERR
)
1063 mswin_map_mode(mswin_hwnd_from_winid(map_id
), mode
);
1066 static struct t_menu2mapmode
{
1069 } _menu2mapmode
[] = { { IDM_MAP_TILES
, MAP_MODE_TILES
},
1070 { IDM_MAP_ASCII4X6
, MAP_MODE_ASCII4x6
},
1071 { IDM_MAP_ASCII6X8
, MAP_MODE_ASCII6x8
},
1072 { IDM_MAP_ASCII8X8
, MAP_MODE_ASCII8x8
},
1073 { IDM_MAP_ASCII16X8
, MAP_MODE_ASCII16x8
},
1074 { IDM_MAP_ASCII7X12
, MAP_MODE_ASCII7x12
},
1075 { IDM_MAP_ASCII8X12
, MAP_MODE_ASCII8x12
},
1076 { IDM_MAP_ASCII12X16
, MAP_MODE_ASCII12x16
},
1077 { IDM_MAP_ASCII16X12
, MAP_MODE_ASCII16x12
},
1078 { IDM_MAP_ASCII10X18
, MAP_MODE_ASCII10x18
},
1079 { IDM_MAP_FIT_TO_SCREEN
, MAP_MODE_ASCII_FIT_TO_SCREEN
},
1083 menuid2mapmode(int menuid
)
1085 struct t_menu2mapmode
*p
;
1086 for (p
= _menu2mapmode
; p
->mapMode
!= -1; p
++)
1087 if (p
->menuID
== menuid
)
1093 mapmode2menuid(int map_mode
)
1095 struct t_menu2mapmode
*p
;
1096 for (p
= _menu2mapmode
; p
->mapMode
!= -1; p
++)
1097 if (p
->mapMode
== map_mode
)
1103 nhlock_windows(BOOL lock
)
1106 GetNHApp()->bWindowsLocked
= lock
;
1107 CheckMenuItem(GetMenu(GetNHApp()->hMainWnd
), IDM_SETTING_LOCKWINDOWS
,
1108 MF_BYCOMMAND
| (lock
? MF_CHECKED
: MF_UNCHECKED
));
1110 /* restyle windows */
1111 mswin_apply_window_style_all();
1115 mswin_apply_window_style(HWND hwnd
) {
1116 DWORD style
= 0, exstyle
= 0;
1118 style
= GetWindowLong(hwnd
, GWL_STYLE
);
1119 exstyle
= GetWindowLong(hwnd
, GWL_EXSTYLE
);
1121 if( !GetNHApp()->bWindowsLocked
) {
1122 style
= WS_CHILD
|WS_CLIPSIBLINGS
|WS_CAPTION
|WS_SIZEBOX
|(style
& (WS_VISIBLE
|WS_VSCROLL
|WS_HSCROLL
));
1123 exstyle
= WS_EX_WINDOWEDGE
;
1124 } else if (GetNHApp()->regNetHackMode
) {
1125 /* do away borders */
1126 style
= WS_CHILD
|WS_CLIPSIBLINGS
|(style
& (WS_VISIBLE
|WS_VSCROLL
|WS_HSCROLL
));
1129 style
= WS_CHILD
|WS_CLIPSIBLINGS
|WS_THICKFRAME
|(style
& (WS_VISIBLE
|WS_VSCROLL
|WS_HSCROLL
));
1130 exstyle
= WS_EX_WINDOWEDGE
;
1133 SetWindowLong(hwnd
, GWL_STYLE
, style
);
1134 SetWindowLong(hwnd
, GWL_EXSTYLE
, exstyle
);
1135 SetWindowPos(hwnd
, NULL
, 0, 0, 0, 0,
1136 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
| SWP_FRAMECHANGED
| SWP_NOCOPYBITS
);
1140 mswin_apply_window_style_all() {
1142 for (i
= 0; i
< MAXWINDOWS
; i
++) {
1143 if (IsWindow(GetNHApp()->windowlist
[i
].win
)
1144 && !GetNHApp()->windowlist
[i
].dead
) {
1145 mswin_apply_window_style(GetNHApp()->windowlist
[i
].win
);
1148 mswin_layout_main_window(NULL
);
1151 // returns strdup() created pointer - callee assumes the ownership
1152 #define TEXT_BUFFER_SIZE 4096
1154 nh_compose_ascii_screenshot()
1157 PMSNHMsgGetText text
;
1159 retval
= (char *) malloc(3 * TEXT_BUFFER_SIZE
);
1162 (PMSNHMsgGetText
) malloc(sizeof(MSNHMsgGetText
) + TEXT_BUFFER_SIZE
);
1165 - 1; /* make sure we always have 0 at the end of the buffer */
1167 ZeroMemory(text
->buffer
, TEXT_BUFFER_SIZE
);
1168 SendMessage(mswin_hwnd_from_winid(WIN_MESSAGE
), WM_MSNH_COMMAND
,
1169 (WPARAM
) MSNH_MSG_GETTEXT
, (LPARAM
) text
);
1170 strcpy(retval
, text
->buffer
);
1172 ZeroMemory(text
->buffer
, TEXT_BUFFER_SIZE
);
1173 SendMessage(mswin_hwnd_from_winid(WIN_MAP
), WM_MSNH_COMMAND
,
1174 (WPARAM
) MSNH_MSG_GETTEXT
, (LPARAM
) text
);
1175 strcat(retval
, text
->buffer
);
1177 ZeroMemory(text
->buffer
, TEXT_BUFFER_SIZE
);
1178 SendMessage(mswin_hwnd_from_winid(WIN_STATUS
), WM_MSNH_COMMAND
,
1179 (WPARAM
) MSNH_MSG_GETTEXT
, (LPARAM
) text
);
1180 strcat(retval
, text
->buffer
);