OSDN Git Service

Initial Import
[nethackexpress/trunk.git] / sys / wince / mswproc.c
1 /* Copyright (C) 2001 by Alex Kompel <shurikk@pacbell.net> */
2 /* NetHack may be freely redistributed.  See license for details. */
3
4 /*
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. 
7 */
8
9 #include "hack.h"
10 #include "dlb.h"
11 #include "winMS.h"
12 #include "mhmap.h"
13 #include "mhstatus.h"
14 #include "mhtext.h"
15 #include "mhmsgwnd.h"
16 #include "mhmenu.h"
17 #include "mhmsg.h"
18 #include "mhcmd.h"
19 #include "mhinput.h"
20 #include "mhaskyn.h"
21 #include "mhdlg.h"
22 #include "mhrip.h"
23 #include "mhmain.h"
24 #include "mhfont.h"
25 #include "mhcolor.h"
26
27 #define LLEN 128
28
29 #ifdef _DEBUG
30 extern void logDebug(const char *fmt, ...);
31 #else
32 void logDebug(const char *fmt, ...) { }
33 #endif
34
35 static void mswin_main_loop();
36 static BOOL initMapTiles(void);
37 static void prompt_for_player_selection(void);
38
39 /* Interface definition, for windows.c */
40 struct window_procs mswin_procs = {
41     "MSWIN",
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,
49     mswin_init_nhwindows,
50     mswin_player_selection,
51     mswin_askname,
52     mswin_get_nh_event,
53     mswin_exit_nhwindows,
54     mswin_suspend_nhwindows,
55     mswin_resume_nhwindows,
56     mswin_create_nhwindow,
57     mswin_clear_nhwindow,
58     mswin_display_nhwindow,
59     mswin_destroy_nhwindow,
60     mswin_curs,
61     mswin_putstr,
62     mswin_display_file,
63     mswin_start_menu,
64     mswin_add_menu,
65     mswin_end_menu,
66     mswin_select_menu,
67     genl_message_menu,          /* no need for X-specific handling */
68     mswin_update_inventory,
69     mswin_mark_synch,
70     mswin_wait_synch,
71 #ifdef CLIPPING
72     mswin_cliparound,
73 #endif
74 #ifdef POSITIONBAR
75     donull,
76 #endif
77     mswin_print_glyph,
78     mswin_raw_print,
79     mswin_raw_print_bold,
80     mswin_nhgetch,
81     mswin_nh_poskey,
82     mswin_nhbell,
83     mswin_doprev_message,
84     mswin_yn_function,
85     mswin_getlin,
86     mswin_get_ext_cmd,
87     mswin_number_pad,
88     mswin_delay_output,
89 #ifdef CHANGE_COLOR     /* only a Mac option currently */
90         mswin,
91         mswin_change_background,
92 #endif
93     /* other defs that really should go away (they're tty specific) */
94     mswin_start_screen,
95     mswin_end_screen,
96     mswin_outrip,
97     mswin_preference_update,
98 };
99
100 /*  
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
104                    not display them.
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
113 */
114 void mswin_init_nhwindows(int* argc, char** argv)
115 {
116         HWND hWnd;
117         logDebug("mswin_init_nhwindows()\n");
118
119 #ifdef _DEBUG
120         {
121                 /* truncate trace file */
122                 FILE *dfp = fopen("nhtrace.log", "w");
123                 fclose(dfp);
124         }
125 #endif
126
127         /* intialize input subsystem */
128     mswin_nh_input_init();
129
130         /* read registry settings */
131     mswin_read_reg();
132
133         /* set it to WIN_ERR so we can detect attempts to
134            use this ID before it is inialized */
135         WIN_MAP = WIN_ERR;
136
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;
141
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;
145
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;
149
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;
153
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;
159
160         if( iflags.wc_vary_msgcount==0 ) iflags.wc_vary_msgcount = 3;
161
162         /* force tabs in menus */
163         iflags.menu_tab_sep = 1;
164
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
168          */
169         flags.toptenwin = 1;
170         set_option_mod_status("toptenwin", SET_IN_FILE);
171
172         /* initialize map tiles bitmap */
173         initMapTiles();
174
175         /* set tile-related options to readonly */
176         set_wc_option_mod_status(
177            WC_TILE_WIDTH|WC_TILE_HEIGHT|WC_TILE_FILE,
178            DISP_IN_GAME);
179
180         /* init color table */
181         mswin_init_color_table();
182
183         /* set font-related options to change in the game */
184         set_wc_option_mod_status(
185                 WC_HILITE_PET |
186                 WC_ALIGN_MESSAGE | 
187                 WC_ALIGN_STATUS |
188                 WC_SCROLL_MARGIN | 
189                 WC_MAP_MODE |
190                 WC_FONT_MESSAGE |
191                 WC_FONT_STATUS |
192                 WC_FONT_MENU |
193                 WC_FONT_TEXT |
194                 WC_FONTSIZ_MESSAGE | 
195                 WC_FONTSIZ_STATUS | 
196                 WC_FONTSIZ_MENU | 
197                 WC_FONTSIZ_TEXT |
198                 WC_VARY_MSGCOUNT,
199                 SET_IN_GAME 
200         );
201
202         /* WC2 options */
203         set_wc2_option_mod_status(
204                 WC2_FULLSCREEN|
205                 WC2_SOFTKEYBOARD,
206                 SET_IN_FILE
207         );
208         GetNHApp()->bFullScreen = iflags.wc2_fullscreen;
209         GetNHApp()->bUseSIP = iflags.wc2_softkeyboard;
210         
211         set_wc2_option_mod_status(
212                 WC2_WRAPTEXT,
213                 SET_IN_GAME
214         );
215         GetNHApp()->bWrapText = iflags.wc2_wraptext;
216
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);
221         UpdateWindow(hWnd);
222         GetNHApp()->hMainWnd = hWnd;
223
224         /* set Full screen if requested */
225         mswin_set_fullscreen(GetNHApp()->bFullScreen);
226
227         /* let nethack code know that the window subsystem is ready */
228         iflags.window_inited = TRUE;
229 }
230
231
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].
235 */
236 void mswin_player_selection(void)
237 {
238         logDebug("mswin_player_selection()\n");
239
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();
244 #else
245         if (iflags.wc_player_selection == VIA_DIALOG) {
246                 int nRole;
247
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();
256                         }
257                 }
258
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);
265                         }
266                 }
267
268                 if (flags.initgend < 0 || !validgend(flags.initrole, flags.initrace,
269                                                 flags.initgend)) {
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);
275                         }
276                 }
277
278                 if (flags.initalign < 0 || !validalign(flags.initrole, flags.initrace,
279                                                                 flags.initalign)) {
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);
285                         }
286                 }
287             } else {
288                 /* select a role */
289                 if( mswin_player_selection_window( &nRole ) == IDCANCEL ) {
290                         bail(0);
291                 }
292             }
293         } else { /* iflags.wc_player_selection == VIA_PROMPTS */
294             prompt_for_player_selection();
295         }
296 #endif /* defined(WIN_CE_SMARTPHONE) */
297 }
298
299 void prompt_for_player_selection(void)
300 {
301         int i, k, n;
302         char pick4u = 'n', thisch, lastch = 0;
303         char pbuf[QBUFSZ], plbuf[QBUFSZ];
304         winid win;
305         anything any;
306         menu_item *selected = 0;
307         int box_result;
308         TCHAR wbuf[BUFSZ];
309
310         logDebug("prompt_for_player_selection()\n");
311
312         /* prevent an unnecessary prompt */
313         rigid_role_checks();
314
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)) {
319             /* int echoline; */
320             char *prompt = build_plselection_prompt(pbuf, QBUFSZ, flags.initrole,
321                                 flags.initrace, flags.initgend, flags.initalign);
322
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 
330 #else                                   
331                                         MB_YESNOCANCEL | MB_DEFBUTTON1 
332 #endif
333                                         );
334
335         pick4u = (box_result == IDYES) ? 'y' : (box_result == IDNO) ? 'n' : '\033';
336             /* tty_putstr(BASE_WINDOW, 0, prompt); */
337             do {
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, ""); */
345             } else
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.
350                  */
351                 /* tty_clear_nhwindow(BASE_WINDOW) */ ;
352             
353             if (pick4u != 'y' && pick4u != 'n') {
354 give_up:        /* Quit */
355                 if (selected) free((genericptr_t) selected);
356                 bail((char *)0);
357                 /*NOTREACHED*/
358                 return;
359             }
360         }
361
362         (void)  root_plselection_prompt(plbuf, QBUFSZ - 1,
363                         flags.initrole, flags.initrace, flags.initgend, flags.initalign);
364
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();
378                 }
379             } else {
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);
384                 start_menu(win);
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,
388                                                         flags.initalign)) {
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);
395                                 else
396                                         Strcpy(rolenamebuf, roles[i].name.m);
397                         } else {
398                                 if (roles[i].name.f) {
399                                         Strcpy(rolenamebuf, roles[i].name.m);
400                                         Strcat(rolenamebuf, "/");
401                                         Strcat(rolenamebuf, roles[i].name.f);
402                                 } else 
403                                         Strcpy(rolenamebuf, roles[i].name.m);
404                         }       
405                         add_menu(win, NO_GLYPH, &any, thisch,
406                             0, ATR_NONE, an(rolenamebuf), MENU_UNSELECTED);
407                         lastch = thisch;
408                     }
409                 }
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);
420                 end_menu(win, pbuf);
421                 n = select_menu(win, PICK_ONE, &selected);
422                 destroy_nhwindow(win);
423
424                 /* Process the choice */
425                 if (n != 1 || selected[0].item.a_int == any.a_int)
426                     goto give_up;               /* Selected quit */
427
428                 flags.initrole = selected[0].item.a_int - 1;
429                 free((genericptr_t) selected),  selected = 0;
430             }
431             (void)  root_plselection_prompt(plbuf, QBUFSZ - 1,
432                         flags.initrole, flags.initrace, flags.initgend, flags.initalign);
433         }
434         
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);
446                 }
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,
453                                                         flags.initalign)) {
454                         n++;
455                         k = i;
456                     }
457                 }
458                 if (n == 0) {
459                     for (i = 0; races[i].noun; i++) {
460                         if (validrace(flags.initrole, i)) {
461                             n++;
462                             k = i;
463                         }
464                     }
465                 }
466
467                 /* Permit the user to pick, if there is more than one */
468                 if (n > 1) {
469                     /* tty_clear_nhwindow(BASE_WINDOW); */
470                     /* tty_putstr(BASE_WINDOW, 0, "Choosing Race"); */
471                     win = create_nhwindow(NHW_MENU);
472                     start_menu(win);
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,
476                                                         flags.initalign)) {
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);
480                         }
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);
491                     end_menu(win, pbuf);
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 */
496
497                     k = selected[0].item.a_int - 1;
498                     free((genericptr_t) selected),      selected = 0;
499                 }
500                 flags.initrace = k;
501             }
502             (void)  root_plselection_prompt(plbuf, QBUFSZ - 1,
503                         flags.initrole, flags.initrace, flags.initgend, flags.initalign);
504         }
505
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,
510                                                 flags.initgend)) {
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);
518                 }
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,
525                                                         flags.initalign)) {
526                         n++;
527                         k = i;
528                     }
529                 }
530                 if (n == 0) {
531                     for (i = 0; i < ROLE_GENDERS; i++) {
532                         if (validgend(flags.initrole, flags.initrace, i)) {
533                             n++;
534                             k = i;
535                         }
536                     }
537                 }
538
539                 /* Permit the user to pick, if there is more than one */
540                 if (n > 1) {
541                     /* tty_clear_nhwindow(BASE_WINDOW); */
542                     /* tty_putstr(BASE_WINDOW, 0, "Choosing Gender"); */
543                     win = create_nhwindow(NHW_MENU);
544                     start_menu(win);
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,
548                                                             flags.initalign)) {
549                             any.a_int = i+1;
550                             add_menu(win, NO_GLYPH, &any, genders[i].adj[0],
551                                 0, ATR_NONE, genders[i].adj, MENU_UNSELECTED);
552                         }
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);
563                     end_menu(win, pbuf);
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 */
568
569                     k = selected[0].item.a_int - 1;
570                     free((genericptr_t) selected),      selected = 0;
571                 }
572                 flags.initgend = k;
573             }
574             (void)  root_plselection_prompt(plbuf, QBUFSZ - 1,
575                         flags.initrole, flags.initrace, flags.initgend, flags.initalign);
576         }
577
578         /* Select an alignment, if necessary */
579         /* force compatibility with role/race/gender */
580         if (flags.initalign < 0 || !validalign(flags.initrole, flags.initrace,
581                                                         flags.initalign)) {
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);
589                 }
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,
596                                                         i)) {
597                         n++;
598                         k = i;
599                     }
600                 }
601                 if (n == 0) {
602                     for (i = 0; i < ROLE_ALIGNS; i++) {
603                         if (validalign(flags.initrole, flags.initrace, i)) {
604                             n++;
605                             k = i;
606                         }
607                     }
608                 }
609
610                 /* Permit the user to pick, if there is more than one */
611                 if (n > 1) {
612                     /* tty_clear_nhwindow(BASE_WINDOW); */
613                     /* tty_putstr(BASE_WINDOW, 0, "Choosing Alignment"); */
614                     win = create_nhwindow(NHW_MENU);
615                     start_menu(win);
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)) {
620                             any.a_int = i+1;
621                             add_menu(win, NO_GLYPH, &any, aligns[i].adj[0],
622                                  0, ATR_NONE, aligns[i].adj, MENU_UNSELECTED);
623                         }
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);
634                     end_menu(win, pbuf);
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 */
639
640                     k = selected[0].item.a_int - 1;
641                     free((genericptr_t) selected),      selected = 0;
642                 }
643                 flags.initalign = k;
644             }
645         }
646         /* Success! */
647         /* tty_display_nhwindow(BASE_WINDOW, FALSE); */
648 }
649
650 /* Ask the user for a player name. */
651 void mswin_askname(void)
652 {
653         logDebug("mswin_askname()\n");
654
655         if( mswin_getlin_window("who are you?", plname, PL_NSIZ)==IDCANCEL ) {
656                 bail("bye-bye");
657                 /* not reached */
658         }
659 }
660
661
662 /* Does window event processing (e.g. exposure events).
663    A noop for the tty and X window-ports.
664 */
665 void mswin_get_nh_event(void)
666 {
667         logDebug("mswin_get_nh_event()\n");
668         return;
669 }
670
671 /* Exits the window system.  This should dismiss all windows,
672    except the "window" used for raw_print().  str is printed if possible.
673 */
674 void mswin_exit_nhwindows(const char *str)
675 {
676         logDebug("mswin_exit_nhwindows(%s)\n", str);
677
678     /* Write Window settings to the registry */
679     mswin_write_reg();
680
681         // Don't do any of this (?) - exit_nhwindows does not terminate 
682         // the application
683         // DestroyWindow(GetNHApp()->hMainWnd);
684         // terminate(EXIT_SUCCESS);
685 }
686
687 /* Prepare the window to be suspended. */
688 void mswin_suspend_nhwindows(const char *str)
689 {
690         logDebug("mswin_suspend_nhwindows(%s)\n", str);
691         return;
692 }
693
694
695 /* Restore the windows after being suspended. */
696 void mswin_resume_nhwindows()
697 {
698         logDebug("mswin_resume_nhwindows()\n");
699         return;
700 }
701
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)
708 */
709 winid 
710 mswin_create_nhwindow(int type)
711 {
712         winid i = 0;
713         MSNHMsgAddWnd data;
714
715         logDebug("mswin_create_nhwindow(%d)\n", type);
716
717         /* Return the next available winid
718          */
719
720         for (i=1; i<MAXWINDOWS; i++)
721           if (GetNHApp()->windowlist[i].win == NULL &&
722                   !GetNHApp()->windowlist[i].dead)
723                   break;
724         if (i == MAXWINDOWS)
725           panic ("ERROR:  No windows available...\n");
726
727     switch (type) {
728     case NHW_MAP:
729         {
730                 GetNHApp()->windowlist[i].win = mswin_init_map_window();
731                 GetNHApp()->windowlist[i].type = type;
732                 GetNHApp()->windowlist[i].dead = 0;
733                 break;
734         }
735     case NHW_MESSAGE:
736         {
737                 GetNHApp()->windowlist[i].win = mswin_init_message_window();
738                 GetNHApp()->windowlist[i].type = type;
739                 GetNHApp()->windowlist[i].dead = 0;
740                 break;
741         }
742     case NHW_STATUS:
743         {
744                 GetNHApp()->windowlist[i].win = mswin_init_status_window();
745                 GetNHApp()->windowlist[i].type = type;
746                 GetNHApp()->windowlist[i].dead = 0;
747                 break;
748         }    
749     case NHW_MENU:
750         {
751                 GetNHApp()->windowlist[i].win = NULL; //will create later
752                 GetNHApp()->windowlist[i].type = type;
753                 GetNHApp()->windowlist[i].dead = 1;
754                 break;
755         } 
756     case NHW_TEXT:
757         {
758                 GetNHApp()->windowlist[i].win = mswin_init_text_window();
759                 GetNHApp()->windowlist[i].type = type;
760                 GetNHApp()->windowlist[i].dead = 0;
761                 break;
762         }
763         }
764
765         ZeroMemory(&data, sizeof(data) );
766         data.wid = i;
767         SendMessage( GetNHApp()->hMainWnd, 
768                          WM_MSNH_COMMAND, (WPARAM)MSNH_MSG_ADDWND, (LPARAM)&data );
769         return i;
770 }
771
772 /* Clear the given window, when asked to. */
773 void mswin_clear_nhwindow(winid wid)
774 {
775         logDebug("mswin_clear_nhwindow(%d)\n", wid);
776
777     if ((wid >= 0) && 
778         (wid < MAXWINDOWS) &&
779         (GetNHApp()->windowlist[wid].win != NULL))
780     {
781 #ifdef REINCARNATION
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);
785                         else 
786                                 mswin_map_mode(mswin_hwnd_from_winid(WIN_MAP), iflags.wc_map_mode);
787                 }
788 #endif
789
790          SendMessage( 
791                          GetNHApp()->windowlist[wid].win, 
792                          WM_MSNH_COMMAND, (WPARAM)MSNH_MSG_CLEAR_WINDOW, (LPARAM)NULL );
793     }
794 }
795
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.
804 */
805 void mswin_display_nhwindow(winid wid, BOOLEAN_P block)
806 {
807         logDebug("mswin_display_nhwindow(%d, %d)\n", wid, block);
808         if (GetNHApp()->windowlist[wid].win != NULL)
809         {
810                 if (GetNHApp()->windowlist[wid].type == NHW_MENU) {
811                         MENU_ITEM_P* p;
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);
817                 } else {
818                         if( !block ) {
819                                 UpdateWindow(GetNHApp()->windowlist[wid].win);
820                         } else {
821                                 if ( GetNHApp()->windowlist[wid].type == NHW_MAP ) {
822                                         (void) mswin_nhgetch();
823                                 }
824                         }
825                 }
826                 SetFocus(GetNHApp()->hMainWnd);
827         }
828 }
829
830
831 HWND mswin_hwnd_from_winid(winid wid)
832 {
833         if( wid>=0 && wid<MAXWINDOWS) {
834                 return GetNHApp()->windowlist[wid].win;
835         } else {
836                 return NULL;
837         }
838 }
839
840 winid mswin_winid_from_handle(HWND hWnd)
841 {
842         winid i = 0;
843
844         for (i=1; i<MAXWINDOWS; i++)
845           if (GetNHApp()->windowlist[i].win == hWnd)
846                   return i;
847         return -1;
848 }
849
850 winid mswin_winid_from_type(int type)
851 {
852         winid i = 0;
853
854         for (i=1; i<MAXWINDOWS; i++)
855           if (GetNHApp()->windowlist[i].type == type)
856                   return i;
857         return -1;
858 }
859
860 void mswin_window_mark_dead(winid wid)
861 {
862         if( wid>=0 && wid<MAXWINDOWS) {
863                 GetNHApp()->windowlist[wid].win = NULL;
864                 GetNHApp()->windowlist[wid].dead = 1;
865         }
866 }
867
868 /* Destroy will dismiss the window if the window has not 
869  * already been dismissed.
870 */
871 void mswin_destroy_nhwindow(winid wid)
872 {
873         logDebug("mswin_destroy_nhwindow(%d)\n", wid);
874
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 */
879                 return;
880     }
881
882     if (wid != -1) {
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;
889         }
890 }
891
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
895  the size of window.
896 */
897 void mswin_curs(winid wid, int x, int y)
898 {
899         logDebug("mswin_curs(%d, %d, %d)\n", wid, x, y);
900
901     if ((wid >= 0) && 
902         (wid < MAXWINDOWS) &&
903         (GetNHApp()->windowlist[wid].win != NULL))
904     {
905                  MSNHMsgCursor data;
906                  data.x = x;
907                  data.y = y;
908                  SendMessage( 
909                          GetNHApp()->windowlist[wid].win, 
910                          WM_MSNH_COMMAND, (WPARAM)MSNH_MSG_CURSOR, (LPARAM)&data );
911     }
912 }
913
914 /*
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.
919 Attributes
920                    can be one of
921                         ATR_NONE (or 0)
922                         ATR_ULINE
923                         ATR_BOLD
924                         ATR_BLINK
925                         ATR_INVERSE
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
931                    to end-of-line.
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.
936 */
937 void mswin_putstr(winid wid, int attr, const char *text)
938 {
939         logDebug("mswin_putstr(%d, %d, %s)\n", wid, attr, text);
940
941         mswin_putstr_ex(wid, attr, text, 0);
942 }
943
944 void mswin_putstr_ex(winid wid, int attr, const char *text, boolean app)
945 {
946         if( (wid >= 0) && 
947         (wid < MAXWINDOWS) )
948         {
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;
953                 }
954
955                 if (GetNHApp()->windowlist[wid].win != NULL)
956                 {
957                          MSNHMsgPutstr data;
958                          ZeroMemory(&data, sizeof(data));
959                          data.attr = attr;
960                          data.text = text;
961                          data.append = app;
962                          SendMessage( 
963                                  GetNHApp()->windowlist[wid].win, 
964                                  WM_MSNH_COMMAND, (WPARAM)MSNH_MSG_PUTSTR, (LPARAM)&data );
965                 }
966         }
967 }
968
969 /* Display the file named str.  Complain about missing files
970                    iff complain is TRUE.
971 */
972 void mswin_display_file(const char *filename,BOOLEAN_P must_exist)
973 {
974         dlb *f;
975         TCHAR wbuf[BUFSZ];
976
977         logDebug("mswin_display_file(%s, %d)\n", filename, must_exist);
978
979         f = dlb_fopen(filename, RDTMODE);
980         if (!f) {
981                 if (must_exist) {
982                         TCHAR message[90];
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 );
985                 } 
986         } else {
987                 winid text;
988                 char line[LLEN];
989
990                 text = mswin_create_nhwindow(NHW_TEXT);
991
992                 while (dlb_fgets(line, LLEN, f)) {
993                          size_t len;
994                          len = strlen(line);
995                          if( line[len-1]=='\n' ) line[len-1]='\x0';
996                                 mswin_putstr(text, ATR_NONE, line);
997                 }
998                 (void) dlb_fclose(f);
999
1000                 mswin_display_nhwindow(text, 1);
1001                 mswin_destroy_nhwindow(text);
1002         }
1003 }
1004
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
1008    be used for menus.
1009 */
1010 void mswin_start_menu(winid wid)
1011 {
1012         logDebug("mswin_start_menu(%d)\n", wid);
1013         if( (wid >= 0) && 
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;
1019                 }
1020
1021                 if(GetNHApp()->windowlist[wid].win != NULL)     {
1022                         SendMessage( 
1023                                  GetNHApp()->windowlist[wid].win, 
1024                                  WM_MSNH_COMMAND, (WPARAM)MSNH_MSG_STARTMENU, (LPARAM)NULL
1025                         );
1026                 }
1027         }
1028 }
1029
1030 /*
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.
1060 */
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)
1064 {
1065         logDebug("mswin_add_menu(%d, %d, %p, %c, %c, %d, %s, %d)\n",
1066                      wid, glyph, identifier, (char)accelerator, (char)group_accel,
1067                          attr, str, presel);
1068         if ((wid >= 0) && 
1069                 (wid < MAXWINDOWS) &&
1070                 (GetNHApp()->windowlist[wid].win != NULL))
1071         {
1072                 MSNHMsgAddMenu data;
1073                 ZeroMemory(&data, sizeof(data));
1074                 data.glyph = glyph;
1075                 data.identifier = identifier;
1076                 data.accelerator = accelerator;
1077                 data.group_accel = group_accel;
1078                 data.attr = attr;
1079                 data.str = str;
1080                 data.presel = presel;
1081
1082                 SendMessage( 
1083                          GetNHApp()->windowlist[wid].win, 
1084                          WM_MSNH_COMMAND, (WPARAM)MSNH_MSG_ADDMENU, (LPARAM)&data
1085                 );
1086         }
1087 }
1088
1089 /*
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
1094                    be printed.
1095                 ** This probably shouldn't flush the window any more (if
1096                 ** it ever did).  That should be select_menu's job.  -dean
1097 */
1098 void mswin_end_menu(winid wid, const char *prompt)
1099 {
1100         logDebug("mswin_end_menu(%d, %s)\n", wid, prompt);
1101         if ((wid >= 0) && 
1102                 (wid < MAXWINDOWS) &&
1103                 (GetNHApp()->windowlist[wid].win != NULL))
1104         {
1105                 MSNHMsgEndMenu data;
1106                 ZeroMemory(&data, sizeof(data));
1107                 data.text = prompt;
1108
1109                 SendMessage( 
1110                          GetNHApp()->windowlist[wid].win, 
1111                          WM_MSNH_COMMAND, (WPARAM)MSNH_MSG_ENDMENU, (LPARAM)&data
1112                 );
1113         }
1114 }
1115
1116 /*
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.
1140 */
1141 int mswin_select_menu(winid wid, int how, MENU_ITEM_P **selected)
1142 {
1143         int nReturned = -1;
1144
1145         logDebug("mswin_select_menu(%d, %d)\n", wid, how);
1146
1147         if ((wid >= 0) && 
1148                 (wid < MAXWINDOWS) &&
1149                 (GetNHApp()->windowlist[wid].win != NULL))
1150         {
1151                 nReturned = mswin_menu_window_select_menu(GetNHApp()->windowlist[wid].win, how, selected);
1152         }
1153     return nReturned;
1154 }
1155
1156 /*
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.
1160 */
1161 void mswin_update_inventory()
1162 {
1163         logDebug("mswin_update_inventory()\n");
1164 }
1165
1166 /*
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
1169                    for the moment
1170 */
1171 void mswin_mark_synch()
1172 {
1173         logDebug("mswin_mark_synch()\n");
1174 }
1175
1176 /*
1177 wait_synch()    -- Wait until all pending output is complete (*flush*() for
1178                    streams goes here).
1179                 -- May also deal with exposure events etc. so that the
1180                    display is OK when return from wait_synch().
1181 */
1182 void mswin_wait_synch()
1183 {
1184         logDebug("mswin_wait_synch()\n");
1185 }
1186
1187 /*
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.
1191 */
1192 void mswin_cliparound(int x, int y)
1193 {
1194         winid wid = WIN_MAP;
1195
1196         logDebug("mswin_cliparound(%d, %d)\n", x, y);
1197
1198     if ((wid >= 0) && 
1199         (wid < MAXWINDOWS) &&
1200         (GetNHApp()->windowlist[wid].win != NULL))
1201     {
1202                  MSNHMsgClipAround data;
1203                  data.x = x;
1204                  data.y = y;
1205          SendMessage( 
1206                          GetNHApp()->windowlist[wid].win, 
1207                          WM_MSNH_COMMAND, (WPARAM)MSNH_MSG_CLIPAROUND, (LPARAM)&data );
1208     }
1209 }
1210
1211 /*
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).
1217 */
1218 void mswin_print_glyph(winid wid,XCHAR_P x,XCHAR_P y,int glyph)
1219 {
1220     logDebug("mswin_print_glyph(%d, %d, %d, %d)\n", wid, x, y, glyph);
1221
1222     if ((wid >= 0) && 
1223         (wid < MAXWINDOWS) &&
1224         (GetNHApp()->windowlist[wid].win != NULL))
1225     {
1226                 MSNHMsgPrintGlyph data;
1227
1228                 ZeroMemory(&data, sizeof(data) );
1229                 data.x = x;
1230                 data.y = y;
1231                 data.glyph = glyph;
1232                 SendMessage( GetNHApp()->windowlist[wid].win, 
1233                          WM_MSNH_COMMAND, (WPARAM)MSNH_MSG_PRINT_GLYPH, (LPARAM)&data );
1234         }
1235 }
1236
1237 /*
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").
1245 */
1246 void mswin_raw_print(const char *str)
1247 {
1248         TCHAR wbuf[255];
1249     logDebug("mswin_raw_print(%s)\n", str);
1250         if( str && *str)
1251                 MessageBox(GetNHApp()->hMainWnd, NH_A2W(str, wbuf, sizeof(wbuf)), TEXT("NetHack"), MB_OK );
1252 }
1253
1254 /*
1255 raw_print_bold(str)
1256                 -- Like raw_print(), but prints in bold/standout (if
1257 possible).
1258 */
1259 void mswin_raw_print_bold(const char *str)
1260 {
1261         TCHAR wbuf[255];
1262     logDebug("mswin_raw_print_bold(%s)\n", str);
1263         if( str && *str)
1264                 MessageBox(GetNHApp()->hMainWnd, NH_A2W(str, wbuf, sizeof(wbuf)), TEXT("NetHack"), MB_OK );
1265 }
1266
1267 /*
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.
1272 */
1273 int mswin_nhgetch()
1274 {
1275         PMSNHEvent event;
1276     int key = 0;
1277
1278         logDebug("mswin_nhgetch()\n");
1279         
1280
1281         while( (event = mswin_input_pop()) == NULL ||
1282                    event->type != NHEVENT_CHAR ) 
1283                 mswin_main_loop();
1284
1285         key = event->kbd.ch;
1286     return (key);
1287 }
1288
1289 /*
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.
1295                    mod may be one of
1296
1297                         CLICK_1         -- mouse click type 1 
1298                         CLICK_2         -- mouse click type 2 
1299
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.
1303 */
1304 int mswin_nh_poskey(int *x, int *y, int *mod)
1305 {
1306         PMSNHEvent event;
1307         int key;
1308
1309         logDebug("mswin_nh_poskey()\n");
1310
1311         while( (event = mswin_input_pop())==NULL ) mswin_main_loop();
1312
1313         if( event->type==NHEVENT_MOUSE ) {
1314                 *mod = event->ms.mod;
1315                 *x = event->ms.x;
1316                 *y = event->ms.y;
1317                 key = 0;
1318         } else {
1319                 key = event->kbd.ch;
1320         }
1321         return (key);
1322 }
1323
1324 /*
1325 nhbell()        -- Beep at user.  [This will exist at least until sounds are
1326                    redone, since sounds aren't attributable to windows anyway.]
1327 */
1328 void mswin_nhbell()
1329 {
1330         logDebug("mswin_nhbell()\n");
1331 }
1332
1333 /*
1334 doprev_message()
1335                 -- Display previous messages.  Used by the ^P command.
1336                 -- On the tty-port this scrolls WIN_MESSAGE back one line.
1337 */
1338 int mswin_doprev_message()
1339 {
1340     logDebug("mswin_doprev_message()\n");
1341         SendMessage(mswin_hwnd_from_winid(WIN_MESSAGE), WM_VSCROLL, MAKEWPARAM(SB_LINEUP, 0), (LPARAM)NULL); 
1342     return 0;
1343 }
1344
1345 /*
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.
1363 */
1364 char mswin_yn_function(const char *question, const char *choices,
1365                 CHAR_P def)
1366 {
1367     int result=-1;
1368     char ch;
1369     char yn_esc_map='\033';
1370     char message[BUFSZ];
1371         char res_ch[2];
1372
1373         logDebug("mswin_yn_function(%s, %s, %d)\n", question, choices, def);
1374
1375     if (choices) {
1376                 char *cb, choicebuf[QBUFSZ];
1377                 Strcpy(choicebuf, choices);
1378                 if ((cb = index(choicebuf, '\033')) != 0) {
1379                         /* anything beyond <esc> is hidden */
1380                         *cb = '\0';
1381                 }
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));
1387         } else {
1388                 Strcpy(message, question);
1389     }
1390
1391 #if defined(WIN_CE_SMARTPHONE)
1392         {
1393         char buf[BUFSZ];
1394         ZeroMemory(buf, sizeof(buf));
1395         if( choices ) {
1396                 if( !index(choices, '\033') ) buf[0]='\033'; /* make sure ESC is always available */
1397                 strncat( buf, choices, sizeof(buf)-2);
1398                 NHSPhoneSetKeypadFromString( buf );
1399         } else {
1400                 /* sometimes choices are included in the message itself, e.g. "what? [abcd]" */
1401                 char *p1, *p2;
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( );
1411                 } else {
1412                         /* anything goes */
1413                         NHSPhoneSetKeypadFromString( "\0330-9a-zA-Z" );
1414                 }
1415         }
1416         }
1417 #endif /* defined(WIN_CE_SMARTPHONE) */
1418
1419     mswin_putstr(WIN_MESSAGE, ATR_BOLD, message);
1420
1421     /* Only here if main window is not present */
1422     while (result<0) {
1423         ch=mswin_nhgetch();
1424         if (ch=='\033') {
1425             result=yn_esc_map;
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)) {
1429                 result=def;
1430             } else {
1431                 mswin_nhbell();
1432                 /* and try again... */
1433             }
1434         } else {
1435             result=ch;
1436         }
1437     }
1438
1439         /* display selection in the message window */
1440         if( isprint(ch) ) {
1441                 res_ch[0] = ch;
1442                 res_ch[1] = '\x0';
1443                 mswin_putstr_ex(WIN_MESSAGE, ATR_BOLD, res_ch, 1);
1444         }
1445
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);
1451
1452 #if defined(WIN_CE_SMARTPHONE)
1453         NHSPhoneSetKeypadDefault();
1454 #endif
1455     return result;
1456 }
1457
1458 /*
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.
1467 */
1468 void mswin_getlin(const char *question, char *input)
1469 {
1470         logDebug("mswin_getlin(%s, %p)\n", question, input);
1471         if( mswin_getlin_window(question, input, BUFSZ)==IDCANCEL ) {
1472                 strcpy(input, "\033");
1473         }
1474 }
1475
1476 /*
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.
1481 */
1482 int mswin_get_ext_cmd()
1483 {
1484         int ret;
1485         logDebug("mswin_get_ext_cmd()\n");
1486
1487         if(mswin_ext_cmd_window (&ret) == IDCANCEL)
1488                 return -1;
1489         else 
1490                 return ret;
1491 }
1492
1493
1494 /*
1495 number_pad(state)
1496             -- Initialize the number pad to the given state.
1497 */
1498 void mswin_number_pad(int state)
1499 {
1500     /* Do Nothing */
1501         logDebug("mswin_number_pad(%d)\n", state);
1502 }
1503
1504 /*
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.
1508 */
1509 void mswin_delay_output()
1510 {
1511         logDebug("mswin_delay_output()\n");
1512         Sleep(50);
1513 }
1514
1515 void mswin_change_color() 
1516
1517         logDebug("mswin_change_color()\n"); 
1518 }
1519
1520 char *mswin_get_color_string() 
1521
1522         logDebug("mswin_get_color_string()\n");
1523         return( "" ); 
1524 }
1525
1526 /*
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.
1532 */
1533 void mswin_start_screen()
1534 {
1535     /* Do Nothing */
1536         logDebug("mswin_start_screen()\n");
1537 }
1538
1539 /*
1540 end_screen()    -- Only used on Unix tty ports, but must be declared for
1541                completeness.  The complement of start_screen().
1542 */
1543 void mswin_end_screen()
1544 {
1545     /* Do Nothing */
1546         logDebug("mswin_end_screen()\n");
1547 }
1548
1549 /*
1550 outrip(winid, int)
1551             -- The tombstone code.  If you want the traditional code use
1552                genl_outrip for the value and check the #if in rip.c.
1553 */
1554 void mswin_outrip(winid wid, int how)
1555 {
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;
1562         }
1563
1564         genl_outrip(wid, how);
1565 }
1566
1567 /* handle options updates here */
1568 void mswin_preference_update(const char *pref)
1569 {
1570         HDC hdc;
1571
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;
1577
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);
1586
1587                 mswin_layout_main_window(NULL);
1588                 return;
1589         }
1590
1591         if( _stricmp( pref, "font_status")==0 ||
1592                 _stricmp( pref, "font_size_status")==0 ) {
1593
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;
1597
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);
1606
1607                 mswin_layout_main_window(NULL);
1608                 return;
1609         }
1610
1611         if( _stricmp( pref, "font_message")==0 ||
1612                 _stricmp( pref, "font_size_message")==0 ) {
1613
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;
1617
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);
1626
1627                 mswin_layout_main_window(NULL);
1628                 return;
1629         }
1630
1631         if( _stricmp( pref, "font_text")==0 ||
1632                 _stricmp( pref, "font_size_text")==0 ) {
1633
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;
1637
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);
1646
1647                 mswin_layout_main_window(NULL);
1648                 return;
1649         }
1650
1651         if( _stricmp( pref, "scroll_margin")==0 ) {
1652                 mswin_cliparound(u.ux, u.uy);
1653                 return;
1654         }
1655
1656         if( _stricmp( pref, "map_mode")==0 ) {
1657                 mswin_select_map_mode( iflags.wc_map_mode );
1658                 return;
1659         }
1660
1661         if( _stricmp( pref, "hilite_pet")==0 ) {
1662                 InvalidateRect(mswin_hwnd_from_winid(WIN_MAP), NULL, TRUE);
1663                 return;
1664         }
1665
1666         if( _stricmp( pref, "align_message")==0 ||
1667                 _stricmp( pref, "align_status")==0 ) {
1668                 mswin_layout_main_window(NULL);
1669                 return;
1670         }
1671
1672         if( _stricmp( pref, "vary_msgcount")==0 ) {
1673                 InvalidateRect(mswin_hwnd_from_winid(WIN_MESSAGE), NULL, TRUE);
1674                 mswin_layout_main_window(NULL);
1675                 return;
1676         }
1677
1678         if( _stricmp( pref, "fullscreen")==0 ) {
1679                 mswin_set_fullscreen(iflags.wc2_fullscreen);
1680                 return;
1681         }
1682
1683         if( _stricmp( pref, "softkeyboard")==0 ) {
1684                 GetNHApp()->bUseSIP = iflags.wc2_softkeyboard;
1685                 return;
1686         }
1687
1688         if( _stricmp( pref, "wraptext")==0 ) {
1689                 GetNHApp()->bWrapText = iflags.wc2_wraptext;
1690                 return;
1691         }
1692
1693 }
1694
1695 void mswin_main_loop()
1696 {
1697         MSG msg;
1698
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);
1704                 }
1705         } 
1706 }
1707
1708 /* clean up and quit */
1709 void bail(const char *mesg)
1710 {
1711     clearlocks();
1712     mswin_exit_nhwindows(mesg);
1713     terminate(EXIT_SUCCESS);
1714     /*NOTREACHED*/
1715 }
1716
1717 BOOL initMapTiles(void)
1718 {
1719         HBITMAP hBmp;
1720         BITMAP  bm;
1721         TCHAR   wbuf[MAX_PATH];
1722         int     tl_num;
1723         SIZE    map_size;
1724         extern int total_tiles_used;
1725
1726         /* no file - no tile */
1727         if( !(iflags.wc_tile_file && *iflags.wc_tile_file) ) 
1728                 return TRUE;
1729
1730         /* load bitmap */
1731         hBmp = SHLoadDIBitmap(NH_A2W(iflags.wc_tile_file, wbuf, MAX_PATH));
1732         if( hBmp==NULL ) {
1733                 raw_print("Cannot load tiles from the file. Reverting back to default.");
1734                 return FALSE;
1735         }
1736
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 ) {
1741                 DeleteObject(hBmp);
1742                 raw_print("Tiles bitmap does not match tile_width and tile_height options. Reverting back to default.");
1743                 return FALSE;
1744         }
1745
1746         tl_num = (bm.bmWidth/iflags.wc_tile_width)*
1747                      (bm.bmHeight/iflags.wc_tile_height);
1748         if( tl_num<total_tiles_used ) {
1749                 DeleteObject(hBmp);
1750                 raw_print("Number of tiles in the bitmap is less than required by the game. Reverting back to default.");
1751                 return FALSE;
1752         }
1753
1754         /* set the tile information */
1755         if( GetNHApp()->bmpMapTiles!=GetNHApp()->bmpTiles ) {
1756                 DeleteObject(GetNHApp()->bmpMapTiles);
1757         }
1758
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;
1763
1764         map_size.cx = GetNHApp()->mapTile_X * COLNO;
1765         map_size.cy = GetNHApp()->mapTile_Y * ROWNO;
1766         mswin_map_stretch(
1767                 mswin_hwnd_from_winid(WIN_MAP),
1768                 &map_size,
1769                 TRUE 
1770         );
1771         return TRUE;
1772 }
1773
1774 void mswin_popup_display(HWND hWnd, int* done_indicator)
1775 {
1776         MSG msg;
1777         HWND hChild;
1778
1779         /* activate the menu window */
1780         GetNHApp()->hPopupWnd = hWnd;
1781
1782         mswin_layout_main_window(hWnd);
1783
1784         /* disable game windows */
1785         for( hChild=GetWindow(GetNHApp()->hMainWnd, GW_CHILD);
1786                  hChild;
1787                  hChild = GetWindow(hChild, GW_HWNDNEXT) ) {
1788                 if( hChild!=hWnd ) EnableWindow(hChild, FALSE);
1789         }
1790 #if defined(WIN_CE_SMARTPHONE)
1791         ShowWindow(GetNHApp()->hMenuBar, SW_HIDE);
1792         ShowWindow(SHFindMenuBar(hWnd), SW_SHOW);
1793 #else
1794         EnableWindow(GetNHApp()->hMenuBar, FALSE);
1795 #endif
1796
1797         /* bring menu window on top */
1798         SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
1799
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);
1809                         }
1810                 }
1811         }
1812 }
1813
1814 void mswin_popup_destroy(HWND hWnd)
1815 {
1816         HWND hChild;
1817
1818         /* enable game windows */
1819         for( hChild=GetWindow(GetNHApp()->hMainWnd, GW_CHILD);
1820                  hChild;
1821                  hChild = GetWindow(hChild, GW_HWNDNEXT) ) {
1822                 if( hChild!= hWnd) {
1823                         EnableWindow(hChild, TRUE);
1824                 }
1825         }
1826 #if defined(WIN_CE_SMARTPHONE)
1827         ShowWindow(SHFindMenuBar(hWnd), SW_HIDE);
1828         ShowWindow(GetNHApp()->hMenuBar, SW_SHOW);
1829 #else
1830         EnableWindow(GetNHApp()->hMenuBar, TRUE);
1831 #endif
1832
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);
1837
1838         mswin_layout_main_window(hWnd);
1839
1840         SetFocus(GetNHApp()->hMainWnd );
1841 }
1842
1843 void mswin_set_fullscreen(BOOL is_fullscreen)
1844 {
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);
1849                 MoveWindow(
1850                         GetNHApp()->hMainWnd,
1851                         0,
1852                         0,
1853                         GetSystemMetrics(SM_CXSCREEN),
1854                         GetSystemMetrics(SM_CYSCREEN),
1855                         FALSE
1856                 );
1857         } else {
1858                 RECT rc;
1859                 SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, 0);
1860                 SHFullScreen(GetNHApp()->hMainWnd, SHFS_SHOWTASKBAR | SHFS_SHOWSTARTICON);
1861                 MoveWindow(
1862                         GetNHApp()->hMainWnd,
1863                         rc.left,
1864                         rc.top,
1865                         rc.right - rc.left,
1866                         rc.bottom - rc.top,
1867                         FALSE
1868                 );
1869         }
1870         GetNHApp()->bFullScreen = is_fullscreen;
1871 #else
1872         GetNHApp()->bFullScreen = FALSE;
1873 #endif
1874 }
1875
1876 #if defined(WIN_CE_SMARTPHONE)
1877 void NHSPhoneDialogSetup(HWND hDlg, BOOL is_edit, BOOL is_fullscreen)
1878 {
1879     SHMENUBARINFO mbi;
1880         HWND hOK, hCancel;
1881         RECT rtOK, rtDlg;
1882
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");
1891         }
1892
1893         if(is_fullscreen) {
1894                 SHINITDLGINFO shidi;
1895                 RECT main_wnd_rect;
1896                 shidi.dwMask = SHIDIM_FLAGS;
1897                 shidi.dwFlags = SHIDIF_SIZEDLGFULLSCREEN;
1898                 shidi.hDlg = hDlg;
1899                 SHInitDialog(&shidi);
1900
1901                 GetWindowRect(GetNHApp()->hMainWnd, &main_wnd_rect);
1902                 MoveWindow(
1903                         hDlg,
1904                         main_wnd_rect.left,
1905                         main_wnd_rect.top,
1906                         main_wnd_rect.right - main_wnd_rect.left,
1907                         main_wnd_rect.bottom - main_wnd_rect.top,
1908                         FALSE
1909                 );
1910         }
1911
1912         /* hide OK and CANCEL buttons */
1913         hOK = GetDlgItem(hDlg, IDOK);
1914         hCancel = GetDlgItem(hDlg, IDCANCEL);
1915
1916         if( IsWindow(hCancel) ) ShowWindow(hCancel, SW_HIDE);
1917         if( IsWindow(hOK) ) {
1918                 GetWindowRect(hOK, &rtOK);
1919                 GetWindowRect(hDlg, &rtDlg);
1920
1921                 rtDlg.bottom -= rtOK.bottom-rtOK.top;
1922                 ShowWindow(hOK, SW_HIDE);
1923                 SetWindowPos( hDlg, HWND_TOP, 
1924                                   0, 0, 
1925                                           rtDlg.right-rtDlg.left, rtDlg.bottom-rtDlg.top,
1926                                           SWP_NOMOVE | SWP_NOREPOSITION | SWP_NOZORDER );
1927         }
1928
1929         /* override "Back" button for edit box dialogs */
1930         if( is_edit ) 
1931                 SendMessage(mbi.hwndMB, SHCMBM_OVERRIDEKEY, VK_TBACK, MAKELPARAM(SHMBOF_NODEFAULT | SHMBOF_NOTIFY, SHMBOF_NODEFAULT | SHMBOF_NOTIFY));
1932 }
1933 #endif /* defined(WIN_CE_SMARTPHONE) */
1934
1935 void mswin_read_reg(void)
1936 {
1937 }
1938
1939 void mswin_destroy_reg(void)
1940 {
1941 }
1942
1943 void mswin_write_reg(void)
1944 {
1945 }
1946
1947 #ifdef _DEBUG
1948 #include <stdarg.h>
1949
1950 void
1951 logDebug(const char *fmt, ...)
1952 {
1953   FILE *dfp = fopen("nhtrace.log", "a");
1954
1955   if (dfp) {
1956      va_list args;
1957
1958      va_start(args, fmt);
1959      vfprintf(dfp, fmt, args);
1960      va_end(args);
1961      fclose(dfp);
1962   }
1963 }
1964
1965 #endif
1966