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
logDebug(const char * fmt,...)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 */
mswin_init_nhwindows(int * argc,char ** argv)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 */
mswin_player_selection(void)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
prompt_for_player_selection(void)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. */
mswin_askname(void)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 */
mswin_get_nh_event(void)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 */
mswin_exit_nhwindows(const char * str)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. */
mswin_suspend_nhwindows(const char * str)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. */
mswin_resume_nhwindows()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
mswin_create_nhwindow(int type)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. */
mswin_clear_nhwindow(winid wid)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 */
mswin_display_nhwindow(winid wid,BOOLEAN_P block)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
mswin_hwnd_from_winid(winid wid)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
mswin_winid_from_handle(HWND hWnd)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
mswin_winid_from_type(int type)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
mswin_window_mark_dead(winid wid)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 */
mswin_destroy_nhwindow(winid wid)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 */
mswin_curs(winid wid,int x,int y)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 */
mswin_putstr(winid wid,int attr,const char * text)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
mswin_putstr_ex(winid wid,int attr,const char * text,boolean app)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 */
mswin_display_file(const char * filename,BOOLEAN_P must_exist)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 */
mswin_start_menu(winid wid)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 */
mswin_add_menu(winid wid,int glyph,const ANY_P * identifier,CHAR_P accelerator,CHAR_P group_accel,int attr,const char * str,BOOLEAN_P presel)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 */
mswin_end_menu(winid wid,const char * prompt)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 */
mswin_select_menu(winid wid,int how,MENU_ITEM_P ** selected)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 */
mswin_update_inventory()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 */
mswin_mark_synch()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 */
mswin_wait_synch()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 */
mswin_cliparound(int x,int y)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 */
mswin_print_glyph(winid wid,XCHAR_P x,XCHAR_P y,int glyph)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 */
mswin_raw_print(const char * str)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 */
mswin_raw_print_bold(const char * str)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 */
mswin_nhgetch()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 */
mswin_nh_poskey(int * x,int * y,int * mod)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 */
mswin_nhbell()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 */
mswin_doprev_message()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 */
mswin_yn_function(const char * question,const char * choices,CHAR_P def)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 */
mswin_getlin(const char * question,char * input)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 */
mswin_get_ext_cmd()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 */
mswin_number_pad(int state)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 */
mswin_delay_output()1509 void mswin_delay_output()
1510 {
1511 logDebug("mswin_delay_output()\n");
1512 Sleep(50);
1513 }
1514
mswin_change_color()1515 void mswin_change_color()
1516 {
1517 logDebug("mswin_change_color()\n");
1518 }
1519
mswin_get_color_string()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 */
mswin_start_screen()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 */
mswin_end_screen()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 */
mswin_outrip(winid wid,int how)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 */
mswin_preference_update(const char * pref)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
mswin_main_loop()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 */
bail(const char * mesg)1709 void bail(const char *mesg)
1710 {
1711 clearlocks();
1712 mswin_exit_nhwindows(mesg);
1713 terminate(EXIT_SUCCESS);
1714 /*NOTREACHED*/
1715 }
1716
initMapTiles(void)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
mswin_popup_display(HWND hWnd,int * done_indicator)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
mswin_popup_destroy(HWND hWnd)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
mswin_set_fullscreen(BOOL is_fullscreen)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)
NHSPhoneDialogSetup(HWND hDlg,BOOL is_edit,BOOL is_fullscreen)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
mswin_read_reg(void)1935 void mswin_read_reg(void)
1936 {
1937 }
1938
mswin_destroy_reg(void)1939 void mswin_destroy_reg(void)
1940 {
1941 }
1942
mswin_write_reg(void)1943 void mswin_write_reg(void)
1944 {
1945 }
1946
1947 #ifdef _DEBUG
1948 #include <stdarg.h>
1949
1950 void
logDebug(const char * fmt,...)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
1967