1 /* Copyright (C) 2001 by Alex Kompel <shurikk@pacbell.net> */
2 /* NetHack may be freely redistributed. See license for details. */
5 * This file implements the interface between the window port specific
6 * code in the mswin port and the rest of the nethack game engine.
30 extern void logDebug(const char *fmt, ...);
32 void logDebug(const char *fmt, ...) { }
35 static void mswin_main_loop();
36 static BOOL initMapTiles(void);
37 static void prompt_for_player_selection(void);
39 /* Interface definition, for windows.c */
40 struct window_procs mswin_procs = {
42 WC_COLOR|WC_HILITE_PET|WC_ALIGN_MESSAGE|WC_ALIGN_STATUS|
43 WC_INVERSE|WC_SCROLL_MARGIN|WC_MAP_MODE|
44 WC_FONT_MESSAGE|WC_FONT_STATUS|WC_FONT_MENU|WC_FONT_TEXT|WC_FONT_MAP|
45 WC_FONTSIZ_MESSAGE|WC_FONTSIZ_STATUS|WC_FONTSIZ_MENU|WC_FONTSIZ_TEXT|
46 WC_TILE_WIDTH|WC_TILE_HEIGHT|WC_TILE_FILE|WC_VARY_MSGCOUNT|
47 WC_WINDOWCOLORS|WC_PLAYER_SELECTION,
48 WC2_FULLSCREEN|WC2_SOFTKEYBOARD|WC2_WRAPTEXT,
50 mswin_player_selection,
54 mswin_suspend_nhwindows,
55 mswin_resume_nhwindows,
56 mswin_create_nhwindow,
58 mswin_display_nhwindow,
59 mswin_destroy_nhwindow,
67 genl_message_menu, /* no need for X-specific handling */
68 mswin_update_inventory,
89 #ifdef CHANGE_COLOR /* only a Mac option currently */
91 mswin_change_background,
93 /* other defs that really should go away (they're tty specific) */
97 mswin_preference_update,
101 init_nhwindows(int* argcp, char** argv)
102 -- Initialize the windows used by NetHack. This can also
103 create the standard windows listed at the top, but does
105 -- Any commandline arguments relevant to the windowport
106 should be interpreted, and *argcp and *argv should
107 be changed to remove those arguments.
108 -- When the message window is created, the variable
109 iflags.window_inited needs to be set to TRUE. Otherwise
110 all plines() will be done via raw_print().
111 ** Why not have init_nhwindows() create all of the "standard"
112 ** windows? Or at least all but WIN_INFO? -dean
114 void mswin_init_nhwindows(int* argc, char** argv)
117 logDebug("mswin_init_nhwindows()\n");
121 /* truncate trace file */
122 FILE *dfp = fopen("nhtrace.log", "w");
127 /* intialize input subsystem */
128 mswin_nh_input_init();
130 /* read registry settings */
133 /* set it to WIN_ERR so we can detect attempts to
134 use this ID before it is inialized */
137 /* check default values */
138 if( iflags.wc_fontsiz_status<NHFONT_SIZE_MIN ||
139 iflags.wc_fontsiz_status>NHFONT_SIZE_MAX )
140 iflags.wc_fontsiz_status = NHFONT_STATUS_DEFAULT_SIZE;
142 if( iflags.wc_fontsiz_message<NHFONT_SIZE_MIN ||
143 iflags.wc_fontsiz_message>NHFONT_SIZE_MAX )
144 iflags.wc_fontsiz_message = NHFONT_DEFAULT_SIZE;
146 if( iflags.wc_fontsiz_text<NHFONT_SIZE_MIN ||
147 iflags.wc_fontsiz_text>NHFONT_SIZE_MAX )
148 iflags.wc_fontsiz_text = NHFONT_DEFAULT_SIZE;
150 if( iflags.wc_fontsiz_menu<NHFONT_SIZE_MIN ||
151 iflags.wc_fontsiz_menu>NHFONT_SIZE_MAX )
152 iflags.wc_fontsiz_menu = NHFONT_DEFAULT_SIZE;
154 if( iflags.wc_align_message==0 ) iflags.wc_align_message = ALIGN_BOTTOM;
155 if( iflags.wc_align_status==0 ) iflags.wc_align_status = ALIGN_TOP;
156 if( iflags.wc_scroll_margin==0 ) iflags.wc_scroll_margin = DEF_CLIPAROUND_MARGIN;
157 if( iflags.wc_tile_width==0 ) iflags.wc_tile_width = TILE_X;
158 if( iflags.wc_tile_height==0 ) iflags.wc_tile_height = TILE_Y;
160 if( iflags.wc_vary_msgcount==0 ) iflags.wc_vary_msgcount = 3;
162 /* force tabs in menus */
163 iflags.menu_tab_sep = 1;
165 /* force toptenwin to be true. toptenwin is the option that decides whether to
166 * write output to a window or stdout. stdout doesn't make sense on Windows
167 * non-console applications
170 set_option_mod_status("toptenwin", SET_IN_FILE);
172 /* initialize map tiles bitmap */
175 /* set tile-related options to readonly */
176 set_wc_option_mod_status(
177 WC_TILE_WIDTH|WC_TILE_HEIGHT|WC_TILE_FILE,
180 /* init color table */
181 mswin_init_color_table();
183 /* set font-related options to change in the game */
184 set_wc_option_mod_status(
203 set_wc2_option_mod_status(
208 GetNHApp()->bFullScreen = iflags.wc2_fullscreen;
209 GetNHApp()->bUseSIP = iflags.wc2_softkeyboard;
211 set_wc2_option_mod_status(
215 GetNHApp()->bWrapText = iflags.wc2_wraptext;
217 /* create the main nethack window */
218 hWnd = mswin_init_main_window();
219 if (!hWnd) panic( "Cannot create the main window." );
220 ShowWindow(hWnd, GetNHApp()->nCmdShow);
222 GetNHApp()->hMainWnd = hWnd;
224 /* set Full screen if requested */
225 mswin_set_fullscreen(GetNHApp()->bFullScreen);
227 /* let nethack code know that the window subsystem is ready */
228 iflags.window_inited = TRUE;
232 /* Do a window-port specific player type selection. If player_selection()
233 offers a Quit option, it is its responsibility to clean up and terminate
234 the process. You need to fill in pl_character[0].
236 void mswin_player_selection(void)
238 logDebug("mswin_player_selection()\n");
240 #if defined(WIN_CE_SMARTPHONE)
241 /* SmartPhone does not supprt combo-boxes therefor we cannot
242 use dialog for player selection */
243 prompt_for_player_selection();
245 if (iflags.wc_player_selection == VIA_DIALOG) {
248 /* pick player type randomly (use pre-selected role/race/gender/alignment) */
249 if( flags.randomall ) {
250 if (flags.initrole < 0) {
251 flags.initrole = pick_role(flags.initrace, flags.initgend,
252 flags.initalign, PICK_RANDOM);
253 if (flags.initrole < 0) {
254 raw_print("Incompatible role!");
255 flags.initrole = randrole();
259 if (flags.initrace < 0 || !validrace(flags.initrole, flags.initrace)) {
260 flags.initrace = pick_race(flags.initrole, flags.initgend,
261 flags.initalign, PICK_RANDOM);
262 if (flags.initrace < 0) {
263 raw_print("Incompatible race!");
264 flags.initrace = randrace(flags.initrole);
268 if (flags.initgend < 0 || !validgend(flags.initrole, flags.initrace,
270 flags.initgend = pick_gend(flags.initrole, flags.initrace,
271 flags.initalign, PICK_RANDOM);
272 if (flags.initgend < 0) {
273 raw_print("Incompatible gender!");
274 flags.initgend = randgend(flags.initrole, flags.initrace);
278 if (flags.initalign < 0 || !validalign(flags.initrole, flags.initrace,
280 flags.initalign = pick_align(flags.initrole, flags.initrace,
281 flags.initgend, PICK_RANDOM);
282 if (flags.initalign < 0) {
283 raw_print("Incompatible alignment!");
284 flags.initalign = randalign(flags.initrole, flags.initrace);
289 if( mswin_player_selection_window( &nRole ) == IDCANCEL ) {
293 } else { /* iflags.wc_player_selection == VIA_PROMPTS */
294 prompt_for_player_selection();
296 #endif /* defined(WIN_CE_SMARTPHONE) */
299 void prompt_for_player_selection(void)
302 char pick4u = 'n', thisch, lastch = 0;
303 char pbuf[QBUFSZ], plbuf[QBUFSZ];
306 menu_item *selected = 0;
310 logDebug("prompt_for_player_selection()\n");
312 /* prevent an unnecessary prompt */
315 /* Should we randomly pick for the player? */
316 if (!flags.randomall &&
317 (flags.initrole == ROLE_NONE || flags.initrace == ROLE_NONE ||
318 flags.initgend == ROLE_NONE || flags.initalign == ROLE_NONE)) {
320 char *prompt = build_plselection_prompt(pbuf, QBUFSZ, flags.initrole,
321 flags.initrace, flags.initgend, flags.initalign);
323 /* tty_putstr(BASE_WINDOW, 0, ""); */
324 /* echoline = wins[BASE_WINDOW]->cury; */
325 box_result = MessageBox(NULL,
326 NH_A2W(prompt, wbuf, BUFSZ),
327 TEXT("NetHack for Windows"),
328 #if defined(WIN_CE_SMARTPHONE)
329 MB_YESNO | MB_DEFBUTTON1
331 MB_YESNOCANCEL | MB_DEFBUTTON1
335 pick4u = (box_result == IDYES) ? 'y' : (box_result == IDNO) ? 'n' : '\033';
336 /* tty_putstr(BASE_WINDOW, 0, prompt); */
338 /* pick4u = lowc(readchar()); */
339 if (index(quitchars, pick4u)) pick4u = 'y';
340 } while(!index(ynqchars, pick4u));
341 if ((int)strlen(prompt) + 1 < CO) {
342 /* Echo choice and move back down line */
343 /* tty_putsym(BASE_WINDOW, (int)strlen(prompt)+1, echoline, pick4u); */
344 /* tty_putstr(BASE_WINDOW, 0, ""); */
346 /* Otherwise it's hard to tell where to echo, and things are
347 * wrapping a bit messily anyway, so (try to) make sure the next
348 * question shows up well and doesn't get wrapped at the
349 * bottom of the window.
351 /* tty_clear_nhwindow(BASE_WINDOW) */ ;
353 if (pick4u != 'y' && pick4u != 'n') {
355 if (selected) free((genericptr_t) selected);
362 (void) root_plselection_prompt(plbuf, QBUFSZ - 1,
363 flags.initrole, flags.initrace, flags.initgend, flags.initalign);
365 /* Select a role, if necessary */
366 /* we'll try to be compatible with pre-selected race/gender/alignment,
367 * but may not succeed */
368 if (flags.initrole < 0) {
369 char rolenamebuf[QBUFSZ];
370 /* Process the choice */
371 if (pick4u == 'y' || flags.initrole == ROLE_RANDOM || flags.randomall) {
372 /* Pick a random role */
373 flags.initrole = pick_role(flags.initrace, flags.initgend,
374 flags.initalign, PICK_RANDOM);
375 if (flags.initrole < 0) {
376 /* tty_putstr(BASE_WINDOW, 0, "Incompatible role!"); */
377 flags.initrole = randrole();
380 /* tty_clear_nhwindow(BASE_WINDOW); */
381 /* tty_putstr(BASE_WINDOW, 0, "Choosing Character's Role"); */
382 /* Prompt for a role */
383 win = create_nhwindow(NHW_MENU);
385 any.a_void = 0; /* zero out all bits */
386 for (i = 0; roles[i].name.m; i++) {
387 if (ok_role(i, flags.initrace, flags.initgend,
389 any.a_int = i+1; /* must be non-zero */
390 thisch = lowc(roles[i].name.m[0]);
391 if (thisch == lastch) thisch = highc(thisch);
392 if (flags.initgend != ROLE_NONE && flags.initgend != ROLE_RANDOM) {
393 if (flags.initgend == 1 && roles[i].name.f)
394 Strcpy(rolenamebuf, roles[i].name.f);
396 Strcpy(rolenamebuf, roles[i].name.m);
398 if (roles[i].name.f) {
399 Strcpy(rolenamebuf, roles[i].name.m);
400 Strcat(rolenamebuf, "/");
401 Strcat(rolenamebuf, roles[i].name.f);
403 Strcpy(rolenamebuf, roles[i].name.m);
405 add_menu(win, NO_GLYPH, &any, thisch,
406 0, ATR_NONE, an(rolenamebuf), MENU_UNSELECTED);
410 any.a_int = pick_role(flags.initrace, flags.initgend,
411 flags.initalign, PICK_RANDOM)+1;
412 if (any.a_int == 0) /* must be non-zero */
413 any.a_int = randrole()+1;
414 add_menu(win, NO_GLYPH, &any , '*', 0, ATR_NONE,
415 "Random", MENU_UNSELECTED);
416 any.a_int = i+1; /* must be non-zero */
417 add_menu(win, NO_GLYPH, &any , 'q', 0, ATR_NONE,
418 "Quit", MENU_UNSELECTED);
419 Sprintf(pbuf, "Pick a role for your %s", plbuf);
421 n = select_menu(win, PICK_ONE, &selected);
422 destroy_nhwindow(win);
424 /* Process the choice */
425 if (n != 1 || selected[0].item.a_int == any.a_int)
426 goto give_up; /* Selected quit */
428 flags.initrole = selected[0].item.a_int - 1;
429 free((genericptr_t) selected), selected = 0;
431 (void) root_plselection_prompt(plbuf, QBUFSZ - 1,
432 flags.initrole, flags.initrace, flags.initgend, flags.initalign);
435 /* Select a race, if necessary */
436 /* force compatibility with role, try for compatibility with
437 * pre-selected gender/alignment */
438 if (flags.initrace < 0 || !validrace(flags.initrole, flags.initrace)) {
439 /* pre-selected race not valid */
440 if (pick4u == 'y' || flags.initrace == ROLE_RANDOM || flags.randomall) {
441 flags.initrace = pick_race(flags.initrole, flags.initgend,
442 flags.initalign, PICK_RANDOM);
443 if (flags.initrace < 0) {
444 /* tty_putstr(BASE_WINDOW, 0, "Incompatible race!"); */
445 flags.initrace = randrace(flags.initrole);
447 } else { /* pick4u == 'n' */
448 /* Count the number of valid races */
449 n = 0; /* number valid */
450 k = 0; /* valid race */
451 for (i = 0; races[i].noun; i++) {
452 if (ok_race(flags.initrole, i, flags.initgend,
459 for (i = 0; races[i].noun; i++) {
460 if (validrace(flags.initrole, i)) {
467 /* Permit the user to pick, if there is more than one */
469 /* tty_clear_nhwindow(BASE_WINDOW); */
470 /* tty_putstr(BASE_WINDOW, 0, "Choosing Race"); */
471 win = create_nhwindow(NHW_MENU);
473 any.a_void = 0; /* zero out all bits */
474 for (i = 0; races[i].noun; i++)
475 if (ok_race(flags.initrole, i, flags.initgend,
477 any.a_int = i+1; /* must be non-zero */
478 add_menu(win, NO_GLYPH, &any, races[i].noun[0],
479 0, ATR_NONE, races[i].noun, MENU_UNSELECTED);
481 any.a_int = pick_race(flags.initrole, flags.initgend,
482 flags.initalign, PICK_RANDOM)+1;
483 if (any.a_int == 0) /* must be non-zero */
484 any.a_int = randrace(flags.initrole)+1;
485 add_menu(win, NO_GLYPH, &any , '*', 0, ATR_NONE,
486 "Random", MENU_UNSELECTED);
487 any.a_int = i+1; /* must be non-zero */
488 add_menu(win, NO_GLYPH, &any , 'q', 0, ATR_NONE,
489 "Quit", MENU_UNSELECTED);
490 Sprintf(pbuf, "Pick the race of your %s", plbuf);
492 n = select_menu(win, PICK_ONE, &selected);
493 destroy_nhwindow(win);
494 if (n != 1 || selected[0].item.a_int == any.a_int)
495 goto give_up; /* Selected quit */
497 k = selected[0].item.a_int - 1;
498 free((genericptr_t) selected), selected = 0;
502 (void) root_plselection_prompt(plbuf, QBUFSZ - 1,
503 flags.initrole, flags.initrace, flags.initgend, flags.initalign);
506 /* Select a gender, if necessary */
507 /* force compatibility with role/race, try for compatibility with
508 * pre-selected alignment */
509 if (flags.initgend < 0 || !validgend(flags.initrole, flags.initrace,
511 /* pre-selected gender not valid */
512 if (pick4u == 'y' || flags.initgend == ROLE_RANDOM || flags.randomall) {
513 flags.initgend = pick_gend(flags.initrole, flags.initrace,
514 flags.initalign, PICK_RANDOM);
515 if (flags.initgend < 0) {
516 /* tty_putstr(BASE_WINDOW, 0, "Incompatible gender!"); */
517 flags.initgend = randgend(flags.initrole, flags.initrace);
519 } else { /* pick4u == 'n' */
520 /* Count the number of valid genders */
521 n = 0; /* number valid */
522 k = 0; /* valid gender */
523 for (i = 0; i < ROLE_GENDERS; i++) {
524 if (ok_gend(flags.initrole, flags.initrace, i,
531 for (i = 0; i < ROLE_GENDERS; i++) {
532 if (validgend(flags.initrole, flags.initrace, i)) {
539 /* Permit the user to pick, if there is more than one */
541 /* tty_clear_nhwindow(BASE_WINDOW); */
542 /* tty_putstr(BASE_WINDOW, 0, "Choosing Gender"); */
543 win = create_nhwindow(NHW_MENU);
545 any.a_void = 0; /* zero out all bits */
546 for (i = 0; i < ROLE_GENDERS; i++)
547 if (ok_gend(flags.initrole, flags.initrace, i,
550 add_menu(win, NO_GLYPH, &any, genders[i].adj[0],
551 0, ATR_NONE, genders[i].adj, MENU_UNSELECTED);
553 any.a_int = pick_gend(flags.initrole, flags.initrace,
554 flags.initalign, PICK_RANDOM)+1;
555 if (any.a_int == 0) /* must be non-zero */
556 any.a_int = randgend(flags.initrole, flags.initrace)+1;
557 add_menu(win, NO_GLYPH, &any , '*', 0, ATR_NONE,
558 "Random", MENU_UNSELECTED);
559 any.a_int = i+1; /* must be non-zero */
560 add_menu(win, NO_GLYPH, &any , 'q', 0, ATR_NONE,
561 "Quit", MENU_UNSELECTED);
562 Sprintf(pbuf, "Pick the gender of your %s", plbuf);
564 n = select_menu(win, PICK_ONE, &selected);
565 destroy_nhwindow(win);
566 if (n != 1 || selected[0].item.a_int == any.a_int)
567 goto give_up; /* Selected quit */
569 k = selected[0].item.a_int - 1;
570 free((genericptr_t) selected), selected = 0;
574 (void) root_plselection_prompt(plbuf, QBUFSZ - 1,
575 flags.initrole, flags.initrace, flags.initgend, flags.initalign);
578 /* Select an alignment, if necessary */
579 /* force compatibility with role/race/gender */
580 if (flags.initalign < 0 || !validalign(flags.initrole, flags.initrace,
582 /* pre-selected alignment not valid */
583 if (pick4u == 'y' || flags.initalign == ROLE_RANDOM || flags.randomall) {
584 flags.initalign = pick_align(flags.initrole, flags.initrace,
585 flags.initgend, PICK_RANDOM);
586 if (flags.initalign < 0) {
587 /* tty_putstr(BASE_WINDOW, 0, "Incompatible alignment!"); */
588 flags.initalign = randalign(flags.initrole, flags.initrace);
590 } else { /* pick4u == 'n' */
591 /* Count the number of valid alignments */
592 n = 0; /* number valid */
593 k = 0; /* valid alignment */
594 for (i = 0; i < ROLE_ALIGNS; i++) {
595 if (ok_align(flags.initrole, flags.initrace, flags.initgend,
602 for (i = 0; i < ROLE_ALIGNS; i++) {
603 if (validalign(flags.initrole, flags.initrace, i)) {
610 /* Permit the user to pick, if there is more than one */
612 /* tty_clear_nhwindow(BASE_WINDOW); */
613 /* tty_putstr(BASE_WINDOW, 0, "Choosing Alignment"); */
614 win = create_nhwindow(NHW_MENU);
616 any.a_void = 0; /* zero out all bits */
617 for (i = 0; i < ROLE_ALIGNS; i++)
618 if (ok_align(flags.initrole, flags.initrace,
619 flags.initgend, i)) {
621 add_menu(win, NO_GLYPH, &any, aligns[i].adj[0],
622 0, ATR_NONE, aligns[i].adj, MENU_UNSELECTED);
624 any.a_int = pick_align(flags.initrole, flags.initrace,
625 flags.initgend, PICK_RANDOM)+1;
626 if (any.a_int == 0) /* must be non-zero */
627 any.a_int = randalign(flags.initrole, flags.initrace)+1;
628 add_menu(win, NO_GLYPH, &any , '*', 0, ATR_NONE,
629 "Random", MENU_UNSELECTED);
630 any.a_int = i+1; /* must be non-zero */
631 add_menu(win, NO_GLYPH, &any , 'q', 0, ATR_NONE,
632 "Quit", MENU_UNSELECTED);
633 Sprintf(pbuf, "Pick the alignment of your %s", plbuf);
635 n = select_menu(win, PICK_ONE, &selected);
636 destroy_nhwindow(win);
637 if (n != 1 || selected[0].item.a_int == any.a_int)
638 goto give_up; /* Selected quit */
640 k = selected[0].item.a_int - 1;
641 free((genericptr_t) selected), selected = 0;
647 /* tty_display_nhwindow(BASE_WINDOW, FALSE); */
650 /* Ask the user for a player name. */
651 void mswin_askname(void)
653 logDebug("mswin_askname()\n");
655 if( mswin_getlin_window("who are you?", plname, PL_NSIZ)==IDCANCEL ) {
662 /* Does window event processing (e.g. exposure events).
663 A noop for the tty and X window-ports.
665 void mswin_get_nh_event(void)
667 logDebug("mswin_get_nh_event()\n");
671 /* Exits the window system. This should dismiss all windows,
672 except the "window" used for raw_print(). str is printed if possible.
674 void mswin_exit_nhwindows(const char *str)
676 logDebug("mswin_exit_nhwindows(%s)\n", str);
678 /* Write Window settings to the registry */
681 // Don't do any of this (?) - exit_nhwindows does not terminate
683 // DestroyWindow(GetNHApp()->hMainWnd);
684 // terminate(EXIT_SUCCESS);
687 /* Prepare the window to be suspended. */
688 void mswin_suspend_nhwindows(const char *str)
690 logDebug("mswin_suspend_nhwindows(%s)\n", str);
695 /* Restore the windows after being suspended. */
696 void mswin_resume_nhwindows()
698 logDebug("mswin_resume_nhwindows()\n");
702 /* Create a window of type "type" which can be
703 NHW_MESSAGE (top line)
704 NHW_STATUS (bottom lines)
705 NHW_MAP (main dungeon)
706 NHW_MENU (inventory or other "corner" windows)
707 NHW_TEXT (help/text, full screen paged window)
710 mswin_create_nhwindow(int type)
715 logDebug("mswin_create_nhwindow(%d)\n", type);
717 /* Return the next available winid
720 for (i=1; i<MAXWINDOWS; i++)
721 if (GetNHApp()->windowlist[i].win == NULL &&
722 !GetNHApp()->windowlist[i].dead)
725 panic ("ERROR: No windows available...\n");
730 GetNHApp()->windowlist[i].win = mswin_init_map_window();
731 GetNHApp()->windowlist[i].type = type;
732 GetNHApp()->windowlist[i].dead = 0;
737 GetNHApp()->windowlist[i].win = mswin_init_message_window();
738 GetNHApp()->windowlist[i].type = type;
739 GetNHApp()->windowlist[i].dead = 0;
744 GetNHApp()->windowlist[i].win = mswin_init_status_window();
745 GetNHApp()->windowlist[i].type = type;
746 GetNHApp()->windowlist[i].dead = 0;
751 GetNHApp()->windowlist[i].win = NULL; //will create later
752 GetNHApp()->windowlist[i].type = type;
753 GetNHApp()->windowlist[i].dead = 1;
758 GetNHApp()->windowlist[i].win = mswin_init_text_window();
759 GetNHApp()->windowlist[i].type = type;
760 GetNHApp()->windowlist[i].dead = 0;
765 ZeroMemory(&data, sizeof(data) );
767 SendMessage( GetNHApp()->hMainWnd,
768 WM_MSNH_COMMAND, (WPARAM)MSNH_MSG_ADDWND, (LPARAM)&data );
772 /* Clear the given window, when asked to. */
773 void mswin_clear_nhwindow(winid wid)
775 logDebug("mswin_clear_nhwindow(%d)\n", wid);
778 (wid < MAXWINDOWS) &&
779 (GetNHApp()->windowlist[wid].win != NULL))
782 if( GetNHApp()->windowlist[wid].type == NHW_MAP ) {
783 if( Is_rogue_level(&u.uz) )
784 mswin_map_mode(mswin_hwnd_from_winid(WIN_MAP), ROGUE_LEVEL_MAP_MODE);
786 mswin_map_mode(mswin_hwnd_from_winid(WIN_MAP), iflags.wc_map_mode);
791 GetNHApp()->windowlist[wid].win,
792 WM_MSNH_COMMAND, (WPARAM)MSNH_MSG_CLEAR_WINDOW, (LPARAM)NULL );
796 /* -- Display the window on the screen. If there is data
797 pending for output in that window, it should be sent.
798 If blocking is TRUE, display_nhwindow() will not
799 return until the data has been displayed on the screen,
800 and acknowledged by the user where appropriate.
801 -- All calls are blocking in the tty window-port.
802 -- Calling display_nhwindow(WIN_MESSAGE,???) will do a
803 --more--, if necessary, in the tty window-port.
805 void mswin_display_nhwindow(winid wid, BOOLEAN_P block)
807 logDebug("mswin_display_nhwindow(%d, %d)\n", wid, block);
808 if (GetNHApp()->windowlist[wid].win != NULL)
810 if (GetNHApp()->windowlist[wid].type == NHW_MENU) {
812 mswin_menu_window_select_menu(GetNHApp()->windowlist[wid].win, PICK_NONE, &p);
813 } if (GetNHApp()->windowlist[wid].type == NHW_TEXT) {
814 mswin_display_text_window(GetNHApp()->windowlist[wid].win);
815 } if (GetNHApp()->windowlist[wid].type == NHW_RIP) {
816 mswin_display_RIP_window(GetNHApp()->windowlist[wid].win);
819 UpdateWindow(GetNHApp()->windowlist[wid].win);
821 if ( GetNHApp()->windowlist[wid].type == NHW_MAP ) {
822 (void) mswin_nhgetch();
826 SetFocus(GetNHApp()->hMainWnd);
831 HWND mswin_hwnd_from_winid(winid wid)
833 if( wid>=0 && wid<MAXWINDOWS) {
834 return GetNHApp()->windowlist[wid].win;
840 winid mswin_winid_from_handle(HWND hWnd)
844 for (i=1; i<MAXWINDOWS; i++)
845 if (GetNHApp()->windowlist[i].win == hWnd)
850 winid mswin_winid_from_type(int type)
854 for (i=1; i<MAXWINDOWS; i++)
855 if (GetNHApp()->windowlist[i].type == type)
860 void mswin_window_mark_dead(winid wid)
862 if( wid>=0 && wid<MAXWINDOWS) {
863 GetNHApp()->windowlist[wid].win = NULL;
864 GetNHApp()->windowlist[wid].dead = 1;
868 /* Destroy will dismiss the window if the window has not
869 * already been dismissed.
871 void mswin_destroy_nhwindow(winid wid)
873 logDebug("mswin_destroy_nhwindow(%d)\n", wid);
875 if ((GetNHApp()->windowlist[wid].type == NHW_MAP) ||
876 (GetNHApp()->windowlist[wid].type == NHW_MESSAGE) ||
877 (GetNHApp()->windowlist[wid].type == NHW_STATUS)) {
878 /* main windows is going to take care of those */
883 if( !GetNHApp()->windowlist[wid].dead &&
884 GetNHApp()->windowlist[wid].win != NULL )
885 DestroyWindow(GetNHApp()->windowlist[wid].win);
886 GetNHApp()->windowlist[wid].win = NULL;
887 GetNHApp()->windowlist[wid].type = 0;
888 GetNHApp()->windowlist[wid].dead = 0;
892 /* Next output to window will start at (x,y), also moves
893 displayable cursor to (x,y). For backward compatibility,
894 1 <= x < cols, 0 <= y < rows, where cols and rows are
897 void mswin_curs(winid wid, int x, int y)
899 logDebug("mswin_curs(%d, %d, %d)\n", wid, x, y);
902 (wid < MAXWINDOWS) &&
903 (GetNHApp()->windowlist[wid].win != NULL))
909 GetNHApp()->windowlist[wid].win,
910 WM_MSNH_COMMAND, (WPARAM)MSNH_MSG_CURSOR, (LPARAM)&data );
915 putstr(window, attr, str)
916 -- Print str on the window with the given attribute. Only
917 printable ASCII characters (040-0126) must be supported.
918 Multiple putstr()s are output on separate lines.
926 If a window-port does not support all of these, it may map
927 unsupported attributes to a supported one (e.g. map them
928 all to ATR_INVERSE). putstr() may compress spaces out of
929 str, break str, or truncate str, if necessary for the
930 display. Where putstr() breaks a line, it has to clear
932 -- putstr should be implemented such that if two putstr()s
933 are done consecutively the user will see the first and
934 then the second. In the tty port, pline() achieves this
935 by calling more() or displaying both on the same line.
937 void mswin_putstr(winid wid, int attr, const char *text)
939 logDebug("mswin_putstr(%d, %d, %s)\n", wid, attr, text);
941 mswin_putstr_ex(wid, attr, text, 0);
944 void mswin_putstr_ex(winid wid, int attr, const char *text, boolean app)
949 if( GetNHApp()->windowlist[wid].win==NULL &&
950 GetNHApp()->windowlist[wid].type==NHW_MENU ) {
951 GetNHApp()->windowlist[wid].win = mswin_init_menu_window(MENU_TYPE_TEXT);
952 GetNHApp()->windowlist[wid].dead = 0;
955 if (GetNHApp()->windowlist[wid].win != NULL)
958 ZeroMemory(&data, sizeof(data));
963 GetNHApp()->windowlist[wid].win,
964 WM_MSNH_COMMAND, (WPARAM)MSNH_MSG_PUTSTR, (LPARAM)&data );
969 /* Display the file named str. Complain about missing files
970 iff complain is TRUE.
972 void mswin_display_file(const char *filename,BOOLEAN_P must_exist)
977 logDebug("mswin_display_file(%s, %d)\n", filename, must_exist);
979 f = dlb_fopen(filename, RDTMODE);
983 _stprintf(message, TEXT("Warning! Could not find file: %s\n"), NH_A2W(filename, wbuf, sizeof(wbuf)));
984 MessageBox(GetNHApp()->hMainWnd, message, TEXT("ERROR"), MB_OK | MB_ICONERROR );
990 text = mswin_create_nhwindow(NHW_TEXT);
992 while (dlb_fgets(line, LLEN, f)) {
995 if( line[len-1]=='\n' ) line[len-1]='\x0';
996 mswin_putstr(text, ATR_NONE, line);
998 (void) dlb_fclose(f);
1000 mswin_display_nhwindow(text, 1);
1001 mswin_destroy_nhwindow(text);
1005 /* Start using window as a menu. You must call start_menu()
1006 before add_menu(). After calling start_menu() you may not
1007 putstr() to the window. Only windows of type NHW_MENU may
1010 void mswin_start_menu(winid wid)
1012 logDebug("mswin_start_menu(%d)\n", wid);
1014 (wid < MAXWINDOWS) ) {
1015 if( GetNHApp()->windowlist[wid].win==NULL &&
1016 GetNHApp()->windowlist[wid].type==NHW_MENU ) {
1017 GetNHApp()->windowlist[wid].win = mswin_init_menu_window(MENU_TYPE_MENU);
1018 GetNHApp()->windowlist[wid].dead = 0;
1021 if(GetNHApp()->windowlist[wid].win != NULL) {
1023 GetNHApp()->windowlist[wid].win,
1024 WM_MSNH_COMMAND, (WPARAM)MSNH_MSG_STARTMENU, (LPARAM)NULL
1031 add_menu(windid window, int glyph, const anything identifier,
1032 char accelerator, char groupacc,
1033 int attr, char *str, boolean preselected)
1034 -- Add a text line str to the given menu window. If identifier
1035 is 0, then the line cannot be selected (e.g. a title).
1036 Otherwise, identifier is the value returned if the line is
1037 selected. Accelerator is a keyboard key that can be used
1038 to select the line. If the accelerator of a selectable
1039 item is 0, the window system is free to select its own
1040 accelerator. It is up to the window-port to make the
1041 accelerator visible to the user (e.g. put "a - " in front
1042 of str). The value attr is the same as in putstr().
1043 Glyph is an optional glyph to accompany the line. If
1044 window port cannot or does not want to display it, this
1045 is OK. If there is no glyph applicable, then this
1046 value will be NO_GLYPH.
1047 -- All accelerators should be in the range [A-Za-z].
1048 -- It is expected that callers do not mix accelerator
1049 choices. Either all selectable items have an accelerator
1050 or let the window system pick them. Don't do both.
1051 -- Groupacc is a group accelerator. It may be any character
1052 outside of the standard accelerator (see above) or a
1053 number. If 0, the item is unaffected by any group
1054 accelerator. If this accelerator conflicts with
1055 the menu command (or their user defined alises), it loses.
1056 The menu commands and aliases take care not to interfere
1057 with the default object class symbols.
1058 -- If you want this choice to be preselected when the
1059 menu is displayed, set preselected to TRUE.
1061 void mswin_add_menu(winid wid, int glyph, const ANY_P * identifier,
1062 CHAR_P accelerator, CHAR_P group_accel, int attr,
1063 const char *str, BOOLEAN_P presel)
1065 logDebug("mswin_add_menu(%d, %d, %p, %c, %c, %d, %s, %d)\n",
1066 wid, glyph, identifier, (char)accelerator, (char)group_accel,
1069 (wid < MAXWINDOWS) &&
1070 (GetNHApp()->windowlist[wid].win != NULL))
1072 MSNHMsgAddMenu data;
1073 ZeroMemory(&data, sizeof(data));
1075 data.identifier = identifier;
1076 data.accelerator = accelerator;
1077 data.group_accel = group_accel;
1080 data.presel = presel;
1083 GetNHApp()->windowlist[wid].win,
1084 WM_MSNH_COMMAND, (WPARAM)MSNH_MSG_ADDMENU, (LPARAM)&data
1090 end_menu(window, prompt)
1091 -- Stop adding entries to the menu and flushes the window
1092 to the screen (brings to front?). Prompt is a prompt
1093 to give the user. If prompt is NULL, no prompt will
1095 ** This probably shouldn't flush the window any more (if
1096 ** it ever did). That should be select_menu's job. -dean
1098 void mswin_end_menu(winid wid, const char *prompt)
1100 logDebug("mswin_end_menu(%d, %s)\n", wid, prompt);
1102 (wid < MAXWINDOWS) &&
1103 (GetNHApp()->windowlist[wid].win != NULL))
1105 MSNHMsgEndMenu data;
1106 ZeroMemory(&data, sizeof(data));
1110 GetNHApp()->windowlist[wid].win,
1111 WM_MSNH_COMMAND, (WPARAM)MSNH_MSG_ENDMENU, (LPARAM)&data
1117 int select_menu(windid window, int how, menu_item **selected)
1118 -- Return the number of items selected; 0 if none were chosen,
1119 -1 when explicitly cancelled. If items were selected, then
1120 selected is filled in with an allocated array of menu_item
1121 structures, one for each selected line. The caller must
1122 free this array when done with it. The "count" field
1123 of selected is a user supplied count. If the user did
1124 not supply a count, then the count field is filled with
1125 -1 (meaning all). A count of zero is equivalent to not
1126 being selected and should not be in the list. If no items
1127 were selected, then selected is NULL'ed out. How is the
1128 mode of the menu. Three valid values are PICK_NONE,
1129 PICK_ONE, and PICK_N, meaning: nothing is selectable,
1130 only one thing is selectable, and any number valid items
1131 may selected. If how is PICK_NONE, this function should
1132 never return anything but 0 or -1.
1133 -- You may call select_menu() on a window multiple times --
1134 the menu is saved until start_menu() or destroy_nhwindow()
1135 is called on the window.
1136 -- Note that NHW_MENU windows need not have select_menu()
1137 called for them. There is no way of knowing whether
1138 select_menu() will be called for the window at
1139 create_nhwindow() time.
1141 int mswin_select_menu(winid wid, int how, MENU_ITEM_P **selected)
1145 logDebug("mswin_select_menu(%d, %d)\n", wid, how);
1148 (wid < MAXWINDOWS) &&
1149 (GetNHApp()->windowlist[wid].win != NULL))
1151 nReturned = mswin_menu_window_select_menu(GetNHApp()->windowlist[wid].win, how, selected);
1157 -- Indicate to the window port that the inventory has been changed.
1158 -- Merely calls display_inventory() for window-ports that leave the
1159 window up, otherwise empty.
1161 void mswin_update_inventory()
1163 logDebug("mswin_update_inventory()\n");
1167 mark_synch() -- Don't go beyond this point in I/O on any channel until
1168 all channels are caught up to here. Can be an empty call
1171 void mswin_mark_synch()
1173 logDebug("mswin_mark_synch()\n");
1177 wait_synch() -- Wait until all pending output is complete (*flush*() for
1179 -- May also deal with exposure events etc. so that the
1180 display is OK when return from wait_synch().
1182 void mswin_wait_synch()
1184 logDebug("mswin_wait_synch()\n");
1188 cliparound(x, y)-- Make sure that the user is more-or-less centered on the
1189 screen if the playing area is larger than the screen.
1190 -- This function is only defined if CLIPPING is defined.
1192 void mswin_cliparound(int x, int y)
1194 winid wid = WIN_MAP;
1196 logDebug("mswin_cliparound(%d, %d)\n", x, y);
1199 (wid < MAXWINDOWS) &&
1200 (GetNHApp()->windowlist[wid].win != NULL))
1202 MSNHMsgClipAround data;
1206 GetNHApp()->windowlist[wid].win,
1207 WM_MSNH_COMMAND, (WPARAM)MSNH_MSG_CLIPAROUND, (LPARAM)&data );
1212 print_glyph(window, x, y, glyph)
1213 -- Print the glyph at (x,y) on the given window. Glyphs are
1214 integers at the interface, mapped to whatever the window-
1215 port wants (symbol, font, color, attributes, ...there's
1216 a 1-1 map between glyphs and distinct things on the map).
1218 void mswin_print_glyph(winid wid,XCHAR_P x,XCHAR_P y,int glyph)
1220 logDebug("mswin_print_glyph(%d, %d, %d, %d)\n", wid, x, y, glyph);
1223 (wid < MAXWINDOWS) &&
1224 (GetNHApp()->windowlist[wid].win != NULL))
1226 MSNHMsgPrintGlyph data;
1228 ZeroMemory(&data, sizeof(data) );
1232 SendMessage( GetNHApp()->windowlist[wid].win,
1233 WM_MSNH_COMMAND, (WPARAM)MSNH_MSG_PRINT_GLYPH, (LPARAM)&data );
1238 raw_print(str) -- Print directly to a screen, or otherwise guarantee that
1239 the user sees str. raw_print() appends a newline to str.
1240 It need not recognize ASCII control characters. This is
1241 used during startup (before windowing system initialization
1242 -- maybe this means only error startup messages are raw),
1243 for error messages, and maybe other "msg" uses. E.g.
1244 updating status for micros (i.e, "saving").
1246 void mswin_raw_print(const char *str)
1249 logDebug("mswin_raw_print(%s)\n", str);
1251 MessageBox(GetNHApp()->hMainWnd, NH_A2W(str, wbuf, sizeof(wbuf)), TEXT("NetHack"), MB_OK );
1256 -- Like raw_print(), but prints in bold/standout (if
1259 void mswin_raw_print_bold(const char *str)
1262 logDebug("mswin_raw_print_bold(%s)\n", str);
1264 MessageBox(GetNHApp()->hMainWnd, NH_A2W(str, wbuf, sizeof(wbuf)), TEXT("NetHack"), MB_OK );
1268 int nhgetch() -- Returns a single character input from the user.
1269 -- In the tty window-port, nhgetch() assumes that tgetch()
1270 will be the routine the OS provides to read a character.
1271 Returned character _must_ be non-zero.
1278 logDebug("mswin_nhgetch()\n");
1281 while( (event = mswin_input_pop()) == NULL ||
1282 event->type != NHEVENT_CHAR )
1285 key = event->kbd.ch;
1290 int nh_poskey(int *x, int *y, int *mod)
1291 -- Returns a single character input from the user or a
1292 a positioning event (perhaps from a mouse). If the
1293 return value is non-zero, a character was typed, else,
1294 a position in the MAP window is returned in x, y and mod.
1297 CLICK_1 -- mouse click type 1
1298 CLICK_2 -- mouse click type 2
1300 The different click types can map to whatever the
1301 hardware supports. If no mouse is supported, this
1302 routine always returns a non-zero character.
1304 int mswin_nh_poskey(int *x, int *y, int *mod)
1309 logDebug("mswin_nh_poskey()\n");
1311 while( (event = mswin_input_pop())==NULL ) mswin_main_loop();
1313 if( event->type==NHEVENT_MOUSE ) {
1314 *mod = event->ms.mod;
1319 key = event->kbd.ch;
1325 nhbell() -- Beep at user. [This will exist at least until sounds are
1326 redone, since sounds aren't attributable to windows anyway.]
1330 logDebug("mswin_nhbell()\n");
1335 -- Display previous messages. Used by the ^P command.
1336 -- On the tty-port this scrolls WIN_MESSAGE back one line.
1338 int mswin_doprev_message()
1340 logDebug("mswin_doprev_message()\n");
1341 SendMessage(mswin_hwnd_from_winid(WIN_MESSAGE), WM_VSCROLL, MAKEWPARAM(SB_LINEUP, 0), (LPARAM)NULL);
1346 char yn_function(const char *ques, const char *choices, char default)
1347 -- Print a prompt made up of ques, choices and default.
1348 Read a single character response that is contained in
1349 choices or default. If choices is NULL, all possible
1350 inputs are accepted and returned. This overrides
1351 everything else. The choices are expected to be in
1352 lower case. Entering ESC always maps to 'q', or 'n',
1353 in that order, if present in choices, otherwise it maps
1354 to default. Entering any other quit character (SPACE,
1355 RETURN, NEWLINE) maps to default.
1356 -- If the choices string contains ESC, then anything after
1357 it is an acceptable response, but the ESC and whatever
1358 follows is not included in the prompt.
1359 -- If the choices string contains a '#' then accept a count.
1360 Place this value in the global "yn_number" and return '#'.
1361 -- This uses the top line in the tty window-port, other
1362 ports might use a popup.
1364 char mswin_yn_function(const char *question, const char *choices,
1369 char yn_esc_map='\033';
1370 char message[BUFSZ];
1373 logDebug("mswin_yn_function(%s, %s, %d)\n", question, choices, def);
1376 char *cb, choicebuf[QBUFSZ];
1377 Strcpy(choicebuf, choices);
1378 if ((cb = index(choicebuf, '\033')) != 0) {
1379 /* anything beyond <esc> is hidden */
1382 sprintf(message, "%s [%s] ", question, choicebuf);
1383 if (def) sprintf(eos(message), "(%c) ", def);
1384 /* escape maps to 'q' or 'n' or default, in that order */
1385 yn_esc_map = (index(choices, 'q') ? 'q' :
1386 (index(choices, 'n') ? 'n' : def));
1388 Strcpy(message, question);
1391 #if defined(WIN_CE_SMARTPHONE)
1394 ZeroMemory(buf, sizeof(buf));
1396 if( !index(choices, '\033') ) buf[0]='\033'; /* make sure ESC is always available */
1397 strncat( buf, choices, sizeof(buf)-2);
1398 NHSPhoneSetKeypadFromString( buf );
1400 /* sometimes choices are included in the message itself, e.g. "what? [abcd]" */
1402 p1 = strchr(question, '[');
1403 p2 = strrchr(question, ']');
1404 if( p1 && p2 && p1<p2 ) {
1405 buf[0]='\033'; /* make sure ESC is always available */
1406 strncat(buf, p1+1, p2-p1-1);
1407 NHSPhoneSetKeypadFromString( buf );
1408 } else if( strstr(question, "direction") ) {
1409 /* asking for direction here */
1410 NHSPhoneSetKeypadDirection( );
1413 NHSPhoneSetKeypadFromString( "\0330-9a-zA-Z" );
1417 #endif /* defined(WIN_CE_SMARTPHONE) */
1419 mswin_putstr(WIN_MESSAGE, ATR_BOLD, message);
1421 /* Only here if main window is not present */
1426 } else if (choices && !index(choices,ch)) {
1427 /* FYI: ch==-115 is for KP_ENTER */
1428 if (def && (ch==' ' || ch=='\r' || ch=='\n' || ch==-115)) {
1432 /* and try again... */
1439 /* display selection in the message window */
1443 mswin_putstr_ex(WIN_MESSAGE, ATR_BOLD, res_ch, 1);
1446 /* prevent "--more--" prompt from appearing when several
1447 questions being asked in the same loop (like selling
1448 something in the shop)
1449 It does not really clears the window - mhmsgwnd.c */
1450 mswin_clear_nhwindow(WIN_MESSAGE);
1452 #if defined(WIN_CE_SMARTPHONE)
1453 NHSPhoneSetKeypadDefault();
1459 getlin(const char *ques, char *input)
1460 -- Prints ques as a prompt and reads a single line of text,
1461 up to a newline. The string entered is returned without the
1462 newline. ESC is used to cancel, in which case the string
1463 "\033\000" is returned.
1464 -- getlin() must call flush_screen(1) before doing anything.
1465 -- This uses the top line in the tty window-port, other
1466 ports might use a popup.
1468 void mswin_getlin(const char *question, char *input)
1470 logDebug("mswin_getlin(%s, %p)\n", question, input);
1471 if( mswin_getlin_window(question, input, BUFSZ)==IDCANCEL ) {
1472 strcpy(input, "\033");
1477 int get_ext_cmd(void)
1478 -- Get an extended command in a window-port specific way.
1479 An index into extcmdlist[] is returned on a successful
1480 selection, -1 otherwise.
1482 int mswin_get_ext_cmd()
1485 logDebug("mswin_get_ext_cmd()\n");
1487 if(mswin_ext_cmd_window (&ret) == IDCANCEL)
1496 -- Initialize the number pad to the given state.
1498 void mswin_number_pad(int state)
1501 logDebug("mswin_number_pad(%d)\n", state);
1505 delay_output() -- Causes a visible delay of 50ms in the output.
1506 Conceptually, this is similar to wait_synch() followed
1507 by a nap(50ms), but allows asynchronous operation.
1509 void mswin_delay_output()
1511 logDebug("mswin_delay_output()\n");
1515 void mswin_change_color()
1517 logDebug("mswin_change_color()\n");
1520 char *mswin_get_color_string()
1522 logDebug("mswin_get_color_string()\n");
1527 start_screen() -- Only used on Unix tty ports, but must be declared for
1528 completeness. Sets up the tty to work in full-screen
1529 graphics mode. Look at win/tty/termcap.c for an
1530 example. If your window-port does not need this function
1531 just declare an empty function.
1533 void mswin_start_screen()
1536 logDebug("mswin_start_screen()\n");
1540 end_screen() -- Only used on Unix tty ports, but must be declared for
1541 completeness. The complement of start_screen().
1543 void mswin_end_screen()
1546 logDebug("mswin_end_screen()\n");
1551 -- The tombstone code. If you want the traditional code use
1552 genl_outrip for the value and check the #if in rip.c.
1554 void mswin_outrip(winid wid, int how)
1556 logDebug("mswin_outrip(%d)\n", wid, how);
1557 if ((wid >= 0) && (wid < MAXWINDOWS) ) {
1558 DestroyWindow(GetNHApp()->windowlist[wid].win);
1559 GetNHApp()->windowlist[wid].win = mswin_init_RIP_window();
1560 GetNHApp()->windowlist[wid].type = NHW_RIP;
1561 GetNHApp()->windowlist[wid].dead = 0;
1564 genl_outrip(wid, how);
1567 /* handle options updates here */
1568 void mswin_preference_update(const char *pref)
1572 if( _stricmp( pref, "font_menu")==0 ||
1573 _stricmp( pref, "font_size_menu")==0 ) {
1574 if( iflags.wc_fontsiz_menu<NHFONT_SIZE_MIN ||
1575 iflags.wc_fontsiz_menu>NHFONT_SIZE_MAX )
1576 iflags.wc_fontsiz_menu = NHFONT_DEFAULT_SIZE;
1578 hdc = GetDC(GetNHApp()->hMainWnd);
1579 mswin_get_font(NHW_MENU, ATR_NONE, hdc, TRUE);
1580 mswin_get_font(NHW_MENU, ATR_BOLD, hdc, TRUE);
1581 mswin_get_font(NHW_MENU, ATR_DIM, hdc, TRUE);
1582 mswin_get_font(NHW_MENU, ATR_ULINE, hdc, TRUE);
1583 mswin_get_font(NHW_MENU, ATR_BLINK, hdc, TRUE);
1584 mswin_get_font(NHW_MENU, ATR_INVERSE, hdc, TRUE);
1585 ReleaseDC(GetNHApp()->hMainWnd, hdc);
1587 mswin_layout_main_window(NULL);
1591 if( _stricmp( pref, "font_status")==0 ||
1592 _stricmp( pref, "font_size_status")==0 ) {
1594 if( iflags.wc_fontsiz_status<NHFONT_SIZE_MIN ||
1595 iflags.wc_fontsiz_status>NHFONT_SIZE_MAX )
1596 iflags.wc_fontsiz_status = NHFONT_DEFAULT_SIZE;
1598 hdc = GetDC(GetNHApp()->hMainWnd);
1599 mswin_get_font(NHW_STATUS, ATR_NONE, hdc, TRUE);
1600 mswin_get_font(NHW_STATUS, ATR_BOLD, hdc, TRUE);
1601 mswin_get_font(NHW_STATUS, ATR_DIM, hdc, TRUE);
1602 mswin_get_font(NHW_STATUS, ATR_ULINE, hdc, TRUE);
1603 mswin_get_font(NHW_STATUS, ATR_BLINK, hdc, TRUE);
1604 mswin_get_font(NHW_STATUS, ATR_INVERSE, hdc, TRUE);
1605 ReleaseDC(GetNHApp()->hMainWnd, hdc);
1607 mswin_layout_main_window(NULL);
1611 if( _stricmp( pref, "font_message")==0 ||
1612 _stricmp( pref, "font_size_message")==0 ) {
1614 if( iflags.wc_fontsiz_message<NHFONT_SIZE_MIN ||
1615 iflags.wc_fontsiz_message>NHFONT_SIZE_MAX )
1616 iflags.wc_fontsiz_message = NHFONT_DEFAULT_SIZE;
1618 hdc = GetDC(GetNHApp()->hMainWnd);
1619 mswin_get_font(NHW_MESSAGE, ATR_NONE, hdc, TRUE);
1620 mswin_get_font(NHW_MESSAGE, ATR_BOLD, hdc, TRUE);
1621 mswin_get_font(NHW_MESSAGE, ATR_DIM, hdc, TRUE);
1622 mswin_get_font(NHW_MESSAGE, ATR_ULINE, hdc, TRUE);
1623 mswin_get_font(NHW_MESSAGE, ATR_BLINK, hdc, TRUE);
1624 mswin_get_font(NHW_MESSAGE, ATR_INVERSE, hdc, TRUE);
1625 ReleaseDC(GetNHApp()->hMainWnd, hdc);
1627 mswin_layout_main_window(NULL);
1631 if( _stricmp( pref, "font_text")==0 ||
1632 _stricmp( pref, "font_size_text")==0 ) {
1634 if( iflags.wc_fontsiz_text<NHFONT_SIZE_MIN ||
1635 iflags.wc_fontsiz_text>NHFONT_SIZE_MAX )
1636 iflags.wc_fontsiz_text = NHFONT_DEFAULT_SIZE;
1638 hdc = GetDC(GetNHApp()->hMainWnd);
1639 mswin_get_font(NHW_TEXT, ATR_NONE, hdc, TRUE);
1640 mswin_get_font(NHW_TEXT, ATR_BOLD, hdc, TRUE);
1641 mswin_get_font(NHW_TEXT, ATR_DIM, hdc, TRUE);
1642 mswin_get_font(NHW_TEXT, ATR_ULINE, hdc, TRUE);
1643 mswin_get_font(NHW_TEXT, ATR_BLINK, hdc, TRUE);
1644 mswin_get_font(NHW_TEXT, ATR_INVERSE, hdc, TRUE);
1645 ReleaseDC(GetNHApp()->hMainWnd, hdc);
1647 mswin_layout_main_window(NULL);
1651 if( _stricmp( pref, "scroll_margin")==0 ) {
1652 mswin_cliparound(u.ux, u.uy);
1656 if( _stricmp( pref, "map_mode")==0 ) {
1657 mswin_select_map_mode( iflags.wc_map_mode );
1661 if( _stricmp( pref, "hilite_pet")==0 ) {
1662 InvalidateRect(mswin_hwnd_from_winid(WIN_MAP), NULL, TRUE);
1666 if( _stricmp( pref, "align_message")==0 ||
1667 _stricmp( pref, "align_status")==0 ) {
1668 mswin_layout_main_window(NULL);
1672 if( _stricmp( pref, "vary_msgcount")==0 ) {
1673 InvalidateRect(mswin_hwnd_from_winid(WIN_MESSAGE), NULL, TRUE);
1674 mswin_layout_main_window(NULL);
1678 if( _stricmp( pref, "fullscreen")==0 ) {
1679 mswin_set_fullscreen(iflags.wc2_fullscreen);
1683 if( _stricmp( pref, "softkeyboard")==0 ) {
1684 GetNHApp()->bUseSIP = iflags.wc2_softkeyboard;
1688 if( _stricmp( pref, "wraptext")==0 ) {
1689 GetNHApp()->bWrapText = iflags.wc2_wraptext;
1695 void mswin_main_loop()
1699 while( !mswin_have_input() &&
1700 GetMessage(&msg, NULL, 0, 0)!=0 ) {
1701 if (!TranslateAccelerator(msg.hwnd, GetNHApp()->hAccelTable, &msg)) {
1702 TranslateMessage(&msg);
1703 DispatchMessage(&msg);
1708 /* clean up and quit */
1709 void bail(const char *mesg)
1712 mswin_exit_nhwindows(mesg);
1713 terminate(EXIT_SUCCESS);
1717 BOOL initMapTiles(void)
1721 TCHAR wbuf[MAX_PATH];
1724 extern int total_tiles_used;
1726 /* no file - no tile */
1727 if( !(iflags.wc_tile_file && *iflags.wc_tile_file) )
1731 hBmp = SHLoadDIBitmap(NH_A2W(iflags.wc_tile_file, wbuf, MAX_PATH));
1733 raw_print("Cannot load tiles from the file. Reverting back to default.");
1737 /* calculate tile dimensions */
1738 GetObject(hBmp, sizeof(BITMAP), (LPVOID)&bm);
1739 if( bm.bmWidth%iflags.wc_tile_width ||
1740 bm.bmHeight%iflags.wc_tile_height ) {
1742 raw_print("Tiles bitmap does not match tile_width and tile_height options. Reverting back to default.");
1746 tl_num = (bm.bmWidth/iflags.wc_tile_width)*
1747 (bm.bmHeight/iflags.wc_tile_height);
1748 if( tl_num<total_tiles_used ) {
1750 raw_print("Number of tiles in the bitmap is less than required by the game. Reverting back to default.");
1754 /* set the tile information */
1755 if( GetNHApp()->bmpMapTiles!=GetNHApp()->bmpTiles ) {
1756 DeleteObject(GetNHApp()->bmpMapTiles);
1759 GetNHApp()->bmpMapTiles = hBmp;
1760 GetNHApp()->mapTile_X = iflags.wc_tile_width;
1761 GetNHApp()->mapTile_Y = iflags.wc_tile_height;
1762 GetNHApp()->mapTilesPerLine = bm.bmWidth / iflags.wc_tile_width;
1764 map_size.cx = GetNHApp()->mapTile_X * COLNO;
1765 map_size.cy = GetNHApp()->mapTile_Y * ROWNO;
1767 mswin_hwnd_from_winid(WIN_MAP),
1774 void mswin_popup_display(HWND hWnd, int* done_indicator)
1779 /* activate the menu window */
1780 GetNHApp()->hPopupWnd = hWnd;
1782 mswin_layout_main_window(hWnd);
1784 /* disable game windows */
1785 for( hChild=GetWindow(GetNHApp()->hMainWnd, GW_CHILD);
1787 hChild = GetWindow(hChild, GW_HWNDNEXT) ) {
1788 if( hChild!=hWnd ) EnableWindow(hChild, FALSE);
1790 #if defined(WIN_CE_SMARTPHONE)
1791 ShowWindow(GetNHApp()->hMenuBar, SW_HIDE);
1792 ShowWindow(SHFindMenuBar(hWnd), SW_SHOW);
1794 EnableWindow(GetNHApp()->hMenuBar, FALSE);
1797 /* bring menu window on top */
1798 SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
1800 /* go into message loop */
1801 if( done_indicator ) *done_indicator = 0;
1802 while( IsWindow(hWnd) &&
1803 (done_indicator==NULL || !*done_indicator) &&
1804 GetMessage(&msg, NULL, 0, 0)!=0 ) {
1805 if( !IsDialogMessage(hWnd, &msg) ) {
1806 if (!TranslateAccelerator(msg.hwnd, GetNHApp()->hAccelTable, &msg)) {
1807 TranslateMessage(&msg);
1808 DispatchMessage(&msg);
1814 void mswin_popup_destroy(HWND hWnd)
1818 /* enable game windows */
1819 for( hChild=GetWindow(GetNHApp()->hMainWnd, GW_CHILD);
1821 hChild = GetWindow(hChild, GW_HWNDNEXT) ) {
1822 if( hChild!= hWnd) {
1823 EnableWindow(hChild, TRUE);
1826 #if defined(WIN_CE_SMARTPHONE)
1827 ShowWindow(SHFindMenuBar(hWnd), SW_HIDE);
1828 ShowWindow(GetNHApp()->hMenuBar, SW_SHOW);
1830 EnableWindow(GetNHApp()->hMenuBar, TRUE);
1833 SetWindowPos(hWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_HIDEWINDOW);
1834 GetNHApp()->hPopupWnd = NULL;
1835 mswin_window_mark_dead( mswin_winid_from_handle(hWnd) );
1836 DestroyWindow(hWnd);
1838 mswin_layout_main_window(hWnd);
1840 SetFocus(GetNHApp()->hMainWnd );
1843 void mswin_set_fullscreen(BOOL is_fullscreen)
1845 #if defined(WIN_CE_POCKETPC) || defined(WIN_CE_SMARTPHONE)
1846 SetForegroundWindow(GetNHApp()->hMainWnd);
1847 if( is_fullscreen ) {
1848 SHFullScreen(GetNHApp()->hMainWnd, SHFS_HIDETASKBAR | SHFS_HIDESTARTICON);
1850 GetNHApp()->hMainWnd,
1853 GetSystemMetrics(SM_CXSCREEN),
1854 GetSystemMetrics(SM_CYSCREEN),
1859 SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, 0);
1860 SHFullScreen(GetNHApp()->hMainWnd, SHFS_SHOWTASKBAR | SHFS_SHOWSTARTICON);
1862 GetNHApp()->hMainWnd,
1870 GetNHApp()->bFullScreen = is_fullscreen;
1872 GetNHApp()->bFullScreen = FALSE;
1876 #if defined(WIN_CE_SMARTPHONE)
1877 void NHSPhoneDialogSetup(HWND hDlg, BOOL is_edit, BOOL is_fullscreen)
1883 // Create our MenuBar
1884 ZeroMemory(&mbi, sizeof(SHMENUBARINFO));
1885 mbi.cbSize = sizeof(mbi);
1886 mbi.hwndParent = hDlg;
1887 mbi.nToolBarId = IDC_SPHONE_DIALOGBAR;
1888 mbi.hInstRes = GetNHApp()->hApp;
1889 if(!SHCreateMenuBar(&mbi)) {
1890 error("cannot create dialog menu");
1894 SHINITDLGINFO shidi;
1896 shidi.dwMask = SHIDIM_FLAGS;
1897 shidi.dwFlags = SHIDIF_SIZEDLGFULLSCREEN;
1899 SHInitDialog(&shidi);
1901 GetWindowRect(GetNHApp()->hMainWnd, &main_wnd_rect);
1906 main_wnd_rect.right - main_wnd_rect.left,
1907 main_wnd_rect.bottom - main_wnd_rect.top,
1912 /* hide OK and CANCEL buttons */
1913 hOK = GetDlgItem(hDlg, IDOK);
1914 hCancel = GetDlgItem(hDlg, IDCANCEL);
1916 if( IsWindow(hCancel) ) ShowWindow(hCancel, SW_HIDE);
1917 if( IsWindow(hOK) ) {
1918 GetWindowRect(hOK, &rtOK);
1919 GetWindowRect(hDlg, &rtDlg);
1921 rtDlg.bottom -= rtOK.bottom-rtOK.top;
1922 ShowWindow(hOK, SW_HIDE);
1923 SetWindowPos( hDlg, HWND_TOP,
1925 rtDlg.right-rtDlg.left, rtDlg.bottom-rtDlg.top,
1926 SWP_NOMOVE | SWP_NOREPOSITION | SWP_NOZORDER );
1929 /* override "Back" button for edit box dialogs */
1931 SendMessage(mbi.hwndMB, SHCMBM_OVERRIDEKEY, VK_TBACK, MAKELPARAM(SHMBOF_NODEFAULT | SHMBOF_NOTIFY, SHMBOF_NODEFAULT | SHMBOF_NOTIFY));
1933 #endif /* defined(WIN_CE_SMARTPHONE) */
1935 void mswin_read_reg(void)
1939 void mswin_destroy_reg(void)
1943 void mswin_write_reg(void)
1951 logDebug(const char *fmt, ...)
1953 FILE *dfp = fopen("nhtrace.log", "a");
1958 va_start(args, fmt);
1959 vfprintf(dfp, fmt, args);