NHDT->ANH, nethack->anethack, nhdat->anhdat
[aNetHack.git] / sys / wince / mhmain.c
blob041d9540706ddeead880613550cabfd5fef1c380
1 /* aNetHack 0.0.1 mhmain.c $ANH-Date: 1432512800 2015/05/25 00:13:20 $ $ANH-Branch: master $:$ANH-Revision: 1.46 $ */
2 /* Copyright (C) 2001 by Alex Kompel */
3 /* aNetHack may be freely redistributed. See license for details. */
5 #include "winMS.h"
6 #include "mhmsg.h"
7 #include "mhinput.h"
8 #include "mhmain.h"
9 #include "mhmenu.h"
10 #include "mhstatus.h"
11 #include "mhmsgwnd.h"
12 #include "mhcmd.h"
13 #include "mhmap.h"
14 #include "date.h"
15 #include "patchlevel.h"
17 #define MAX_LOADSTRING 100
19 typedef struct mswin_anethack_main_window {
20 int mapAcsiiModeSave;
21 } NHMainWindow, *PNHMainWindow;
23 TCHAR szMainWindowClass[] = TEXT("MSNHMainWndClass");
24 static TCHAR szTitle[MAX_LOADSTRING];
26 LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);
27 LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
28 static LRESULT onWMCommand(HWND hWnd, WPARAM wParam, LPARAM lParam);
29 static void onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam);
30 static void register_main_window_class();
31 static void select_map_mode(int map_mode);
32 static int menuid2mapmode(int menuid);
33 static int mapmode2menuid(int map_mode);
34 static HMENU _get_main_menu(UINT menu_id);
35 static void mswin_direct_command();
37 HWND
38 mswin_init_main_window()
40 static int run_once = 0;
41 HWND ret;
42 RECT rc;
44 /* register window class */
45 if (!run_once) {
46 LoadString(GetNHApp()->hApp, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
47 register_main_window_class();
48 run_once = 1;
51 /* create the main window */
52 SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, 0);
54 ret = CreateWindow(szMainWindowClass, /* registered class name */
55 szTitle, /* window name */
56 WS_CLIPCHILDREN, /* window style */
57 rc.left, /* horizontal position of window */
58 rc.top, /* vertical position of window */
59 rc.right - rc.left, /* window width */
60 rc.bottom - rc.top, /* window height */
61 NULL, /* handle to parent or owner window */
62 NULL, /* menu handle or child identifier */
63 GetNHApp()->hApp, /* handle to application instance */
64 NULL /* window-creation data */
67 if (!ret)
68 panic("Cannot create main window");
69 return ret;
72 void
73 register_main_window_class()
75 WNDCLASS wcex;
77 ZeroMemory(&wcex, sizeof(wcex));
78 wcex.style = CS_HREDRAW | CS_VREDRAW;
79 wcex.lpfnWndProc = (WNDPROC) MainWndProc;
80 wcex.cbClsExtra = 0;
81 wcex.cbWndExtra = 0;
82 wcex.hInstance = GetNHApp()->hApp;
83 wcex.hIcon = LoadIcon(GetNHApp()->hApp, (LPCTSTR) IDI_WINHACK);
84 wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
85 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
86 wcex.lpszMenuName = NULL;
87 wcex.lpszClassName = szMainWindowClass;
89 RegisterClass(&wcex);
93 * Keypad keys are translated to the normal values below.
94 * Shifted keypad keys are translated to the
95 * shift values below.
98 enum KEY_INDEXES {
99 KEY_NW,
100 KEY_N,
101 KEY_NE,
102 KEY_MINUS,
103 KEY_W,
104 KEY_GOINTERESTING,
105 KEY_E,
106 KEY_PLUS,
107 KEY_SW,
108 KEY_S,
109 KEY_SE,
110 KEY_INV,
111 KEY_WAITLOOK,
112 KEY_LAST
115 static const unsigned char
116 /* normal, shift, control */
117 keypad[KEY_LAST][3] =
119 { 'y', 'Y', C('y') }, /* 7 */
120 { 'k', 'K', C('k') }, /* 8 */
121 { 'u', 'U', C('u') }, /* 9 */
122 { 'm', C('p'), C('p') }, /* - */
123 { 'h', 'H', C('h') }, /* 4 */
124 { 'g', 'G', 'g' }, /* 5 */
125 { 'l', 'L', C('l') }, /* 6 */
126 { '+', 'P', C('p') }, /* + */
127 { 'b', 'B', C('b') }, /* 1 */
128 { 'j', 'J', C('j') }, /* 2 */
129 { 'n', 'N', C('n') }, /* 3 */
130 { 'i', 'I', C('i') }, /* Ins */
131 { '.', ':', ':' } /* Del */
133 numpad[KEY_LAST][3] = {
134 { '7', M('7'), '7' }, /* 7 */
135 { '8', M('8'), '8' }, /* 8 */
136 { '9', M('9'), '9' }, /* 9 */
137 { 'm', C('p'), C('p') }, /* - */
138 { '4', M('4'), '4' }, /* 4 */
139 { 'g', 'G', 'g' }, /* 5 */
140 { '6', M('6'), '6' }, /* 6 */
141 { '+', 'P', C('p') }, /* + */
142 { '1', M('1'), '1' }, /* 1 */
143 { '2', M('2'), '2' }, /* 2 */
144 { '3', M('3'), '3' }, /* 3 */
145 { 'i', 'I', C('i') }, /* Ins */
146 { '.', ':', ':' } /* Del */
149 #define STATEON(x) ((GetKeyState(x) & 0xFFFE) != 0)
150 #define KEYTABLE_REGULAR(x) ((iflags.num_pad ? numpad : keypad)[x][0])
151 #define KEYTABLE_SHIFT(x) ((iflags.num_pad ? numpad : keypad)[x][1])
152 #define KEYTABLE(x) \
153 (STATEON(VK_SHIFT) ? KEYTABLE_SHIFT(x) : KEYTABLE_REGULAR(x))
155 /* map mode macros */
156 #define IS_MAP_FIT_TO_SCREEN(mode) \
157 ((mode) == MAP_MODE_ASCII_FIT_TO_SCREEN \
158 || (mode) == MAP_MODE_TILES_FIT_TO_SCREEN)
160 #define IS_MAP_ASCII(mode) \
161 ((mode) != MAP_MODE_TILES && (mode) != MAP_MODE_TILES_FIT_TO_SCREEN)
164 // FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
166 // PURPOSE: Processes messages for the main window.
168 LRESULT CALLBACK
169 MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
171 PNHMainWindow data;
173 switch (message) {
174 /*-----------------------------------------------------------------------*/
175 case WM_CREATE: {
176 #if defined(WIN_CE_POCKETPC) || defined(WIN_CE_SMARTPHONE)
177 SHMENUBARINFO menubar;
178 #endif
179 /* set window data */
180 data = (PNHMainWindow) malloc(sizeof(NHMainWindow));
181 if (!data)
182 panic("out of memory");
183 ZeroMemory(data, sizeof(NHMainWindow));
184 data->mapAcsiiModeSave = MAP_MODE_ASCII12x16;
185 SetWindowLong(hWnd, GWL_USERDATA, (LONG) data);
187 GetNHApp()->hMainWnd = hWnd;
189 /* create menu bar */
190 #if defined(WIN_CE_POCKETPC) || defined(WIN_CE_SMARTPHONE)
191 ZeroMemory(&menubar, sizeof(menubar));
192 menubar.cbSize = sizeof(menubar);
193 menubar.hwndParent = hWnd;
194 menubar.dwFlags = 0;
195 menubar.nToolBarId = IDC_WINHACK;
196 menubar.hInstRes = GetNHApp()->hApp;
197 #if defined(WIN_CE_POCKETPC)
198 menubar.nBmpId = IDB_MENUBAR;
199 menubar.cBmpImages = 2;
200 #else
201 menubar.nBmpId = 0;
202 menubar.cBmpImages = 0;
203 #endif
204 if (!SHCreateMenuBar(&menubar))
205 panic("cannot create menu");
206 GetNHApp()->hMenuBar = menubar.hwndMB;
207 #else
208 GetNHApp()->hMenuBar = CommandBar_Create(GetNHApp()->hApp, hWnd, 1);
209 if (!GetNHApp()->hMenuBar)
210 panic("cannot create menu");
211 CommandBar_InsertMenubar(GetNHApp()->hMenuBar, GetNHApp()->hApp,
212 IDC_WINHACK, 0);
213 #endif
214 CheckMenuItem(
215 _get_main_menu(ID_VIEW), IDM_VIEW_KEYPAD,
216 MF_BYCOMMAND | (GetNHApp()->bCmdPad ? MF_CHECKED : MF_UNCHECKED));
218 } break;
220 /*-----------------------------------------------------------------------*/
222 case WM_MSNH_COMMAND:
223 onMSNHCommand(hWnd, wParam, lParam);
224 break;
226 /*-----------------------------------------------------------------------*/
228 case WM_KEYDOWN:
229 data = (PNHMainWindow) GetWindowLong(hWnd, GWL_USERDATA);
231 /* translate arrow keys into anethack commands */
232 switch (wParam) {
233 case VK_LEFT:
234 if (STATEON(VK_CONTROL)) {
235 /* scroll map window one line left */
236 SendMessage(mswin_hwnd_from_winid(WIN_MAP), WM_HSCROLL,
237 MAKEWPARAM(SB_LINEUP, 0), (LPARAM) NULL);
238 } else {
239 NHEVENT_KBD(KEYTABLE(KEY_W));
241 return 0;
243 case VK_RIGHT:
244 if (STATEON(VK_CONTROL)) {
245 /* scroll map window one line right */
246 SendMessage(mswin_hwnd_from_winid(WIN_MAP), WM_HSCROLL,
247 MAKEWPARAM(SB_LINEDOWN, 0), (LPARAM) NULL);
248 } else {
249 NHEVENT_KBD(KEYTABLE(KEY_E));
251 return 0;
253 case VK_UP:
254 if (STATEON(VK_CONTROL)) {
255 /* scroll map window one line up */
256 SendMessage(mswin_hwnd_from_winid(WIN_MAP), WM_VSCROLL,
257 MAKEWPARAM(SB_LINEUP, 0), (LPARAM) NULL);
258 } else {
259 NHEVENT_KBD(KEYTABLE(KEY_N));
261 return 0;
263 case VK_DOWN:
264 if (STATEON(VK_CONTROL)) {
265 /* scroll map window one line down */
266 SendMessage(mswin_hwnd_from_winid(WIN_MAP), WM_VSCROLL,
267 MAKEWPARAM(SB_LINEDOWN, 0), (LPARAM) NULL);
268 } else {
269 NHEVENT_KBD(KEYTABLE(KEY_S));
271 return 0;
273 case VK_HOME:
274 if (STATEON(VK_CONTROL)) {
275 /* scroll map window to upper left corner */
276 SendMessage(mswin_hwnd_from_winid(WIN_MAP), WM_VSCROLL,
277 MAKEWPARAM(SB_THUMBTRACK, 0), (LPARAM) NULL);
279 SendMessage(mswin_hwnd_from_winid(WIN_MAP), WM_HSCROLL,
280 MAKEWPARAM(SB_THUMBTRACK, 0), (LPARAM) NULL);
281 } else {
282 NHEVENT_KBD(KEYTABLE(KEY_NW));
284 return 0;
286 case VK_END:
287 if (STATEON(VK_CONTROL)) {
288 /* scroll map window to lower right corner */
289 SendMessage(mswin_hwnd_from_winid(WIN_MAP), WM_VSCROLL,
290 MAKEWPARAM(SB_THUMBTRACK, ROWNO), (LPARAM) NULL);
292 SendMessage(mswin_hwnd_from_winid(WIN_MAP), WM_HSCROLL,
293 MAKEWPARAM(SB_THUMBTRACK, COLNO), (LPARAM) NULL);
294 } else {
295 NHEVENT_KBD(KEYTABLE(KEY_SW));
297 return 0;
299 case VK_PRIOR:
300 if (STATEON(VK_CONTROL)) {
301 /* scroll map window one page up */
302 SendMessage(mswin_hwnd_from_winid(WIN_MAP), WM_VSCROLL,
303 MAKEWPARAM(SB_PAGEUP, 0), (LPARAM) NULL);
304 } else {
305 NHEVENT_KBD(KEYTABLE(KEY_NE));
307 return 0;
309 case VK_NEXT:
310 if (STATEON(VK_CONTROL)) {
311 /* scroll map window one page down */
312 SendMessage(mswin_hwnd_from_winid(WIN_MAP), WM_VSCROLL,
313 MAKEWPARAM(SB_PAGEDOWN, 0), (LPARAM) NULL);
314 } else {
315 NHEVENT_KBD(KEYTABLE(KEY_SE));
317 return 0;
319 case VK_DECIMAL:
320 case VK_DELETE:
321 NHEVENT_KBD(KEYTABLE(KEY_WAITLOOK));
322 return 0;
324 case VK_INSERT:
325 NHEVENT_KBD(KEYTABLE(KEY_INV));
326 return 0;
328 case VK_SUBTRACT:
329 NHEVENT_KBD(KEYTABLE(KEY_MINUS));
330 return 0;
332 case VK_ADD:
333 NHEVENT_KBD(KEYTABLE(KEY_PLUS));
334 return 0;
336 case VK_CLEAR: /* This is the '5' key */
337 NHEVENT_KBD(KEYTABLE(KEY_GOINTERESTING));
338 return 0;
340 case VK_F4:
341 if (IS_MAP_FIT_TO_SCREEN(iflags.wc_map_mode)) {
342 mswin_select_map_mode(IS_MAP_ASCII(iflags.wc_map_mode)
343 ? data->mapAcsiiModeSave
344 : MAP_MODE_TILES);
345 } else {
346 mswin_select_map_mode(IS_MAP_ASCII(iflags.wc_map_mode)
347 ? MAP_MODE_ASCII_FIT_TO_SCREEN
348 : MAP_MODE_TILES_FIT_TO_SCREEN);
350 return 0;
352 case VK_F5:
353 if (IS_MAP_ASCII(iflags.wc_map_mode)) {
354 if (IS_MAP_FIT_TO_SCREEN(iflags.wc_map_mode)) {
355 mswin_select_map_mode(MAP_MODE_TILES_FIT_TO_SCREEN);
356 } else {
357 mswin_select_map_mode(MAP_MODE_TILES);
359 } else {
360 if (IS_MAP_FIT_TO_SCREEN(iflags.wc_map_mode)) {
361 mswin_select_map_mode(MAP_MODE_ASCII_FIT_TO_SCREEN);
362 } else {
363 mswin_select_map_mode(data->mapAcsiiModeSave);
366 return 0;
368 case VK_RETURN: {
369 int x, y;
370 if (WIN_MAP != WIN_ERR) {
371 mswin_map_get_cursor(mswin_hwnd_from_winid(WIN_MAP), &x, &y);
372 } else {
373 x = u.ux;
374 y = u.uy;
376 NHEVENT_MS(CLICK_1, x, y);
378 return 0;
381 #if defined(WIN_CE_SMARTPHONE)
382 if (GetNHApp()->bCmdPad
383 && NHSPhoneTranslateKbdMessage(wParam, lParam, TRUE))
384 return 0;
385 #endif
386 return 1; /* end of WM_KEYDOWN */
388 /*-----------------------------------------------------------------------*/
390 #if defined(WIN_CE_SMARTPHONE)
391 case WM_KEYUP:
392 if (GetNHApp()->bCmdPad
393 && NHSPhoneTranslateKbdMessage(wParam, lParam, FALSE))
394 return 0;
395 return 1; /* end of WM_KEYUP */
396 #endif
397 /*-----------------------------------------------------------------------*/
399 case WM_CHAR:
400 #if defined(WIN_CE_SMARTPHONE)
401 /* if smartphone cmdpad is up then translation happens - disable
402 WM_CHAR processing
403 to avoid double input */
404 if (GetNHApp()->bCmdPad) {
405 return 1;
407 #endif
409 if (wParam == '\n' || wParam == '\r' || wParam == C('M'))
410 return 0; /* we already processed VK_RETURN */
412 /* all characters go to anethack except Ctrl-P that scrolls message
413 * window up */
414 if (wParam == C('P') || wParam == C('p')) {
415 SendMessage(mswin_hwnd_from_winid(WIN_MESSAGE), WM_VSCROLL,
416 MAKEWPARAM(SB_LINEUP, 0), (LPARAM) NULL);
417 } else {
418 NHEVENT_KBD((lParam & 1 << 29) ? M(tolower(wParam)) : wParam);
420 return 0;
422 /*-----------------------------------------------------------------------*/
424 case WM_COMMAND:
425 /* process commands - menu commands mostly */
426 if (IsWindow(GetNHApp()->hPopupWnd)) {
427 return SendMessage(GetNHApp()->hPopupWnd, message, wParam,
428 lParam);
429 } else if (onWMCommand(hWnd, wParam, lParam))
430 return DefWindowProc(hWnd, message, wParam, lParam);
431 else
432 return 0;
434 /*-----------------------------------------------------------------------*/
436 case WM_ACTIVATE:
437 if (LOWORD(wParam) != WA_INACTIVE) {
438 #if defined(WIN_CE_POCKETPC) || defined(WIN_CE_SMARTPHONE)
439 if (GetNHApp()->bFullScreen)
440 SHFullScreen(GetNHApp()->hMainWnd,
441 SHFS_HIDETASKBAR | SHFS_HIDESTARTICON);
442 else
443 SHFullScreen(GetNHApp()->hMainWnd,
444 SHFS_SHOWTASKBAR | SHFS_SHOWSTARTICON);
445 #endif
446 mswin_layout_main_window(NULL);
448 break;
450 case WM_SETTINGCHANGE:
451 #if defined(WIN_CE_POCKETPC) || defined(WIN_CE_SMARTPHONE)
452 if (GetNHApp()->bFullScreen)
453 SHFullScreen(GetNHApp()->hMainWnd,
454 SHFS_HIDETASKBAR | SHFS_HIDESTARTICON);
455 else
456 SHFullScreen(GetNHApp()->hMainWnd,
457 SHFS_SHOWTASKBAR | SHFS_SHOWSTARTICON);
458 #endif
459 mswin_layout_main_window(NULL);
460 break;
462 case WM_SIZE:
463 mswin_layout_main_window(NULL);
464 break;
466 /*-----------------------------------------------------------------------*/
468 case WM_SETFOCUS:
469 /* if there is a menu window out there -
470 transfer input focus to it */
471 if (IsWindow(GetNHApp()->hPopupWnd)) {
472 SetFocus(GetNHApp()->hPopupWnd);
474 break;
476 /*-----------------------------------------------------------------------*/
478 case WM_CLOSE: {
479 /* exit gracefully */
480 #ifdef SAFERHANGUP
481 /* destroy popup window - it has its own loop and we need to
482 return control to aNetHack core at this point */
483 if (IsWindow(GetNHApp()->hPopupWnd))
484 SendMessage(GetNHApp()->hPopupWnd, WM_COMMAND, IDCANCEL, 0);
486 /* tell aNetHack core that "hangup" is requested */
487 hangup(1);
488 #else
489 dosave0();
490 terminate(EXIT_SUCCESS);
491 #endif
493 return 0;
495 /*-----------------------------------------------------------------------*/
497 case WM_DESTROY: {
498 /* apparently we never get here
499 TODO: work on exit routines - need to send
500 WM_QUIT somehow */
502 /* clean up */
503 free((PNHMainWindow) GetWindowLong(hWnd, GWL_USERDATA));
504 SetWindowLong(hWnd, GWL_USERDATA, (LONG) 0);
506 terminate(EXIT_SUCCESS);
507 } break;
509 /*-----------------------------------------------------------------------*/
511 default:
512 return DefWindowProc(hWnd, message, wParam, lParam);
514 return 0;
517 void
518 onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
520 switch (wParam) {
521 /* new window was just added */
522 case MSNH_MSG_ADDWND: {
523 PMSNHMsgAddWnd msg_param = (PMSNHMsgAddWnd) lParam;
524 HWND child = GetNHApp()->windowlist[msg_param->wid].win;
526 if (GetNHApp()->windowlist[msg_param->wid].type == NHW_MAP)
527 mswin_select_map_mode(iflags.wc_map_mode);
529 if (child)
530 mswin_layout_main_window(child);
531 } break;
535 /* adjust windows to fit main window layout
536 ---------------------------
537 | Status |
538 +-------------------------+
541 | MAP |
544 +-------------------------+
545 | Command pad |
546 +-------------------------+
547 | Messages |
548 ---------------------------
550 void
551 mswin_layout_main_window(HWND changed_child)
553 winid i;
554 RECT client_rt, wnd_rect;
555 POINT status_org;
556 SIZE status_size;
557 POINT msg_org;
558 SIZE msg_size;
559 POINT map_org;
560 SIZE map_size;
561 POINT cmd_org;
562 SIZE cmd_size;
563 HWND wnd_status, wnd_msg;
564 PNHMainWindow data;
565 #if defined(WIN_CE_POCKETPC)
566 SIPINFO sip;
567 RECT menu_bar;
568 RECT visible_rt;
569 POINT pt;
570 #endif
572 GetClientRect(GetNHApp()->hMainWnd, &client_rt);
574 #if defined(WIN_CE_POCKETPC)
575 ZeroMemory(&sip, sizeof(sip));
576 sip.cbSize = sizeof(sip);
577 SHSipInfo(SPI_GETSIPINFO, 0, &sip, 0);
578 if (GetNHApp()->bFullScreen)
579 sip.rcVisibleDesktop.top = 0;
581 /* adjust client rectangle size */
582 GetWindowRect(GetNHApp()->hMenuBar, &menu_bar);
583 client_rt.bottom -= menu_bar.bottom - menu_bar.top;
585 /* calcuate visible rect in client coordinates */
586 pt.x = sip.rcVisibleDesktop.left;
587 pt.y = sip.rcVisibleDesktop.top;
588 ScreenToClient(GetNHApp()->hMainWnd, &pt);
589 SetRect(&wnd_rect, pt.x, pt.y,
590 pt.x + sip.rcVisibleDesktop.right - sip.rcVisibleDesktop.left,
591 pt.y + sip.rcVisibleDesktop.bottom - sip.rcVisibleDesktop.top);
592 IntersectRect(&visible_rt, &client_rt, &wnd_rect);
593 #else
594 #if !defined(WIN_CE_SMARTPHONE)
595 client_rt.top += CommandBar_Height(GetNHApp()->hMenuBar);
596 #else
597 /* Smartphone only */
598 if (GetNHApp()->bFullScreen) {
599 RECT menu_bar;
600 GetWindowRect(GetNHApp()->hMenuBar, &menu_bar);
601 client_rt.bottom -= menu_bar.bottom - menu_bar.top;
603 #endif
604 #endif
606 /* get window data */
607 data = (PNHMainWindow) GetWindowLong(GetNHApp()->hMainWnd, GWL_USERDATA);
609 /* get sizes of child windows */
610 wnd_status = mswin_hwnd_from_winid(WIN_STATUS);
611 if (IsWindow(wnd_status)) {
612 mswin_status_window_size(wnd_status, &status_size);
613 } else {
614 status_size.cx = status_size.cy = 0;
617 wnd_msg = mswin_hwnd_from_winid(WIN_MESSAGE);
618 if (IsWindow(wnd_msg)) {
619 mswin_message_window_size(wnd_msg, &msg_size);
620 } else {
621 msg_size.cx = msg_size.cy = 0;
624 cmd_size.cx = cmd_size.cy = 0;
625 if (GetNHApp()->bCmdPad && IsWindow(GetNHApp()->hCmdWnd)) {
626 mswin_command_window_size(GetNHApp()->hCmdWnd, &cmd_size);
629 /* set window positions */
631 /* calculate the application windows size */
632 #if defined(WIN_CE_POCKETPC)
633 SetRect(&wnd_rect, visible_rt.left, visible_rt.top, visible_rt.right,
634 visible_rt.bottom);
635 if (sip.fdwFlags & SIPF_ON)
636 cmd_size.cx = cmd_size.cy = 0; /* hide keypad window */
637 #else
638 SetRect(&wnd_rect, client_rt.left, client_rt.top, client_rt.right,
639 client_rt.bottom);
640 #endif
642 #if !defined(WIN_CE_SMARTPHONE)
643 /* other ports have it at the bottom of the screen */
644 cmd_size.cx = (wnd_rect.right - wnd_rect.left);
645 cmd_org.x = wnd_rect.left;
646 cmd_org.y = wnd_rect.bottom - cmd_size.cy;
647 wnd_rect.bottom -= cmd_size.cy;
648 #endif
650 /* status window */
651 switch (iflags.wc_align_status) {
652 case ALIGN_LEFT:
653 status_size.cx = (wnd_rect.right - wnd_rect.left) / 4;
654 status_size.cy =
655 (wnd_rect.bottom - wnd_rect.top); // that won't look good
656 status_org.x = wnd_rect.left;
657 status_org.y = wnd_rect.top;
658 wnd_rect.left += status_size.cx;
659 break;
661 case ALIGN_RIGHT:
662 status_size.cx = (wnd_rect.right - wnd_rect.left) / 4;
663 status_size.cy =
664 (wnd_rect.bottom - wnd_rect.top); // that won't look good
665 status_org.x = wnd_rect.right - status_size.cx;
666 status_org.y = wnd_rect.top;
667 wnd_rect.right -= status_size.cx;
668 break;
670 case ALIGN_TOP:
671 status_size.cx = (wnd_rect.right - wnd_rect.left);
672 status_org.x = wnd_rect.left;
673 status_org.y = wnd_rect.top;
674 wnd_rect.top += status_size.cy;
675 break;
677 case ALIGN_BOTTOM:
678 default:
679 status_size.cx = (wnd_rect.right - wnd_rect.left);
680 status_org.x = wnd_rect.left;
681 status_org.y = wnd_rect.bottom - status_size.cy;
682 wnd_rect.bottom -= status_size.cy;
683 break;
686 /* message window */
687 switch (iflags.wc_align_message) {
688 case ALIGN_LEFT:
689 #if defined(WIN_CE_SMARTPHONE)
690 /* smartphone has a keypad window on the right (bottom) side of the
691 * message window */
692 msg_size.cx = cmd_size.cx = max(msg_size.cx, cmd_size.cx);
693 msg_size.cy = (wnd_rect.bottom - wnd_rect.top) - cmd_size.cy;
694 msg_org.x = cmd_org.x = wnd_rect.left;
695 msg_org.y = wnd_rect.top;
696 cmd_org.y = msg_org.y + msg_size.cy;
697 #else
698 msg_size.cx = (wnd_rect.right - wnd_rect.left) / 4;
699 msg_size.cy = (wnd_rect.bottom - wnd_rect.top);
700 msg_org.x = wnd_rect.left;
701 msg_org.y = wnd_rect.top;
702 #endif
703 wnd_rect.left += msg_size.cx;
705 break;
707 case ALIGN_RIGHT:
708 #if defined(WIN_CE_SMARTPHONE)
709 /* smartphone has a keypad window on the right (bottom) side of the
710 * message window */
711 msg_size.cx = cmd_size.cx = max(msg_size.cx, cmd_size.cx);
712 msg_size.cy = (wnd_rect.bottom - wnd_rect.top) - cmd_size.cy;
713 msg_org.x = cmd_org.x = wnd_rect.right - msg_size.cx;
714 msg_org.y = wnd_rect.top;
715 cmd_org.y = msg_org.y + msg_size.cy;
716 #else
717 msg_size.cx = (wnd_rect.right - wnd_rect.left) / 4;
718 msg_size.cy = (wnd_rect.bottom - wnd_rect.top);
719 msg_org.x = wnd_rect.right - msg_size.cx;
720 msg_org.y = wnd_rect.top;
721 #endif
723 wnd_rect.right -= msg_size.cx;
724 break;
726 case ALIGN_TOP:
727 #if defined(WIN_CE_SMARTPHONE)
728 /* smartphone has a keypad window on the right side of the message
729 * window */
730 msg_size.cy = cmd_size.cy = max(msg_size.cy, cmd_size.cy);
731 msg_size.cx = (wnd_rect.right - wnd_rect.left) - cmd_size.cx;
732 msg_org.x = wnd_rect.left;
733 cmd_org.x = msg_org.x + msg_size.cx;
734 msg_org.y = cmd_org.y = wnd_rect.bottom - msg_size.cy;
735 #else
736 msg_size.cx = (wnd_rect.right - wnd_rect.left);
737 msg_org.x = wnd_rect.left;
738 msg_org.y = wnd_rect.top;
739 #endif
740 wnd_rect.top += msg_size.cy;
741 break;
743 case ALIGN_BOTTOM:
744 default:
745 #if defined(WIN_CE_SMARTPHONE)
746 /* smartphone has a keypad window on the right side of the message
747 * window */
748 msg_size.cy = cmd_size.cy = max(msg_size.cy, cmd_size.cy);
749 msg_size.cx = (wnd_rect.right - wnd_rect.left) - cmd_size.cx;
750 msg_org.x = wnd_rect.left;
751 cmd_org.x = msg_org.x + msg_size.cx;
752 msg_org.y = cmd_org.y = wnd_rect.bottom - msg_size.cy;
753 #else
754 msg_size.cx = (wnd_rect.right - wnd_rect.left);
755 msg_org.x = wnd_rect.left;
756 msg_org.y = wnd_rect.bottom - msg_size.cy;
757 #endif
758 wnd_rect.bottom -= msg_size.cy;
759 break;
762 map_org.x = wnd_rect.left;
763 map_org.y = wnd_rect.top;
764 map_size.cx = wnd_rect.right - wnd_rect.left;
765 map_size.cy = wnd_rect.bottom - wnd_rect.top;
767 /* go through the windows list and adjust sizes */
768 for (i = 0; i < MAXWINDOWS; i++) {
769 if (GetNHApp()->windowlist[i].win
770 && !GetNHApp()->windowlist[i].dead) {
771 switch (GetNHApp()->windowlist[i].type) {
772 case NHW_MESSAGE:
773 MoveWindow(GetNHApp()->windowlist[i].win, msg_org.x,
774 msg_org.y, msg_size.cx, msg_size.cy, TRUE);
775 break;
776 case NHW_MAP:
777 MoveWindow(GetNHApp()->windowlist[i].win, map_org.x,
778 map_org.y, map_size.cx, map_size.cy, TRUE);
779 break;
780 case NHW_STATUS:
781 MoveWindow(GetNHApp()->windowlist[i].win, status_org.x,
782 status_org.y, status_size.cx, status_size.cy,
783 TRUE);
784 break;
786 case NHW_TEXT:
787 case NHW_MENU:
788 case NHW_RIP: {
789 POINT menu_org;
790 SIZE menu_size;
792 menu_org.x = client_rt.left;
793 menu_org.y = client_rt.top;
794 #if defined(WIN_CE_POCKETPC)
795 menu_size.cx = min(sip.rcVisibleDesktop.right
796 - sip.rcVisibleDesktop.left,
797 client_rt.right - client_rt.left);
798 menu_size.cy = min(sip.rcVisibleDesktop.bottom
799 - sip.rcVisibleDesktop.top,
800 client_rt.bottom - client_rt.top);
801 #else
802 menu_size.cx = client_rt.right - client_rt.left;
803 menu_size.cy = client_rt.bottom - client_rt.top;
804 #endif
806 #if defined(WIN_CE_SMARTPHONE)
807 /* leave room for the command window */
808 if (GetNHApp()->windowlist[i].type == NHW_MENU) {
809 menu_size.cy -= cmd_size.cy;
812 /* dialogs are popup windows unde SmartPhone so we need
813 to convert to screen coordinates */
814 ClientToScreen(GetNHApp()->hMainWnd, &menu_org);
815 #endif
816 MoveWindow(GetNHApp()->windowlist[i].win, menu_org.x,
817 menu_org.y, menu_size.cx, menu_size.cy, TRUE);
818 } break;
820 ShowWindow(GetNHApp()->windowlist[i].win, SW_SHOW);
821 InvalidateRect(GetNHApp()->windowlist[i].win, NULL, TRUE);
825 if (IsWindow(GetNHApp()->hCmdWnd)) {
826 /* show command window only if it exists and
827 the game is ready (plname is set) */
828 if (GetNHApp()->bCmdPad && cmd_size.cx > 0 && cmd_size.cy > 0
829 && *plname) {
830 MoveWindow(GetNHApp()->hCmdWnd, cmd_org.x, cmd_org.y, cmd_size.cx,
831 cmd_size.cy, TRUE);
832 ShowWindow(GetNHApp()->hCmdWnd, SW_SHOW);
833 } else {
834 ShowWindow(GetNHApp()->hCmdWnd, SW_HIDE);
839 LRESULT
840 onWMCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
842 int wmId, wmEvent;
843 PNHMainWindow data;
845 data = (PNHMainWindow) GetWindowLong(hWnd, GWL_USERDATA);
846 wmId = LOWORD(wParam);
847 wmEvent = HIWORD(wParam);
849 // process the menu selections:
850 switch (wmId) {
851 case IDM_ABOUT:
852 DialogBox(GetNHApp()->hApp, (LPCTSTR) IDD_ABOUTBOX, hWnd,
853 (DLGPROC) About);
854 break;
856 case IDM_EXIT:
857 done2();
858 break;
860 case IDM_SAVE:
861 dosave();
862 break;
864 case IDM_MAP_TILES:
865 case IDM_MAP_ASCII4X6:
866 case IDM_MAP_ASCII6X8:
867 case IDM_MAP_ASCII8X8:
868 case IDM_MAP_ASCII16X8:
869 case IDM_MAP_ASCII7X12:
870 case IDM_MAP_ASCII8X12:
871 case IDM_MAP_ASCII12X16:
872 case IDM_MAP_ASCII16X12:
873 case IDM_MAP_ASCII10X18:
874 mswin_select_map_mode(menuid2mapmode(wmId));
875 break;
877 case IDM_MAP_FIT_TO_SCREEN:
878 if (IS_MAP_FIT_TO_SCREEN(iflags.wc_map_mode)) {
879 mswin_select_map_mode(IS_MAP_ASCII(iflags.wc_map_mode)
880 ? data->mapAcsiiModeSave
881 : MAP_MODE_TILES);
882 } else {
883 mswin_select_map_mode(IS_MAP_ASCII(iflags.wc_map_mode)
884 ? MAP_MODE_ASCII_FIT_TO_SCREEN
885 : MAP_MODE_TILES_FIT_TO_SCREEN);
887 break;
889 case IDM_VIEW_KEYPAD:
890 GetNHApp()->bCmdPad = !GetNHApp()->bCmdPad;
891 CheckMenuItem(
892 _get_main_menu(ID_VIEW), IDM_VIEW_KEYPAD,
893 MF_BYCOMMAND | (GetNHApp()->bCmdPad ? MF_CHECKED : MF_UNCHECKED));
894 mswin_layout_main_window(GetNHApp()->hCmdWnd);
895 break;
897 case IDM_VIEW_OPTIONS:
898 doset();
899 break;
901 case IDM_DIRECT_COMMAND: /* SmartPhone: display dialog to type in arbitary
902 command text */
903 mswin_direct_command();
904 break;
906 case IDM_HELP_LONG:
907 display_file(HELP, TRUE);
908 break;
910 case IDM_HELP_COMMANDS:
911 display_file(SHELP, TRUE);
912 break;
914 case IDM_HELP_HISTORY:
915 (void) dohistory();
916 break;
918 case IDM_HELP_INFO_CHAR:
919 (void) dowhatis();
920 break;
922 case IDM_HELP_INFO_KEY:
923 (void) dowhatdoes();
924 break;
926 case IDM_HELP_OPTIONS:
927 option_help();
928 break;
930 case IDM_HELP_OPTIONS_LONG:
931 display_file(OPTIONFILE, TRUE);
932 break;
934 case IDM_HELP_EXTCMD:
935 (void) doextlist();
936 break;
938 case IDM_HELP_LICENSE:
939 display_file(LICENSE, TRUE);
940 break;
942 case IDM_HELP_MENU:
943 dohelp();
944 break;
946 default:
947 return 1;
949 return 0;
952 // Mesage handler for about box.
953 LRESULT CALLBACK
954 About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
956 char buf[BUFSZ];
957 TCHAR wbuf[NHSTR_BUFSIZE];
958 RECT main_rt, dlg_rt;
959 SIZE dlg_sz;
961 switch (message) {
962 case WM_INITDIALOG:
963 getversionstring(buf);
964 SetDlgItemText(hDlg, IDC_ABOUT_VERSION,
965 NH_A2W(buf, wbuf, NHSTR_BUFSIZE));
967 SetDlgItemText(hDlg, IDC_ABOUT_COPYRIGHT,
968 NH_A2W(COPYRIGHT_BANNER_A "\n" COPYRIGHT_BANNER_B
969 "\n" COPYRIGHT_BANNER_C
970 "\n" COPYRIGHT_BANNER_D,
971 wbuf, NHSTR_BUFSIZE));
973 /* center dialog in the main window */
974 GetWindowRect(GetNHApp()->hMainWnd, &main_rt);
975 GetWindowRect(hDlg, &dlg_rt);
976 dlg_sz.cx = dlg_rt.right - dlg_rt.left;
977 dlg_sz.cy = dlg_rt.bottom - dlg_rt.top;
979 dlg_rt.left = (main_rt.left + main_rt.right - dlg_sz.cx) / 2;
980 dlg_rt.right = dlg_rt.left + dlg_sz.cx;
981 dlg_rt.top = (main_rt.top + main_rt.bottom - dlg_sz.cy) / 2;
982 dlg_rt.bottom = dlg_rt.top + dlg_sz.cy;
983 MoveWindow(hDlg, (main_rt.left + main_rt.right - dlg_sz.cx) / 2,
984 (main_rt.top + main_rt.bottom - dlg_sz.cy) / 2, dlg_sz.cx,
985 dlg_sz.cy, TRUE);
987 return TRUE;
989 case WM_COMMAND:
990 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
991 EndDialog(hDlg, LOWORD(wParam));
992 return TRUE;
994 break;
996 return FALSE;
999 /* Set map display mode */
1000 void
1001 mswin_select_map_mode(int mode)
1003 HMENU hmenuMap;
1004 PNHMainWindow data;
1005 winid map_id;
1007 map_id = WIN_MAP;
1008 data = (PNHMainWindow) GetWindowLong(GetNHApp()->hMainWnd, GWL_USERDATA);
1009 #if defined(WIN_CE_SMARTPHONE)
1010 /* Smartphone manu has only 2 items */
1011 hmenuMap = _get_main_menu(ID_VIEW);
1012 #else
1013 hmenuMap = _get_main_menu(ID_MAP);
1014 #endif
1016 /* override for Rogue level */
1017 if (Is_rogue_level(&u.uz) && !IS_MAP_ASCII(mode))
1018 return;
1020 /* set map mode menu mark */
1021 if (IS_MAP_ASCII(mode)) {
1022 CheckMenuRadioItem(hmenuMap, IDM_MAP_TILES, IDM_MAP_FIT_TO_SCREEN,
1023 mapmode2menuid(IS_MAP_FIT_TO_SCREEN(mode)
1024 ? data->mapAcsiiModeSave
1025 : mode),
1026 MF_BYCOMMAND);
1027 } else {
1028 CheckMenuRadioItem(hmenuMap, IDM_MAP_TILES, IDM_MAP_FIT_TO_SCREEN,
1029 mapmode2menuid(MAP_MODE_TILES), MF_BYCOMMAND);
1032 #if defined(WIN_CE_SMARTPHONE)
1033 /* update "Fit To Screen" item text */
1035 TCHAR wbuf[BUFSZ];
1036 TBBUTTONINFO tbbi;
1038 ZeroMemory(wbuf, sizeof(wbuf));
1039 if (!LoadString(GetNHApp()->hApp,
1040 (IS_MAP_FIT_TO_SCREEN(mode) ? IDS_CAP_NORMALMAP
1041 : IDS_CAP_ENTIREMAP),
1042 wbuf, BUFSZ)) {
1043 panic("cannot load main menu strings");
1046 ZeroMemory(&tbbi, sizeof(tbbi));
1047 tbbi.cbSize = sizeof(tbbi);
1048 tbbi.dwMask = TBIF_TEXT;
1049 tbbi.pszText = wbuf;
1050 if (!SendMessage(GetNHApp()->hMenuBar, TB_SETBUTTONINFO,
1051 IDM_MAP_FIT_TO_SCREEN, (LPARAM) &tbbi)) {
1052 error("Cannot update IDM_MAP_FIT_TO_SCREEN menu item.");
1055 #else
1056 /* set fit-to-screen mode mark */
1057 CheckMenuItem(hmenuMap, IDM_MAP_FIT_TO_SCREEN,
1058 MF_BYCOMMAND | (IS_MAP_FIT_TO_SCREEN(mode) ? MF_CHECKED
1059 : MF_UNCHECKED));
1060 #endif
1062 if (IS_MAP_ASCII(iflags.wc_map_mode)
1063 && !IS_MAP_FIT_TO_SCREEN(iflags.wc_map_mode)) {
1064 data->mapAcsiiModeSave = iflags.wc_map_mode;
1067 iflags.wc_map_mode = mode;
1070 ** first, check if WIN_MAP has been inialized.
1071 ** If not - attempt to retrieve it by type, then check it again
1073 if (WIN_MAP != WIN_ERR)
1074 mswin_map_mode(mswin_hwnd_from_winid(WIN_MAP), mode);
1077 static struct t_menu2mapmode {
1078 int menuID;
1079 int mapMode;
1080 } _menu2mapmode[] = { { IDM_MAP_TILES, MAP_MODE_TILES },
1081 { IDM_MAP_ASCII4X6, MAP_MODE_ASCII4x6 },
1082 { IDM_MAP_ASCII6X8, MAP_MODE_ASCII6x8 },
1083 { IDM_MAP_ASCII8X8, MAP_MODE_ASCII8x8 },
1084 { IDM_MAP_ASCII16X8, MAP_MODE_ASCII16x8 },
1085 { IDM_MAP_ASCII7X12, MAP_MODE_ASCII7x12 },
1086 { IDM_MAP_ASCII8X12, MAP_MODE_ASCII8x12 },
1087 { IDM_MAP_ASCII12X16, MAP_MODE_ASCII12x16 },
1088 { IDM_MAP_ASCII16X12, MAP_MODE_ASCII16x12 },
1089 { IDM_MAP_ASCII10X18, MAP_MODE_ASCII10x18 },
1090 { IDM_MAP_FIT_TO_SCREEN, MAP_MODE_ASCII_FIT_TO_SCREEN },
1091 { -1, -1 } };
1094 menuid2mapmode(int menuid)
1096 struct t_menu2mapmode *p;
1097 for (p = _menu2mapmode; p->mapMode != -1; p++)
1098 if (p->menuID == menuid)
1099 return p->mapMode;
1100 return -1;
1104 mapmode2menuid(int map_mode)
1106 struct t_menu2mapmode *p;
1107 for (p = _menu2mapmode; p->mapMode != -1; p++)
1108 if (p->mapMode == map_mode)
1109 return p->menuID;
1110 return -1;
1113 HMENU
1114 _get_main_menu(UINT menu_id)
1116 HMENU hmenuMap;
1117 #if defined(WIN_CE_POCKETPC) || defined(WIN_CE_SMARTPHONE)
1118 TBBUTTONINFO tbbi;
1119 #endif
1121 #if defined(WIN_CE_POCKETPC) || defined(WIN_CE_SMARTPHONE)
1122 tbbi.cbSize = sizeof(tbbi);
1123 tbbi.dwMask = TBIF_LPARAM;
1124 SendMessage(GetNHApp()->hMenuBar, TB_GETBUTTONINFO, menu_id,
1125 (LPARAM) &tbbi);
1126 hmenuMap = (HMENU) tbbi.lParam;
1127 #else
1128 hmenuMap = CommandBar_GetMenu(GetNHApp()->hMenuBar, 0);
1129 #endif
1130 return hmenuMap;
1133 /* SmartPhone: display dialog to type arbitrary command text */
1134 void
1135 mswin_direct_command()
1137 char cmd[BUFSZ];
1138 ZeroMemory(cmd, sizeof(cmd));
1139 mswin_getlin("Type cmd text", cmd);
1140 if (cmd[0]) {
1141 /* feed command to anethack */
1142 char *p = cmd;
1143 cmd[32] = '\x0'; /* truncate at 32 chars */
1144 while (*p) {
1145 NHEVENT_KBD(*p);
1146 p++;
1148 if (cmd[0] != '\033')
1149 mswin_putstr(WIN_MESSAGE, ATR_NONE, cmd);