1 /* Copyright (C) 2001 by Alex Kompel <shurikk@pacbell.net> */
2 /* NetHack may be freely redistributed. See license for details. */
3
4 #include "winMS.h"
5 #include "patchlevel.h"
6 #include "resource.h"
7 #include "mhmsg.h"
8 #include "mhinput.h"
9 #include "mhmain.h"
10 #include "mhmenu.h"
11 #include "mhstatus.h"
12 #include "mhmsgwnd.h"
13 #include "mhmap.h"
14
15 typedef struct mswin_nethack_main_window {
16 int mapAcsiiModeSave;
17 } NHMainWindow, *PNHMainWindow;
18
19 static TCHAR szMainWindowClass[] = TEXT("MSNHMainWndClass");
20 static TCHAR szTitle[MAX_LOADSTRING];
21 extern void mswin_display_splash_window(BOOL);
22
23 LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);
24 LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
25 static LRESULT onWMCommand(HWND hWnd, WPARAM wParam, LPARAM lParam);
26 static void onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam);
27 static void register_main_window_class(void);
28 static int menuid2mapmode(int menuid);
29 static int mapmode2menuid(int map_mode);
30
mswin_init_main_window()31 HWND mswin_init_main_window () {
32 static int run_once = 0;
33 HWND ret;
34 WINDOWPLACEMENT wp;
35
36 /* register window class */
37 if( !run_once ) {
38 LoadString(GetNHApp()->hApp, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
39 register_main_window_class( );
40 run_once = 1;
41 }
42
43 /* create the main window */
44 ret = CreateWindow(
45 szMainWindowClass, /* registered class name */
46 szTitle, /* window name */
47 WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, /* window style */
48 CW_USEDEFAULT, /* horizontal position of window */
49 CW_USEDEFAULT, /* vertical position of window */
50 CW_USEDEFAULT, /* window width */
51 CW_USEDEFAULT, /* window height */
52 NULL, /* handle to parent or owner window */
53 NULL, /* menu handle or child identifier */
54 GetNHApp()->hApp, /* handle to application instance */
55 NULL /* window-creation data */
56 );
57
58 if( !ret ) panic("Cannot create main window");
59
60
61 if (GetNHApp()->regMainMinX != CW_USEDEFAULT)
62 {
63 wp.length = sizeof(wp);
64 wp.showCmd = GetNHApp()->regMainShowState;
65
66 wp.ptMinPosition.x = GetNHApp()->regMainMinX;
67 wp.ptMinPosition.y = GetNHApp()->regMainMinY;
68
69 wp.ptMaxPosition.x = GetNHApp()->regMainMaxX;
70 wp.ptMaxPosition.y = GetNHApp()->regMainMaxY;
71
72 wp.rcNormalPosition.left = GetNHApp()->regMainLeft;
73 wp.rcNormalPosition.top = GetNHApp()->regMainTop;
74 wp.rcNormalPosition.right = GetNHApp()->regMainRight;
75 wp.rcNormalPosition.bottom = GetNHApp()->regMainBottom;
76 SetWindowPlacement(ret, &wp);
77 }
78 else
79 ShowWindow(ret, SW_SHOWDEFAULT);
80 UpdateWindow(ret);
81
82 return ret;
83 }
84
register_main_window_class()85 void register_main_window_class()
86 {
87 WNDCLASS wcex;
88
89 ZeroMemory(&wcex, sizeof(wcex));
90 wcex.style = CS_HREDRAW | CS_VREDRAW;
91 wcex.lpfnWndProc = (WNDPROC)MainWndProc;
92 wcex.cbClsExtra = 0;
93 wcex.cbWndExtra = 0;
94 wcex.hInstance = GetNHApp()->hApp;
95 wcex.hIcon = LoadIcon(GetNHApp()->hApp, (LPCTSTR)IDI_NETHACKW);
96 wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
97 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
98 wcex.lpszMenuName = (TCHAR*)IDC_NETHACKW;
99 wcex.lpszClassName = szMainWindowClass;
100
101 RegisterClass(&wcex);
102 }
103
104 /*
105 * Keypad keys are translated to the normal values below.
106 * Shifted keypad keys are translated to the
107 * shift values below.
108 */
109
110 enum KEY_INDEXES {
111 KEY_NW, KEY_N, KEY_NE, KEY_MINUS,
112 KEY_W, KEY_GOINTERESTING, KEY_E, KEY_PLUS,
113 KEY_SW, KEY_S, KEY_SE,
114 KEY_INV, KEY_WAITLOOK,
115 KEY_LAST};
116
117 static const unsigned char
118 /* normal, shift, control */
119 keypad[KEY_LAST][3] = {
120 {'y', 'Y', C('y')}, /* 7 */
121 {'k', 'K', C('k')}, /* 8 */
122 {'u', 'U', C('u')}, /* 9 */
123 {'m', C('p'), C('p')}, /* - */
124 {'h', 'H', C('h')}, /* 4 */
125 {'g', 'G', 'g'}, /* 5 */
126 {'l', 'L', C('l')}, /* 6 */
127 {'+', 'P', C('p')}, /* + */
128 {'b', 'B', C('b')}, /* 1 */
129 {'j', 'J', C('j')}, /* 2 */
130 {'n', 'N', C('n')}, /* 3 */
131 {'i', 'I', C('i')}, /* Ins */
132 {'.', ':', ':'} /* Del */
133 },
134 numpad[KEY_LAST][3] = {
135 {'7', M('7'), '7'}, /* 7 */
136 {'8', M('8'), '8'}, /* 8 */
137 {'9', M('9'), '9'}, /* 9 */
138 {'m', C('p'), C('p')}, /* - */
139 {'4', M('4'), '4'}, /* 4 */
140 {'5', M('5'), '5'}, /* 5 */
141 {'6', M('6'), '6'}, /* 6 */
142 {'+', 'P', C('p')}, /* + */
143 {'1', M('1'), '1'}, /* 1 */
144 {'2', M('2'), '2'}, /* 2 */
145 {'3', M('3'), '3'}, /* 3 */
146 {'0', M('0'), '0'}, /* Ins */
147 {'.', ':', ':'} /* Del */
148 };
149
150 #define STATEON(x) ((GetKeyState(x) & 0xFFFE) != 0)
151 #define KEYTABLE_REGULAR(x) ((iflags.num_pad ? numpad : keypad)[x][0])
152 #define KEYTABLE_SHIFT(x) ((iflags.num_pad ? numpad : keypad)[x][1])
153 #define KEYTABLE(x) (STATEON(VK_SHIFT) ? KEYTABLE_SHIFT(x) : KEYTABLE_REGULAR(x))
154
155 /* map mode macros */
156 #define IS_MAP_FIT_TO_SCREEN(mode) ((mode)==MAP_MODE_ASCII_FIT_TO_SCREEN || \
157 (mode)==MAP_MODE_TILES_FIT_TO_SCREEN )
158
159 #define IS_MAP_ASCII(mode) ((mode)!=MAP_MODE_TILES && (mode)!=MAP_MODE_TILES_FIT_TO_SCREEN)
160
161 static const char *extendedlist = "acdefijlmnopqrstuvw?2";
162
163 #define SCANLO 0x02
164 static const char scanmap[] = { /* ... */
165 '1','2','3','4','5','6','7','8','9','0',0,0,0,0,
166 'q','w','e','r','t','y','u','i','o','p','[',']', '\n',
167 0, 'a','s','d','f','g','h','j','k','l',';','\'', '`',
168 0, '\\', 'z','x','c','v','b','n','m',',','.','?' /* ... */
169 };
170
171 /*
172 // FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
173 //
174 // PURPOSE: Processes messages for the main window.
175 */
MainWndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)176 LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
177 {
178 PNHMainWindow data;
179
180 switch (message)
181 {
182 case WM_CREATE:
183 /* set window data */
184 data = (PNHMainWindow)malloc(sizeof(NHMainWindow));
185 if( !data ) panic("out of memory");
186 ZeroMemory(data, sizeof(NHMainWindow));
187 data->mapAcsiiModeSave = MAP_MODE_ASCII12x16;
188 SetWindowLong(hWnd, GWL_USERDATA, (LONG)data);
189
190 GetNHApp()->hMainWnd = hWnd;
191 break;
192
193 case WM_MSNH_COMMAND:
194 onMSNHCommand(hWnd, wParam, lParam);
195 break;
196
197 case WM_KEYDOWN:
198 {
199 data = (PNHMainWindow)GetWindowLong(hWnd, GWL_USERDATA);
200
201 /* translate arrow keys into nethack commands */
202 switch (wParam)
203 {
204 case VK_LEFT:
205 if( STATEON(VK_CONTROL) ) {
206 /* scroll map window one line left */
207 SendMessage(
208 mswin_hwnd_from_winid(WIN_MAP),
209 WM_HSCROLL,
210 MAKEWPARAM(SB_LINEUP, 0),
211 (LPARAM)NULL
212 );
213 } else {
214 NHEVENT_KBD(KEYTABLE(KEY_W));
215 }
216 return 0;
217
218 case VK_RIGHT:
219 if( STATEON(VK_CONTROL) ) {
220 /* scroll map window one line right */
221 SendMessage(
222 mswin_hwnd_from_winid(WIN_MAP),
223 WM_HSCROLL,
224 MAKEWPARAM(SB_LINEDOWN, 0),
225 (LPARAM)NULL
226 );
227 } else {
228 NHEVENT_KBD(KEYTABLE(KEY_E));
229 }
230 return 0;
231
232 case VK_UP:
233 if( STATEON(VK_CONTROL) ) {
234 /* scroll map window one line up */
235 SendMessage(
236 mswin_hwnd_from_winid(WIN_MAP),
237 WM_VSCROLL,
238 MAKEWPARAM(SB_LINEUP, 0),
239 (LPARAM)NULL
240 );
241 } else {
242 NHEVENT_KBD(KEYTABLE(KEY_N));
243 }
244 return 0;
245
246 case VK_DOWN:
247 if( STATEON(VK_CONTROL) ) {
248 /* scroll map window one line down */
249 SendMessage(
250 mswin_hwnd_from_winid(WIN_MAP),
251 WM_VSCROLL,
252 MAKEWPARAM(SB_LINEDOWN, 0),
253 (LPARAM)NULL
254 );
255 } else {
256 NHEVENT_KBD(KEYTABLE(KEY_S));
257 }
258 return 0;
259
260 case VK_HOME:
261 if( STATEON(VK_CONTROL) ) {
262 /* scroll map window to upper left corner */
263 SendMessage(
264 mswin_hwnd_from_winid(WIN_MAP),
265 WM_VSCROLL,
266 MAKEWPARAM(SB_THUMBTRACK, 0),
267 (LPARAM)NULL
268 );
269
270 SendMessage(
271 mswin_hwnd_from_winid(WIN_MAP),
272 WM_HSCROLL,
273 MAKEWPARAM(SB_THUMBTRACK, 0),
274 (LPARAM)NULL
275 );
276 } else {
277 NHEVENT_KBD(KEYTABLE(KEY_NW));
278 }
279 return 0;
280
281 case VK_END:
282 if( STATEON(VK_CONTROL) ) {
283 /* scroll map window to lower right corner */
284 SendMessage(
285 mswin_hwnd_from_winid(WIN_MAP),
286 WM_VSCROLL,
287 MAKEWPARAM(SB_THUMBTRACK, ROWNO),
288 (LPARAM)NULL
289 );
290
291 SendMessage(
292 mswin_hwnd_from_winid(WIN_MAP),
293 WM_HSCROLL,
294 MAKEWPARAM(SB_THUMBTRACK, COLNO),
295 (LPARAM)NULL
296 );
297 } else {
298 NHEVENT_KBD(KEYTABLE(KEY_SW));
299 }
300 return 0;
301
302 case VK_PRIOR:
303 if( STATEON(VK_CONTROL) ) {
304 /* scroll map window one page up */
305 SendMessage(
306 mswin_hwnd_from_winid(WIN_MAP),
307 WM_VSCROLL,
308 MAKEWPARAM(SB_PAGEUP, 0),
309 (LPARAM)NULL
310 );
311 } else {
312 NHEVENT_KBD(KEYTABLE(KEY_NE));
313 }
314 return 0;
315
316 case VK_NEXT:
317 if( STATEON(VK_CONTROL) ) {
318 /* scroll map window one page down */
319 SendMessage(
320 mswin_hwnd_from_winid(WIN_MAP),
321 WM_VSCROLL,
322 MAKEWPARAM(SB_PAGEDOWN, 0),
323 (LPARAM)NULL
324 );
325 } else {
326 NHEVENT_KBD(KEYTABLE(KEY_SE));
327 }
328 return 0;
329
330 case VK_DECIMAL:
331 case VK_DELETE:
332 NHEVENT_KBD(KEYTABLE(KEY_WAITLOOK));
333 return 0;
334
335 case VK_INSERT:
336 NHEVENT_KBD(KEYTABLE(KEY_INV));
337 return 0;
338
339 case VK_SUBTRACT:
340 NHEVENT_KBD(KEYTABLE(KEY_MINUS));
341 return 0;
342
343 case VK_ADD:
344 NHEVENT_KBD(KEYTABLE(KEY_PLUS));
345 return 0;
346
347 case VK_CLEAR: /* This is the '5' key */
348 NHEVENT_KBD(KEYTABLE(KEY_GOINTERESTING));
349 return 0;
350
351 case VK_F4:
352 if( IS_MAP_FIT_TO_SCREEN(iflags.wc_map_mode) ) {
353 mswin_select_map_mode(
354 IS_MAP_ASCII(iflags.wc_map_mode)?
355 data->mapAcsiiModeSave :
356 MAP_MODE_TILES
357 );
358 } else {
359 mswin_select_map_mode(
360 IS_MAP_ASCII(iflags.wc_map_mode)?
361 MAP_MODE_ASCII_FIT_TO_SCREEN :
362 MAP_MODE_TILES_FIT_TO_SCREEN
363 );
364 }
365 return 0;
366
367 case VK_F5:
368 if( IS_MAP_ASCII(iflags.wc_map_mode) ) {
369 if( IS_MAP_FIT_TO_SCREEN(iflags.wc_map_mode) ) {
370 mswin_select_map_mode(MAP_MODE_TILES_FIT_TO_SCREEN);
371 } else {
372 mswin_select_map_mode(MAP_MODE_TILES);
373 }
374 } else {
375 if( IS_MAP_FIT_TO_SCREEN(iflags.wc_map_mode) ) {
376 mswin_select_map_mode(MAP_MODE_ASCII_FIT_TO_SCREEN);
377 } else {
378 mswin_select_map_mode(data->mapAcsiiModeSave);
379 }
380 }
381 return 0;
382
383 default: {
384 WORD c;
385 BYTE kbd_state[256];
386
387 c = 0;
388 ZeroMemory(kbd_state, sizeof(kbd_state));
389 GetKeyboardState(kbd_state);
390
391 if( ToAscii( wParam, (lParam>>16)&0xFF, kbd_state, &c, 0) ) {
392 NHEVENT_KBD( c&0xFF );
393 return 0;
394 } else {
395 return 1;
396 }
397 }
398
399 } /* end switch */
400 } break;
401
402 case WM_SYSCHAR: /* Alt-char pressed */
403 {
404 /*
405 If not nethackmode, don't handle Alt-keys here.
406 If no Alt-key pressed it can never be an extended command
407 */
408 if (GetNHApp()->regNetHackMode && ((lParam & 1<<29) != 0))
409 {
410 unsigned char c = (unsigned char)(wParam & 0xFF);
411 unsigned char scancode = (lParam >> 16) & 0xFF;
412 if (index(extendedlist, tolower(c)) != 0)
413 {
414 NHEVENT_KBD(M(tolower(c)));
415 } else if (scancode == (SCANLO + SIZE(scanmap)) - 1) {
416 NHEVENT_KBD(M('?'));
417 }
418 return 0;
419 }
420 return DefWindowProc(hWnd, message, wParam, lParam);
421 }
422 break;
423
424 case WM_COMMAND:
425 /* process commands - menu commands mostly */
426 if( onWMCommand(hWnd, wParam, lParam) )
427 return DefWindowProc(hWnd, message, wParam, lParam);
428 else
429 return 0;
430
431 case WM_MOVE:
432 case WM_SIZE:
433 {
434 WINDOWPLACEMENT wp;
435
436 mswin_layout_main_window(NULL);
437
438 wp.length = sizeof(wp);
439 if (GetWindowPlacement(hWnd, &wp)) {
440 GetNHApp()->regMainShowState = (wp.showCmd == SW_SHOWMAXIMIZED
441 ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL);
442
443 GetNHApp()->regMainMinX = wp.ptMinPosition.x;
444 GetNHApp()->regMainMinY = wp.ptMinPosition.y;
445
446 GetNHApp()->regMainMaxX = wp.ptMaxPosition.x;
447 GetNHApp()->regMainMaxY = wp.ptMaxPosition.y;
448
449 GetNHApp()->regMainLeft = wp.rcNormalPosition.left;
450 GetNHApp()->regMainTop = wp.rcNormalPosition.top;
451 GetNHApp()->regMainRight = wp.rcNormalPosition.right;
452 GetNHApp()->regMainBottom = wp.rcNormalPosition.bottom;
453 }
454 break;
455 }
456 case WM_SETFOCUS:
457 /* if there is a menu window out there -
458 transfer input focus to it */
459 if( IsWindow( GetNHApp()->hPopupWnd ) ) {
460 SetFocus( GetNHApp()->hPopupWnd );
461 }
462 break;
463
464 case WM_CLOSE:
465 {
466 /* exit gracefully */
467 if (program_state.gameover)
468 {
469 /* assume the user really meant this, as the game is already over... */
470 /* to make sure we still save bones, just set stop printing flag */
471 program_state.stopprint++;
472 NHEVENT_KBD('\033'); /* and send keyboard input as if user pressed ESC */
473 /* additional code for this is done in menu and rip windows */
474 }
475 else if (!program_state.something_worth_saving)
476 {
477 /* User exited before the game started, e.g. during splash display */
478 /* Just get out. */
479 bail((char *)0);
480 }
481 else
482 {
483 switch (NHMessageBox(hWnd, TEXT("Save?"), MB_YESNOCANCEL | MB_ICONQUESTION)) {
484 case IDYES: NHEVENT_KBD('y'); dosave(); break;
485 case IDNO: NHEVENT_KBD('q'); done(QUIT); break;
486 case IDCANCEL: break;
487 }
488 }
489 } return 0;
490
491 case WM_DESTROY:
492 /* apparently we never get here
493 TODO: work on exit routines - need to send
494 WM_QUIT somehow */
495
496 /* clean up */
497 free( (PNHMainWindow)GetWindowLong(hWnd, GWL_USERDATA) );
498 SetWindowLong(hWnd, GWL_USERDATA, (LONG)0);
499
500 // PostQuitMessage(0);
501 exit(1);
502 break;
503
504 default:
505 return DefWindowProc(hWnd, message, wParam, lParam);
506 }
507 return 0;
508 }
509
onMSNHCommand(HWND hWnd,WPARAM wParam,LPARAM lParam)510 void onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
511 {
512 switch(wParam) {
513
514 /* new window was just added */
515 case MSNH_MSG_ADDWND: {
516 PMSNHMsgAddWnd msg_param = (PMSNHMsgAddWnd)lParam;
517 HWND child;
518
519 if( GetNHApp()->windowlist[msg_param->wid].type == NHW_MAP )
520 mswin_select_map_mode(iflags.wc_map_mode);
521
522 child = GetNHApp()->windowlist[msg_param->wid].win;
523 if( child ) mswin_layout_main_window(child);
524 } break;
525
526 }
527 }
528
529 /* adjust windows to fit main window layout
530 ---------------------------
531 | Status |
532 +-------------------------+
533 | |
534 | |
535 | MAP |
536 | |
537 | |
538 +-------------------------+
539 | Messages |
540 ---------------------------
541 */
mswin_layout_main_window(HWND changed_child)542 void mswin_layout_main_window(HWND changed_child)
543 {
544 winid i;
545 POINT pt;
546 RECT client_rt, wnd_rect;
547 SIZE menu_size;
548 POINT status_org;
549 SIZE status_size;
550 POINT msg_org;
551 SIZE msg_size;
552 POINT map_org;
553 SIZE map_size;
554 HWND wnd_status, wnd_msg;
555 PNHMainWindow data;
556
557 GetClientRect(GetNHApp()->hMainWnd, &client_rt);
558 data = (PNHMainWindow)GetWindowLong(GetNHApp()->hMainWnd, GWL_USERDATA);
559
560 /* get sizes of child windows */
561 wnd_status = mswin_hwnd_from_winid(WIN_STATUS);
562 if( IsWindow(wnd_status) ) {
563 mswin_status_window_size(wnd_status, &status_size);
564 } else {
565 status_size.cx = status_size.cy = 0;
566 }
567
568 wnd_msg = mswin_hwnd_from_winid(WIN_MESSAGE);
569 if( IsWindow(wnd_msg) ) {
570 mswin_message_window_size(wnd_msg, &msg_size);
571 } else {
572 msg_size.cx = msg_size.cy = 0;
573 }
574
575 /* set window positions */
576 SetRect(&wnd_rect, client_rt.left, client_rt.top, client_rt.right, client_rt.bottom);
577 switch(iflags.wc_align_status) {
578 case ALIGN_LEFT:
579 status_size.cx = (wnd_rect.right-wnd_rect.left)/4;
580 status_size.cy = (wnd_rect.bottom-wnd_rect.top); // that won't look good
581 status_org.x = wnd_rect.left;
582 status_org.y = wnd_rect.top;
583 wnd_rect.left += status_size.cx;
584 break;
585
586 case ALIGN_RIGHT:
587 status_size.cx = (wnd_rect.right-wnd_rect.left)/4;
588 status_size.cy = (wnd_rect.bottom-wnd_rect.top); // that won't look good
589 status_org.x = wnd_rect.right - status_size.cx;
590 status_org.y = wnd_rect.top;
591 wnd_rect.right -= status_size.cx;
592 break;
593
594 case ALIGN_TOP:
595 status_size.cx = (wnd_rect.right-wnd_rect.left);
596 status_org.x = wnd_rect.left;
597 status_org.y = wnd_rect.top;
598 wnd_rect.top += status_size.cy;
599 break;
600
601 case ALIGN_BOTTOM:
602 default:
603 status_size.cx = (wnd_rect.right-wnd_rect.left);
604 status_org.x = wnd_rect.left;
605 status_org.y = wnd_rect.bottom - status_size.cy;
606 wnd_rect.bottom -= status_size.cy;
607 break;
608 }
609
610 switch(iflags.wc_align_message) {
611 case ALIGN_LEFT:
612 msg_size.cx = (wnd_rect.right-wnd_rect.left)/4;
613 msg_size.cy = (wnd_rect.bottom-wnd_rect.top);
614 msg_org.x = wnd_rect.left;
615 msg_org.y = wnd_rect.top;
616 wnd_rect.left += msg_size.cx;
617 break;
618
619 case ALIGN_RIGHT:
620 msg_size.cx = (wnd_rect.right-wnd_rect.left)/4;
621 msg_size.cy = (wnd_rect.bottom-wnd_rect.top);
622 msg_org.x = wnd_rect.right - msg_size.cx;
623 msg_org.y = wnd_rect.top;
624 wnd_rect.right -= msg_size.cx;
625 break;
626
627 case ALIGN_TOP:
628 msg_size.cx = (wnd_rect.right-wnd_rect.left);
629 msg_org.x = wnd_rect.left;
630 msg_org.y = wnd_rect.top;
631 wnd_rect.top += msg_size.cy;
632 break;
633
634 case ALIGN_BOTTOM:
635 default:
636 msg_size.cx = (wnd_rect.right-wnd_rect.left);
637 msg_org.x = wnd_rect.left;
638 msg_org.y = wnd_rect.bottom - msg_size.cy;
639 wnd_rect.bottom -= msg_size.cy;
640 break;
641 }
642
643 map_org.x = wnd_rect.left;
644 map_org.y = wnd_rect.top;
645 map_size.cx = wnd_rect.right - wnd_rect.left;
646 map_size.cy = wnd_rect.bottom - wnd_rect.top;
647
648 /* go through the windows list and adjust sizes */
649 for( i=0; i<MAXWINDOWS; i++ ) {
650 if(GetNHApp()->windowlist[i].win && !GetNHApp()->windowlist[i].dead) {
651 switch( GetNHApp()->windowlist[i].type ) {
652 case NHW_STATUS:
653 MoveWindow(GetNHApp()->windowlist[i].win,
654 status_org.x,
655 status_org.y,
656 status_size.cx,
657 status_size.cy,
658 TRUE );
659 break;
660
661 case NHW_TEXT: // same as the map window
662 case NHW_MAP:
663 MoveWindow(GetNHApp()->windowlist[i].win,
664 map_org.x,
665 map_org.y,
666 map_size.cx,
667 map_size.cy,
668 TRUE );
669 break;
670
671 case NHW_MESSAGE:
672 MoveWindow(GetNHApp()->windowlist[i].win,
673 msg_org.x,
674 msg_org.y,
675 msg_size.cx,
676 msg_size.cy,
677 TRUE );
678 break;
679
680 case NHW_MENU:
681 mswin_menu_window_size(GetNHApp()->windowlist[i].win, &menu_size);
682 menu_size.cx = min(menu_size.cx, (client_rt.right-client_rt.left));
683
684 pt.x = map_org.x + max(0, (int)(map_size.cx-menu_size.cx));
685 pt.y = map_org.y;
686 MoveWindow(GetNHApp()->windowlist[i].win,
687 pt.x,
688 pt.y,
689 min(menu_size.cx, map_size.cx),
690 map_size.cy,
691 TRUE );
692 break;
693 }
694 ShowWindow(GetNHApp()->windowlist[i].win, SW_SHOW);
695 }
696 }
697 }
698
onWMCommand(HWND hWnd,WPARAM wParam,LPARAM lParam)699 LRESULT onWMCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
700 {
701 int wmId, wmEvent;
702 PNHMainWindow data;
703
704 data = (PNHMainWindow)GetWindowLong(hWnd, GWL_USERDATA);
705 wmId = LOWORD(wParam);
706 wmEvent = HIWORD(wParam);
707
708 // Parse the menu selections:
709 switch (wmId)
710 {
711 case IDM_ABOUT:
712 mswin_display_splash_window(TRUE);
713 break;
714
715 case IDM_EXIT:
716 done2();
717 break;
718
719 case IDM_SAVE:
720 if (!program_state.gameover && !program_state.done_hup) dosave();
721 else MessageBeep(0);
722 break;
723
724 case IDM_MAP_TILES:
725 case IDM_MAP_ASCII4X6:
726 case IDM_MAP_ASCII6X8:
727 case IDM_MAP_ASCII8X8:
728 case IDM_MAP_ASCII16X8:
729 case IDM_MAP_ASCII7X12:
730 case IDM_MAP_ASCII8X12:
731 case IDM_MAP_ASCII12X16:
732 case IDM_MAP_ASCII16X12:
733 case IDM_MAP_ASCII10X18:
734 mswin_select_map_mode(menuid2mapmode(wmId));
735 break;
736
737 case IDM_MAP_FIT_TO_SCREEN:
738 if( IS_MAP_FIT_TO_SCREEN(iflags.wc_map_mode) ) {
739 mswin_select_map_mode(
740 IS_MAP_ASCII(iflags.wc_map_mode)?
741 data->mapAcsiiModeSave :
742 MAP_MODE_TILES
743 );
744 } else {
745 mswin_select_map_mode(
746 IS_MAP_ASCII(iflags.wc_map_mode)?
747 MAP_MODE_ASCII_FIT_TO_SCREEN :
748 MAP_MODE_TILES_FIT_TO_SCREEN
749 );
750 }
751 break;
752
753 case IDM_NHMODE:
754 {
755 GetNHApp()->regNetHackMode = GetNHApp()->regNetHackMode ? 0 : 1;
756 mswin_menu_check_intf_mode();
757 break;
758 }
759 case IDM_CLEARSETTINGS:
760 {
761 mswin_destroy_reg();
762 /* Notify the user that windows settings will not be saved this time. */
763 NHMessageBox(GetNHApp()->hMainWnd,
764 "Your Windows Settings will not be stored when you exit this time.",
765 MB_OK | MB_ICONINFORMATION);
766 break;
767 }
768 case IDM_HELP_LONG:
769 display_file(HELP, TRUE);
770 break;
771
772 case IDM_HELP_COMMANDS:
773 display_file(SHELP, TRUE);
774 break;
775
776 case IDM_HELP_HISTORY:
777 (void) dohistory();
778 break;
779
780 case IDM_HELP_INFO_CHAR:
781 (void) dowhatis();
782 break;
783
784 case IDM_HELP_INFO_KEY:
785 (void) dowhatdoes();
786 break;
787
788 case IDM_HELP_OPTIONS:
789 option_help();
790 break;
791
792 case IDM_HELP_OPTIONS_LONG:
793 display_file(OPTIONFILE, TRUE);
794 break;
795
796 case IDM_HELP_EXTCMD:
797 (void) doextlist();
798 break;
799
800 case IDM_HELP_LICENSE:
801 display_file(LICENSE, TRUE);
802 break;
803
804 case IDM_HELP_PORTHELP:
805 display_file(PORT_HELP, TRUE);
806 break;
807
808 default:
809 return 1;
810 }
811 return 0;
812 }
813
814 // Mesage handler for about box.
About(HWND hDlg,UINT message,WPARAM wParam,LPARAM lParam)815 LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
816 {
817 char buf[BUFSZ];
818 TCHAR wbuf[BUFSZ];
819 RECT main_rt, dlg_rt;
820 SIZE dlg_sz;
821
822 switch (message)
823 {
824 case WM_INITDIALOG:
825 getversionstring(buf);
826 SetDlgItemText(hDlg, IDC_ABOUT_VERSION, NH_A2W(buf, wbuf, sizeof(wbuf)));
827
828 SetDlgItemText(hDlg, IDC_ABOUT_COPYRIGHT,
829 NH_A2W(
830 COPYRIGHT_BANNER_A "\n"
831 COPYRIGHT_BANNER_B "\n"
832 COPYRIGHT_BANNER_C,
833 wbuf,
834 BUFSZ
835 ) );
836
837
838 /* center dialog in the main window */
839 GetWindowRect(GetNHApp()->hMainWnd, &main_rt);
840 GetWindowRect(hDlg, &dlg_rt);
841 dlg_sz.cx = dlg_rt.right - dlg_rt.left;
842 dlg_sz.cy = dlg_rt.bottom - dlg_rt.top;
843
844 dlg_rt.left = (main_rt.left+main_rt.right-dlg_sz.cx)/2;
845 dlg_rt.right = dlg_rt.left + dlg_sz.cx;
846 dlg_rt.top = (main_rt.top+main_rt.bottom-dlg_sz.cy)/2;
847 dlg_rt.bottom = dlg_rt.top + dlg_sz.cy;
848 MoveWindow( hDlg,
849 (main_rt.left+main_rt.right-dlg_sz.cx)/2,
850 (main_rt.top+main_rt.bottom-dlg_sz.cy)/2,
851 dlg_sz.cx,
852 dlg_sz.cy,
853 TRUE );
854
855 return TRUE;
856
857 case WM_COMMAND:
858 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
859 {
860 EndDialog(hDlg, LOWORD(wParam));
861 return TRUE;
862 }
863 break;
864 }
865 return FALSE;
866 }
867
mswin_menu_check_intf_mode()868 void mswin_menu_check_intf_mode()
869 {
870 HMENU hMenu = GetMenu(GetNHApp()->hMainWnd);
871
872 if (GetNHApp()->regNetHackMode)
873 CheckMenuItem(hMenu, IDM_NHMODE, MF_CHECKED);
874 else
875 CheckMenuItem(hMenu, IDM_NHMODE, MF_UNCHECKED);
876
877 }
878
mswin_select_map_mode(int mode)879 void mswin_select_map_mode(int mode)
880 {
881 PNHMainWindow data;
882 winid map_id;
883
884 map_id = WIN_MAP;
885 data = (PNHMainWindow)GetWindowLong(GetNHApp()->hMainWnd, GWL_USERDATA);
886
887 /* override for Rogue level */
888 #ifdef REINCARNATION
889 if( Is_rogue_level(&u.uz) && !IS_MAP_ASCII(mode) ) return;
890 #endif
891
892 /* set map mode menu mark */
893 if( IS_MAP_ASCII(mode) ) {
894 CheckMenuRadioItem(
895 GetMenu(GetNHApp()->hMainWnd),
896 IDM_MAP_TILES,
897 IDM_MAP_ASCII10X18,
898 mapmode2menuid( IS_MAP_FIT_TO_SCREEN(mode)? data->mapAcsiiModeSave : mode ),
899 MF_BYCOMMAND);
900 } else {
901 CheckMenuRadioItem(
902 GetMenu(GetNHApp()->hMainWnd),
903 IDM_MAP_TILES,
904 IDM_MAP_ASCII10X18,
905 mapmode2menuid( MAP_MODE_TILES ),
906 MF_BYCOMMAND);
907 }
908
909 /* set fit-to-screen mode mark */
910 CheckMenuItem(
911 GetMenu(GetNHApp()->hMainWnd),
912 IDM_MAP_FIT_TO_SCREEN,
913 MF_BYCOMMAND |
914 (IS_MAP_FIT_TO_SCREEN(mode)? MF_CHECKED : MF_UNCHECKED)
915 );
916
917 if( IS_MAP_ASCII(iflags.wc_map_mode) && !IS_MAP_FIT_TO_SCREEN(iflags.wc_map_mode)) {
918 data->mapAcsiiModeSave = iflags.wc_map_mode;
919 }
920
921 iflags.wc_map_mode = mode;
922
923 /*
924 ** first, check if WIN_MAP has been inialized.
925 ** If not - attempt to retrieve it by type, then check it again
926 */
927 if( map_id==WIN_ERR )
928 map_id = mswin_winid_from_type(NHW_MAP);
929 if( map_id!=WIN_ERR )
930 mswin_map_mode(mswin_hwnd_from_winid(map_id), mode);
931 }
932
933 static struct t_menu2mapmode {
934 int menuID;
935 int mapMode;
936 } _menu2mapmode[] =
937 {
938 { IDM_MAP_TILES, MAP_MODE_TILES },
939 { IDM_MAP_ASCII4X6, MAP_MODE_ASCII4x6 },
940 { IDM_MAP_ASCII6X8, MAP_MODE_ASCII6x8 },
941 { IDM_MAP_ASCII8X8, MAP_MODE_ASCII8x8 },
942 { IDM_MAP_ASCII16X8, MAP_MODE_ASCII16x8 },
943 { IDM_MAP_ASCII7X12, MAP_MODE_ASCII7x12 },
944 { IDM_MAP_ASCII8X12, MAP_MODE_ASCII8x12 },
945 { IDM_MAP_ASCII12X16, MAP_MODE_ASCII12x16 },
946 { IDM_MAP_ASCII16X12, MAP_MODE_ASCII16x12 },
947 { IDM_MAP_ASCII10X18, MAP_MODE_ASCII10x18 },
948 { IDM_MAP_FIT_TO_SCREEN, MAP_MODE_ASCII_FIT_TO_SCREEN },
949 { -1, -1 }
950 };
951
menuid2mapmode(int menuid)952 int menuid2mapmode(int menuid)
953 {
954 struct t_menu2mapmode* p;
955 for( p = _menu2mapmode; p->mapMode!=-1; p++ )
956 if(p->menuID==menuid ) return p->mapMode;
957 return -1;
958 }
959
mapmode2menuid(int map_mode)960 int mapmode2menuid(int map_mode)
961 {
962 struct t_menu2mapmode* p;
963 for( p = _menu2mapmode; p->mapMode!=-1; p++ )
964 if(p->mapMode==map_mode ) return p->menuID;
965 return -1;
966 }
967