1 /* File: main-win.c */
2
3 /*
4 * Copyright (c) 1997 Ben Harrison, Skirmantas Kligys, Robert Ruehlmann,
5 * and others
6 *
7 * This software may be copied and distributed for educational, research,
8 * and not for profit purposes provided that this copyright and statement
9 * are included in all such copies.
10 */
11
12
13 /*
14 * This file helps Angband work with Windows computers.
15 *
16 * To use this file, use an appropriate "Makefile" or "Project File",
17 * make sure that "WINDOWS" and/or "WIN32" are defined somewhere, and
18 * make sure to obtain various extra files as described below.
19 *
20 * The Windows version has been tested to compile with Visual C++ 5.0
21 * and 6.0, Cygwin 1.0, Borland C++ 5.5 command line tools, and lcc-win32.
22 *
23 *
24 * See also "main-dos.c" and "main-ibm.c".
25 *
26 *
27 * The "lib/pref/pref-win.prf" file contains keymaps, macro definitions,
28 * and/or color redefinitions.
29 *
30 * The "lib/pref/font-win.prf" contains attr/char mappings for use with the
31 * normal "*.fon" font files in the "lib/xtra/font/" directory.
32 *
33 * The "lib/pref/graf-win.prf" contains attr/char mappings for use with the
34 * special "*.bmp" bitmap files in the "lib/xtra/graf/" directory, which
35 * are activated by a menu item.
36 *
37 *
38 * Compiling this file, and using the resulting executable, requires
39 * several extra files not distributed with the standard Angband code.
40 * If "USE_GRAPHICS" is defined, then "readdib.h" and "readdib.c" must
41 * be placed into "src/", and the "8x8.bmp" bitmap file must be placed
42 * into "lib/xtra/graf". In any case, some "*.fon" files (including
43 * "8X13.FON" if nothing else) must be placed into "lib/xtra/font/".
44 * If "USE_SOUND" is defined, then some special library (for example,
45 * "winmm.lib") may need to be linked in, and desired "*.WAV" sound
46 * files must be placed into "lib/xtra/sound/". All of these extra
47 * files can be found in the "ext-win" archive.
48 *
49 *
50 * The "Term_xtra_win_clear()" function should probably do a low-level
51 * clear of the current window, and redraw the borders and other things,
52 * if only for efficiency. XXX XXX XXX
53 *
54 * A simpler method is needed for selecting the "tile size" for windows.
55 * XXX XXX XXX
56 *
57 * Special "Windows Help Files" can be placed into "lib/xtra/help/" for
58 * use with the "winhelp.exe" program. These files *may* be available
59 * at the ftp site somewhere, but I have not seen them. XXX XXX XXX
60 *
61 * ToDo: The screensaver mode should implement ScreenSaverConfigureDialog,
62 * DefScreenSaverProc, and ScreenSaverProc.
63 *
64 * Initial framework (and most code) by Ben Harrison (benh@phial.com).
65 *
66 * Original code by Skirmantas Kligys (kligys@scf.usc.edu).
67 *
68 * Additional code by Ross E Becker (beckerr@cis.ohio-state.edu),
69 * and Chris R. Martin (crm7479@tam2000.tamu.edu).
70 *
71 * Additional code by Robert Ruehlmann <rr9@angband.org>.
72 */
73
74 #include "angband.h"
75
76 #include "maid-grf.h"
77
78
79 #ifdef WINDOWS
80
81
82 /*
83 * Use HTML-Help.
84 */
85 /* #define HTML_HELP */
86
87 #ifdef HTML_HELP
88 # define HELP_GENERAL "angband.chm"
89 # define HELP_SPOILERS "angband.chm"
90 #else /* HTML_HELP */
91 # define HELP_GENERAL "angband.hlp"
92 # define HELP_SPOILERS "spoilers.hlp"
93 #endif /* HTML_HELP */
94
95
96 /*
97 * Extract the "WIN32" flag from the compiler
98 */
99 #if defined(__WIN32__) || defined(__WINNT__) || defined(__NT__)
100 # ifndef WIN32
101 # define WIN32
102 # endif
103 #endif
104
105
106 #ifdef ALLOW_BORG
107
108 /*
109 * Hack -- allow use of "screen saver" mode
110 */
111 /* #define USE_SAVER */
112
113 #endif /* ALLOW_BORG */
114
115
116 /*
117 * Menu constants -- see "ANGBAND.RC"
118 */
119
120 #define IDM_FILE_NEW 100
121 #define IDM_FILE_OPEN 101
122 #define IDM_FILE_SAVE 110
123 #define IDM_FILE_SCORE 120
124 #define IDM_FILE_EXIT 130
125
126 #define IDM_WINDOW_VIS_0 200
127 #define IDM_WINDOW_VIS_1 201
128 #define IDM_WINDOW_VIS_2 202
129 #define IDM_WINDOW_VIS_3 203
130 #define IDM_WINDOW_VIS_4 204
131 #define IDM_WINDOW_VIS_5 205
132 #define IDM_WINDOW_VIS_6 206
133 #define IDM_WINDOW_VIS_7 207
134
135 #define IDM_WINDOW_FONT_0 210
136 #define IDM_WINDOW_FONT_1 211
137 #define IDM_WINDOW_FONT_2 212
138 #define IDM_WINDOW_FONT_3 213
139 #define IDM_WINDOW_FONT_4 214
140 #define IDM_WINDOW_FONT_5 215
141 #define IDM_WINDOW_FONT_6 216
142 #define IDM_WINDOW_FONT_7 217
143
144 #define IDM_WINDOW_I_WID_0 240
145 #define IDM_WINDOW_I_WID_1 241
146 #define IDM_WINDOW_I_WID_2 242
147 #define IDM_WINDOW_I_WID_3 243
148 #define IDM_WINDOW_I_WID_4 244
149 #define IDM_WINDOW_I_WID_5 245
150 #define IDM_WINDOW_I_WID_6 246
151 #define IDM_WINDOW_I_WID_7 247
152
153 #define IDM_WINDOW_D_WID_0 250
154 #define IDM_WINDOW_D_WID_1 251
155 #define IDM_WINDOW_D_WID_2 252
156 #define IDM_WINDOW_D_WID_3 253
157 #define IDM_WINDOW_D_WID_4 254
158 #define IDM_WINDOW_D_WID_5 255
159 #define IDM_WINDOW_D_WID_6 256
160 #define IDM_WINDOW_D_WID_7 257
161
162 #define IDM_WINDOW_I_HGT_0 260
163 #define IDM_WINDOW_I_HGT_1 261
164 #define IDM_WINDOW_I_HGT_2 262
165 #define IDM_WINDOW_I_HGT_3 263
166 #define IDM_WINDOW_I_HGT_4 264
167 #define IDM_WINDOW_I_HGT_5 265
168 #define IDM_WINDOW_I_HGT_6 266
169 #define IDM_WINDOW_I_HGT_7 267
170
171 #define IDM_WINDOW_D_HGT_0 270
172 #define IDM_WINDOW_D_HGT_1 271
173 #define IDM_WINDOW_D_HGT_2 272
174 #define IDM_WINDOW_D_HGT_3 273
175 #define IDM_WINDOW_D_HGT_4 274
176 #define IDM_WINDOW_D_HGT_5 275
177 #define IDM_WINDOW_D_HGT_6 276
178 #define IDM_WINDOW_D_HGT_7 277
179
180 #define IDM_OPTIONS_GRAPHICS_NONE 400
181 #define IDM_OPTIONS_GRAPHICS_OLD 401
182 #define IDM_OPTIONS_GRAPHICS_ADAM 402
183 #define IDM_OPTIONS_GRAPHICS_DAVID 403
184 #define IDM_OPTIONS_BIGTILE 409
185 #define IDM_OPTIONS_SOUND 410
186 #define IDM_OPTIONS_LOW_PRIORITY 420
187 #define IDM_OPTIONS_SAVER 430
188 #define IDM_OPTIONS_MAP 440
189
190 #define IDM_HELP_GENERAL 901
191 #define IDM_HELP_SPOILERS 902
192
193
194 /*
195 * This may need to be removed for some compilers XXX XXX XXX
196 */
197 #define STRICT
198
199 /*
200 * Exclude parts of WINDOWS.H that are not needed
201 */
202 #define NOCOMM /* Comm driver APIs and definitions */
203 #define NOLOGERROR /* LogError() and related definitions */
204 #define NOPROFILER /* Profiler APIs */
205 #define NOLFILEIO /* _l* file I/O routines */
206 #define NOOPENFILE /* OpenFile and related definitions */
207 #define NORESOURCE /* Resource management */
208 #define NOATOM /* Atom management */
209 #define NOLANGUAGE /* Character test routines */
210 #define NOLSTRING /* lstr* string management routines */
211 #define NODBCS /* Double-byte character set routines */
212 #define NOKEYBOARDINFO /* Keyboard driver routines */
213 #define NOCOLOR /* COLOR_* color values */
214 #define NODRAWTEXT /* DrawText() and related definitions */
215 #define NOSCALABLEFONT /* Truetype scalable font support */
216 #define NOMETAFILE /* Metafile support */
217 #define NOSYSTEMPARAMSINFO /* SystemParametersInfo() and SPI_* definitions */
218 #define NODEFERWINDOWPOS /* DeferWindowPos and related definitions */
219 #define NOKEYSTATES /* MK_* message key state flags */
220 #define NOWH /* SetWindowsHook and related WH_* definitions */
221 #define NOCLIPBOARD /* Clipboard APIs and definitions */
222 #define NOICONS /* IDI_* icon IDs */
223 #define NOMDI /* MDI support */
224 #define NOHELP /* Help support */
225
226 /* Not defined since it breaks Borland C++ 5.5 */
227 /* #define NOCTLMGR */ /* Control management and controls */
228
229 /*
230 * Exclude parts of WINDOWS.H that are not needed (Win32)
231 */
232 #define WIN32_LEAN_AND_MEAN
233 #define NONLS /* All NLS defines and routines */
234 #define NOSERVICE /* All Service Controller routines, SERVICE_ equates, etc. */
235 #define NOKANJI /* Kanji support stuff. */
236 #define NOMCX /* Modem Configuration Extensions */
237
238
239 /* Mega-hack, these include files require double and float to work */
240 #undef float
241 #undef double
242
243 /*
244 * Include the "windows" support file
245 */
246 #include <windows.h>
247
248 #ifdef USE_SOUND
249
250 /*
251 * Exclude parts of MMSYSTEM.H that are not needed
252 */
253 #define MMNODRV /* Installable driver support */
254 #define MMNOWAVE /* Waveform support */
255 #define MMNOMIDI /* MIDI support */
256 #define MMNOAUX /* Auxiliary audio support */
257 #define MMNOTIMER /* Timer support */
258 #define MMNOJOY /* Joystick support */
259 #define MMNOMCI /* MCI support */
260 #define MMNOMMIO /* Multimedia file I/O support */
261 #define MMNOMMSYSTEM /* General MMSYSTEM functions */
262
263 #include <mmsystem.h>
264
265 #endif /* USE_SOUND */
266
267 #include <commdlg.h>
268
269 /*
270 * HTML-Help requires htmlhelp.h and htmlhelp.lib from Microsoft's
271 * HTML Workshop < msdn.microsoft.com/workshop/author/htmlhelp/ >.
272 */
273 #ifdef HTML_HELP
274 #include <htmlhelp.h>
275 #endif /* HTML_HELP */
276
277 /*
278 * Include the support for loading bitmaps
279 */
280 #ifdef USE_GRAPHICS
281 # include "readdib.h"
282 #endif /* USE_GRAPHICS */
283
284 /*
285 * Hack -- Fake declarations from "dos.h" XXX XXX XXX
286 */
287 #ifdef WIN32
288 #define INVALID_FILE_NAME (DWORD)0xFFFFFFFF
289 #else /* WIN32 */
290 #define FA_LABEL 0x08 /* Volume label */
291 #define FA_DIREC 0x10 /* Directory */
292 unsigned _cdecl _dos_getfileattr(const char *, unsigned *);
293 #endif /* WIN32 */
294
295 /* Mega-hack redefine them again */
296 #undef float
297 #define float floating_point_is_not_allowed
298 #undef double
299 #define double floating_point_is_not_allowed
300
301 /*
302 * Silliness in WIN32 drawing routine
303 */
304 #ifdef WIN32
305 # define MoveTo(H,X,Y) MoveToEx(H, X, Y, NULL)
306 #endif /* WIN32 */
307
308 /*
309 * Silliness for Windows 95
310 */
311 #ifndef WS_EX_TOOLWINDOW
312 # define WS_EX_TOOLWINDOW 0
313 #endif /* WS_EX_TOOLWINDOW */
314
315 /*
316 * Foreground color bits (hard-coded by DOS)
317 */
318 #define VID_BLACK 0x00
319 #define VID_BLUE 0x01
320 #define VID_GREEN 0x02
321 #define VID_CYAN 0x03
322 #define VID_RED 0x04
323 #define VID_MAGENTA 0x05
324 #define VID_YELLOW 0x06
325 #define VID_WHITE 0x07
326
327 /*
328 * Bright text (hard-coded by DOS)
329 */
330 #define VID_BRIGHT 0x08
331
332 /*
333 * Background color bits (hard-coded by DOS)
334 */
335 #define VUD_BLACK 0x00
336 #define VUD_BLUE 0x10
337 #define VUD_GREEN 0x20
338 #define VUD_CYAN 0x30
339 #define VUD_RED 0x40
340 #define VUD_MAGENTA 0x50
341 #define VUD_YELLOW 0x60
342 #define VUD_WHITE 0x70
343
344 /*
345 * Blinking text (hard-coded by DOS)
346 */
347 #define VUD_BRIGHT 0x80
348
349
350 /*
351 * Forward declare
352 */
353 typedef struct _term_data term_data;
354
355 /*
356 * Extra "term" data
357 *
358 * Note the use of "font_want" for the names of the font file requested by
359 * the user, and the use of "font_file" for the currently active font file.
360 *
361 * The "font_file" is uppercased, and takes the form "8X13.FON", while
362 * "font_want" can be in almost any form as long as it could be construed
363 * as attempting to represent the name of a font.
364 */
365 struct _term_data
366 {
367 term t;
368
369 cptr s;
370
371 HWND w;
372
373 DWORD dwStyle;
374 DWORD dwExStyle;
375
376 uint keys;
377
378 byte rows;
379 byte cols;
380
381 uint pos_x;
382 uint pos_y;
383 uint size_wid;
384 uint size_hgt;
385 uint size_ow1;
386 uint size_oh1;
387 uint size_ow2;
388 uint size_oh2;
389
390 bool size_hack;
391
392 bool xtra_hack;
393
394 bool visible;
395 bool maximized;
396
397 cptr font_want;
398
399 cptr font_file;
400
401 HFONT font_id;
402
403 uint font_wid;
404 uint font_hgt;
405
406 uint tile_wid;
407 uint tile_hgt;
408
409 uint map_tile_wid;
410 uint map_tile_hgt;
411
412 bool map_active;
413 };
414
415
416 /*
417 * Maximum number of windows XXX XXX XXX
418 */
419 #define MAX_TERM_DATA 8
420
421
422 /*
423 * An array of term_data's
424 */
425 static term_data data[MAX_TERM_DATA];
426
427 /*
428 * Hack -- global "window creation" pointer
429 */
430 static term_data *my_td;
431
432 /*
433 * game in progress
434 */
435 bool game_in_progress = FALSE;
436
437 /*
438 * note when "open"/"new" become valid
439 */
440 bool initialized = FALSE;
441
442 /*
443 * screen paletted, i.e. 256 colors
444 */
445 bool paletted = FALSE;
446
447 /*
448 * 16 colors screen, don't use RGB()
449 */
450 bool colors16 = FALSE;
451
452 static bool low_priority = FALSE;
453
454 /*
455 * Saved instance handle
456 */
457 static HINSTANCE hInstance;
458
459 /*
460 * Yellow brush for the cursor
461 */
462 static HBRUSH hbrYellow;
463
464 /*
465 * An icon
466 */
467 static HICON hIcon;
468
469 /*
470 * A palette
471 */
472 static HPALETTE hPal;
473
474
475 #ifdef USE_SAVER
476
477 /*
478 * The screen saver window
479 */
480 static HWND hwndSaver;
481
482 static bool screensaver = FALSE;
483 static bool screensaver_active = FALSE;
484
485 static HANDLE screensaverSemaphore;
486
487 static char saverfilename[1024];
488
489 static HMENU main_menu;
490
491 #define MOUSE_SENS 10
492
493 #endif /* USE_SAVER */
494
495
496 #ifdef USE_GRAPHICS
497
498 /*
499 * Flag set once "graphics" has been initialized
500 */
501 static bool can_use_graphics = FALSE;
502
503 /*
504 * The global bitmap
505 */
506 static DIBINIT infGraph;
507
508 /*
509 * The global bitmap mask
510 */
511 static DIBINIT infMask;
512
513 #endif /* USE_GRAPHICS */
514
515
516 #ifdef USE_SOUND
517
518 /*
519 * Flag set once "sound" has been initialized
520 */
521 static bool can_use_sound = FALSE;
522
523 #define SAMPLE_MAX 8
524
525 /*
526 * An array of sound file names
527 */
528 static cptr sound_file[SOUND_MAX][SAMPLE_MAX];
529
530 #endif /* USE_SOUND */
531
532
533 /*
534 * Full path to ANGBAND.INI
535 */
536 static cptr ini_file = NULL;
537
538 /*
539 * Name of application
540 */
541 static cptr AppName = VERSION_NAME;
542
543 /*
544 * Name of sub-window type
545 */
546 static cptr AngList = "AngList";
547
548 /*
549 * Directory names
550 */
551 static cptr ANGBAND_DIR_XTRA_FONT;
552 static cptr ANGBAND_DIR_XTRA_GRAF;
553 static cptr ANGBAND_DIR_XTRA_SOUND;
554 static cptr ANGBAND_DIR_XTRA_HELP;
555 #if USE_MUSIC
556 static cptr ANGBAND_DIR_XTRA_MUSIC;
557 #endif /* USE_MUSIC */
558
559 /*
560 * The "complex" color values
561 */
562 static COLORREF win_clr[256];
563
564
565 /*
566 * The "simple" color values
567 *
568 * See "main-ibm.c" for original table information
569 *
570 * The entries below are taken from the "color bits" defined above.
571 *
572 * Note that many of the choices below suck, but so do crappy monitors.
573 */
574 static byte win_pal[256] =
575 {
576 VID_BLACK, /* Dark */
577 VID_WHITE, /* White */
578 VID_CYAN, /* Slate XXX */
579 VID_RED | VID_BRIGHT, /* Orange XXX */
580 VID_RED, /* Red */
581 VID_GREEN, /* Green */
582 VID_BLUE, /* Blue */
583 VID_YELLOW, /* Umber XXX */
584 VID_BLACK | VID_BRIGHT, /* Light Dark */
585 VID_CYAN | VID_BRIGHT, /* Light Slate XXX */
586 VID_MAGENTA, /* Violet XXX */
587 VID_YELLOW | VID_BRIGHT, /* Yellow */
588 VID_MAGENTA | VID_BRIGHT, /* Light Red XXX */
589 VID_GREEN | VID_BRIGHT, /* Light Green */
590 VID_BLUE | VID_BRIGHT, /* Light Blue */
591 VID_YELLOW /* Light Umber XXX */
592 };
593
594
595 #ifdef SUPPORT_GAMMA
596 static int gamma_correction;
597 #endif /* SUPPORT_GAMMA */
598
599
600 /*
601 * Hack -- define which keys are "special"
602 */
603 static bool special_key[256];
604
605 /*
606 * Hack -- initialization list for "special_key"
607 *
608 * We ignore the modifier keys (shift, control, alt, num lock, scroll lock),
609 * and the normal keys (escape, tab, return, letters, numbers, etc), but we
610 * catch the keypad keys (with and without numlock set, including keypad 5),
611 * the function keys (including the "menu" key which maps to F10), and the
612 * "pause" key (between scroll lock and numlock). We also catch a few odd
613 * keys which I do not recognize, but which are listed among keys which we
614 * do catch, so they should be harmless to catch.
615 */
616 static const byte special_key_list[] =
617 {
618 VK_CLEAR, /* 0x0C (KP<5>) */
619
620 VK_PAUSE, /* 0x13 (pause) */
621
622 VK_PRIOR, /* 0x21 (KP<9>) */
623 VK_NEXT, /* 0x22 (KP<3>) */
624 VK_END, /* 0x23 (KP<1>) */
625 VK_HOME, /* 0x24 (KP<7>) */
626 VK_LEFT, /* 0x25 (KP<4>) */
627 VK_UP, /* 0x26 (KP<8>) */
628 VK_RIGHT, /* 0x27 (KP<6>) */
629 VK_DOWN, /* 0x28 (KP<2>) */
630 VK_SELECT, /* 0x29 (?) */
631 VK_PRINT, /* 0x2A (?) */
632 VK_EXECUTE, /* 0x2B (?) */
633 VK_SNAPSHOT, /* 0x2C (?) */
634 VK_INSERT, /* 0x2D (KP<0>) */
635 VK_DELETE, /* 0x2E (KP<.>) */
636 VK_HELP, /* 0x2F (?) */
637
638 #if 0
639 VK_NUMPAD0, /* 0x60 (KP<0>) */
640 VK_NUMPAD1, /* 0x61 (KP<1>) */
641 VK_NUMPAD2, /* 0x62 (KP<2>) */
642 VK_NUMPAD3, /* 0x63 (KP<3>) */
643 VK_NUMPAD4, /* 0x64 (KP<4>) */
644 VK_NUMPAD5, /* 0x65 (KP<5>) */
645 VK_NUMPAD6, /* 0x66 (KP<6>) */
646 VK_NUMPAD7, /* 0x67 (KP<7>) */
647 VK_NUMPAD8, /* 0x68 (KP<8>) */
648 VK_NUMPAD9, /* 0x69 (KP<9>) */
649 VK_MULTIPLY, /* 0x6A (KP<*>) */
650 VK_ADD, /* 0x6B (KP<+>) */
651 VK_SEPARATOR, /* 0x6C (?????) */
652 VK_SUBTRACT, /* 0x6D (KP<->) */
653 VK_DECIMAL, /* 0x6E (KP<.>) */
654 VK_DIVIDE, /* 0x6F (KP</>) */
655 #endif /* 0 */
656
657 VK_F1, /* 0x70 */
658 VK_F2, /* 0x71 */
659 VK_F3, /* 0x72 */
660 VK_F4, /* 0x73 */
661 VK_F5, /* 0x74 */
662 VK_F6, /* 0x75 */
663 VK_F7, /* 0x76 */
664 VK_F8, /* 0x77 */
665 VK_F9, /* 0x78 */
666 VK_F10, /* 0x79 */
667 VK_F11, /* 0x7A */
668 VK_F12, /* 0x7B */
669 VK_F13, /* 0x7C */
670 VK_F14, /* 0x7D */
671 VK_F15, /* 0x7E */
672 VK_F16, /* 0x7F */
673 VK_F17, /* 0x80 */
674 VK_F18, /* 0x81 */
675 VK_F19, /* 0x82 */
676 VK_F20, /* 0x83 */
677 VK_F21, /* 0x84 */
678 VK_F22, /* 0x85 */
679 VK_F23, /* 0x86 */
680 VK_F24, /* 0x87 */
681
682 0
683 };
684
685 #if 0
686 /*
687 * Hack -- given a pathname, point at the filename
688 */
689 static cptr extract_file_name(cptr s)
690 {
691 cptr p;
692
693 /* Start at the end */
694 p = s + strlen(s) - 1;
695
696 /* Back up to divider */
697 while ((p >= s) && (*p != ':') && (*p != '\\')) p--;
698
699 /* Return file name */
700 return (p+1);
701 }
702 #endif /* 0 */
703
704
show_win_error(void)705 static void show_win_error(void)
706 {
707 LPVOID lpMsgBuf;
708
709 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
710 NULL, GetLastError(),
711 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
712 (LPTSTR) &lpMsgBuf, 0, NULL);
713
714 MessageBox(NULL, lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION);
715
716 LocalFree(lpMsgBuf);
717 }
718
719
720 /*
721 * Hack -- given a simple filename, extract the "font size" info
722 *
723 * Return a pointer to a static buffer holding the capitalized base name.
724 */
analyze_font(char * path,int * wp,int * hp)725 static char *analyze_font(char *path, int *wp, int *hp)
726 {
727 int wid, hgt;
728
729 char *s, *p;
730
731 /* Start at the end */
732 p = path + strlen(path) - 1;
733
734 /* Back up to divider */
735 while ((p >= path) && (*p != ':') && (*p != '\\')) --p;
736
737 /* Advance to file name */
738 ++p;
739
740 /* Capitalize */
741 for (s = p; *s; ++s)
742 {
743 /* Capitalize (be paranoid) */
744 if (islower((unsigned char)*s)) *s = toupper((unsigned char)*s);
745 }
746
747 /* Find first 'X' */
748 s = strchr(p, 'X');
749
750 /* Extract font width */
751 wid = atoi(p);
752
753 /* Extract height */
754 hgt = s ? atoi(s+1) : 0;
755
756 /* Save results */
757 (*wp) = wid;
758 (*hp) = hgt;
759
760 /* Result */
761 return (p);
762 }
763
764
765 /*
766 * Check for existance of a file
767 */
check_file(cptr s)768 static bool check_file(cptr s)
769 {
770 char path[1024];
771
772 #ifdef WIN32
773
774 DWORD attrib;
775
776 #else /* WIN32 */
777
778 unsigned int attrib;
779
780 #endif /* WIN32 */
781
782 /* Copy it */
783 strnfmt(path, 1024, "%s", s);
784
785 #ifdef WIN32
786
787 /* Examine */
788 attrib = GetFileAttributes(path);
789
790 /* Require valid filename */
791 if (attrib == INVALID_FILE_NAME) return (FALSE);
792
793 /* Prohibit directory */
794 if (attrib & FILE_ATTRIBUTE_DIRECTORY) return (FALSE);
795
796 #else /* WIN32 */
797
798 /* Examine and verify */
799 if (_dos_getfileattr(path, &attrib)) return (FALSE);
800
801 /* Prohibit something */
802 if (attrib & FA_LABEL) return (FALSE);
803
804 /* Prohibit directory */
805 if (attrib & FA_DIREC) return (FALSE);
806
807 #endif /* WIN32 */
808
809 /* Success */
810 return (TRUE);
811 }
812
813
814 /*
815 * Check for existance of a directory
816 */
check_dir(cptr s)817 static bool check_dir(cptr s)
818 {
819 int i;
820
821 char path[1024];
822
823 #ifdef WIN32
824
825 DWORD attrib;
826
827 #else /* WIN32 */
828
829 unsigned int attrib;
830
831 #endif /* WIN32 */
832
833 /* Copy it */
834 strcpy(path, s);
835
836 /* Check length */
837 i = strlen(path);
838
839 /* Remove trailing backslash */
840 if (i && (path[i-1] == '\\')) path[--i] = '\0';
841
842 #ifdef WIN32
843
844 /* Examine */
845 attrib = GetFileAttributes(path);
846
847 /* Require valid filename */
848 if (attrib == INVALID_FILE_NAME) return (FALSE);
849
850 /* Require directory */
851 if (!(attrib & FILE_ATTRIBUTE_DIRECTORY)) return (FALSE);
852
853 #else /* WIN32 */
854
855 /* Examine and verify */
856 if (_dos_getfileattr(path, &attrib)) return (FALSE);
857
858 /* Prohibit something */
859 if (attrib & FA_LABEL) return (FALSE);
860
861 /* Require directory */
862 if (!(attrib & FA_DIREC)) return (FALSE);
863
864 #endif /* WIN32 */
865
866 /* Success */
867 return (TRUE);
868 }
869
870
871 /*
872 * Validate a file
873 */
validate_file(cptr s)874 static void validate_file(cptr s)
875 {
876 /* Verify or fail */
877 if (!check_file(s))
878 {
879 quit_fmt("Cannot find required file:\n%s", s);
880 }
881 }
882
883
884 /*
885 * Validate a directory
886 */
validate_dir(cptr s)887 static void validate_dir(cptr s)
888 {
889 /* Verify or fail */
890 if (!check_dir(s))
891 {
892 quit_fmt("Cannot find required directory:\n%s", s);
893 }
894 }
895
896
897 /*
898 * Get the "size" for a window
899 */
term_getsize(term_data * td)900 static void term_getsize(term_data *td)
901 {
902 RECT rc;
903
904 int wid, hgt;
905
906 /* Paranoia */
907 if (td->cols < 1) td->cols = 1;
908 if (td->rows < 1) td->rows = 1;
909
910 /* Window sizes */
911 wid = td->cols * td->tile_wid + td->size_ow1 + td->size_ow2;
912 hgt = td->rows * td->tile_hgt + td->size_oh1 + td->size_oh2;
913
914 /* Fake window size */
915 rc.left = 0;
916 rc.right = rc.left + wid;
917 rc.top = 0;
918 rc.bottom = rc.top + hgt;
919
920 /* XXX XXX XXX */
921 /* rc.right += 1; */
922 /* rc.bottom += 1; */
923
924 /* Adjust */
925 AdjustWindowRectEx(&rc, td->dwStyle, TRUE, td->dwExStyle);
926
927 /* Total size */
928 td->size_wid = rc.right - rc.left;
929 td->size_hgt = rc.bottom - rc.top;
930
931 /* See CreateWindowEx */
932 if (!td->w) return;
933
934 /* Extract actual location */
935 GetWindowRect(td->w, &rc);
936
937 /* Save the location */
938 td->pos_x = rc.left;
939 td->pos_y = rc.top;
940 }
941
942
943 /*
944 * Write the "prefs" for a single term
945 */
save_prefs_aux(term_data * td,cptr sec_name)946 static void save_prefs_aux(term_data *td, cptr sec_name)
947 {
948 char buf[1024];
949
950 RECT rc;
951
952 WINDOWPLACEMENT lpwndpl;
953
954 /* Paranoia */
955 if (!td->w) return;
956
957 /* Visible */
958 strcpy(buf, td->visible ? "1" : "0");
959 WritePrivateProfileString(sec_name, "Visible", buf, ini_file);
960
961 /* Font */
962 strcpy(buf, td->font_file ? td->font_file : "8X13.FON");
963 WritePrivateProfileString(sec_name, "Font", buf, ini_file);
964
965 /* Tile size (x) */
966 wsprintf(buf, "%d", td->tile_wid);
967 WritePrivateProfileString(sec_name, "TileWid", buf, ini_file);
968
969 /* Tile size (y) */
970 wsprintf(buf, "%d", td->tile_hgt);
971 WritePrivateProfileString(sec_name, "TileHgt", buf, ini_file);
972
973 /* Window size (x) */
974 wsprintf(buf, "%d", td->cols);
975 WritePrivateProfileString(sec_name, "NumCols", buf, ini_file);
976
977 /* Window size (y) */
978 wsprintf(buf, "%d", td->rows);
979 WritePrivateProfileString(sec_name, "NumRows", buf, ini_file);
980
981 /* Get window placement and dimensions */
982 lpwndpl.length = sizeof(WINDOWPLACEMENT);
983 GetWindowPlacement(td->w, &lpwndpl);
984
985 /* Acquire position in *normal* mode (not minimized) */
986 rc = lpwndpl.rcNormalPosition;
987
988 /* Get information about the placement of the window */
989 if (lpwndpl.flags & SW_SHOWMAXIMIZED)
990 td->maximized = TRUE;
991 else
992 td->maximized = FALSE;
993
994 /* Window position (x) */
995 wsprintf(buf, "%d", rc.left);
996 WritePrivateProfileString(sec_name, "PositionX", buf, ini_file);
997
998 /* Window position (y) */
999 wsprintf(buf, "%d", rc.top);
1000 WritePrivateProfileString(sec_name, "PositionY", buf, ini_file);
1001
1002 /* Maximized */
1003 strcpy(buf, td->maximized ? "1" : "0");
1004 WritePrivateProfileString(sec_name, "Maximized", buf, ini_file);
1005 }
1006
1007
1008 /*
1009 * Write the "prefs"
1010 *
1011 * We assume that the windows have all been initialized
1012 */
save_prefs(void)1013 static void save_prefs(void)
1014 {
1015 int i;
1016
1017 char buf[128];
1018
1019 /* Save the "arg_graphics" flag */
1020 strnfmt(buf, 128, "%d", arg_graphics);
1021 WritePrivateProfileString("Angband", "Graphics", buf, ini_file);
1022
1023 /* Save the "use_bigtile" flag */
1024 strnfmt(buf, 128, "%d", use_bigtile ? 1 : 0);
1025 WritePrivateProfileString("Angband", "Bigtile", buf, ini_file);
1026
1027 /* Save the "arg_sound" flag */
1028 strnfmt(buf, 128, "%d", arg_sound ? 1 : 0);
1029 WritePrivateProfileString("Angband", "Sound", buf, ini_file);
1030
1031 /* Save window prefs */
1032 for (i = 0; i < MAX_TERM_DATA; i++)
1033 {
1034 term_data *td = &data[i];
1035
1036 strnfmt(buf, 128, "Term-%d", i);
1037
1038 save_prefs_aux(td, buf);
1039 }
1040 }
1041
1042
1043 /*
1044 * Load the "prefs" for a single term
1045 */
load_prefs_aux(term_data * td,cptr sec_name)1046 static void load_prefs_aux(term_data *td, cptr sec_name)
1047 {
1048 char tmp[1024];
1049
1050 int wid, hgt;
1051
1052 /* Visible */
1053 td->visible = (GetPrivateProfileInt(sec_name, "Visible", td->visible, ini_file) != 0);
1054
1055 /* Maximized */
1056 td->maximized = (GetPrivateProfileInt(sec_name, "Maximized", td->maximized, ini_file) != 0);
1057
1058 /* Desired font, with default */
1059 GetPrivateProfileString(sec_name, "Font", "8X13.FON", tmp, 127, ini_file);
1060
1061 /* Analyze font, save desired font name */
1062 td->font_want = string_make(analyze_font(tmp, &wid, &hgt));
1063
1064 /* Tile size */
1065 td->tile_wid = GetPrivateProfileInt(sec_name, "TileWid", wid, ini_file);
1066 td->tile_hgt = GetPrivateProfileInt(sec_name, "TileHgt", hgt, ini_file);
1067
1068 /* Window size */
1069 td->cols = GetPrivateProfileInt(sec_name, "NumCols", td->cols, ini_file);
1070 td->rows = GetPrivateProfileInt(sec_name, "NumRows", td->rows, ini_file);
1071
1072 /* Window position */
1073 td->pos_x = GetPrivateProfileInt(sec_name, "PositionX", td->pos_x, ini_file);
1074 td->pos_y = GetPrivateProfileInt(sec_name, "PositionY", td->pos_y, ini_file);
1075 }
1076
1077
1078 /*
1079 * Load the "prefs"
1080 */
load_prefs(void)1081 static void load_prefs(void)
1082 {
1083 int i;
1084
1085 char buf[1024];
1086
1087 /* Extract the "arg_graphics" flag */
1088 arg_graphics = GetPrivateProfileInt("Angband", "Graphics", GRAPHICS_NONE, ini_file);
1089
1090 /* Extract the "use_bigtile" flag */
1091 use_bigtile = GetPrivateProfileInt("Angband", "Bigtile", FALSE, ini_file);
1092
1093 /* Extract the "arg_sound" flag */
1094 arg_sound = (GetPrivateProfileInt("Angband", "Sound", 0, ini_file) != 0);
1095
1096 /* Extract the "arg_fiddle" flag */
1097 arg_fiddle = (GetPrivateProfileInt("Angband", "Fiddle", 0, ini_file) != 0);
1098
1099 /* Extract the "arg_wizard" flag */
1100 arg_wizard = (GetPrivateProfileInt("Angband", "Wizard", 0, ini_file) != 0);
1101
1102 /* Extract the "arg_roguelike" flag */
1103 arg_force_roguelike = (GetPrivateProfileInt("Angband", "force_roguelike", 0, ini_file) != 0);
1104
1105 /* Extract the "arg_original" flag */
1106 arg_force_original = (GetPrivateProfileInt("Angband", "force_original", 0, ini_file) != 0);
1107
1108 #ifdef SUPPORT_GAMMA
1109
1110 /* Extract the gamma correction */
1111 gamma_correction = GetPrivateProfileInt("Angband", "Gamma", 0, ini_file);
1112
1113 #endif /* SUPPORT_GAMMA */
1114
1115 /* Load window prefs */
1116 for (i = 0; i < MAX_TERM_DATA; i++)
1117 {
1118 term_data *td = &data[i];
1119
1120 strnfmt(buf, 1024, "Term-%d", i);
1121
1122 load_prefs_aux(td, buf);
1123 }
1124
1125 /* Paranoia */
1126 if (data[0].cols < 80) data[0].cols = 80;
1127 if (data[0].rows < 24) data[0].rows = 24;
1128 }
1129
1130
1131 #ifdef USE_SOUND
1132
1133 /*
1134 * XXX XXX XXX - Taken from files.c.
1135 *
1136 * Extract "tokens" from a buffer
1137 *
1138 * This function uses "whitespace" as delimiters, and treats any amount of
1139 * whitespace as a single delimiter. We will never return any empty tokens.
1140 * When given an empty buffer, or a buffer containing only "whitespace", we
1141 * will return no tokens. We will never extract more than "num" tokens.
1142 *
1143 * By running a token through the "text_to_ascii()" function, you can allow
1144 * that token to include (encoded) whitespace, using "\s" to encode spaces.
1145 *
1146 * We save pointers to the tokens in "tokens", and return the number found.
1147 */
tokenize_whitespace(char * buf,s16b num,char ** tokens)1148 static s16b tokenize_whitespace(char *buf, s16b num, char **tokens)
1149 {
1150 int k = 0;
1151
1152 char *s = buf;
1153
1154
1155 /* Process */
1156 while (k < num)
1157 {
1158 char *t;
1159
1160 /* Skip leading whitespace */
1161 for ( ; *s && isspace((unsigned char)*s); ++s) /* loop */;
1162
1163 /* All done */
1164 if (!*s) break;
1165
1166 /* Find next whitespace, if any */
1167 for (t = s; *t && !isspace((unsigned char)*t); ++t) /* loop */;
1168
1169 /* Nuke and advance (if necessary) */
1170 if (*t) *t++ = '\0';
1171
1172 /* Save the token */
1173 tokens[k++] = s;
1174
1175 /* Advance */
1176 s = t;
1177 }
1178
1179 /* Count */
1180 return (k);
1181 }
1182
1183
load_sound_prefs(void)1184 static void load_sound_prefs(void)
1185 {
1186 int i, j, num;
1187 char tmp[1024];
1188 char ini_path[1024];
1189 char wav_path[1024];
1190 char *zz[SAMPLE_MAX];
1191
1192 /* Access the sound.cfg */
1193 path_make(ini_path, ANGBAND_DIR_XTRA_SOUND, "sound.cfg");
1194
1195 for (i = 0; i < SOUND_MAX; i++)
1196 {
1197 /* Ignore empty sound strings */
1198 if (!angband_sound_name[i][0]) continue;
1199
1200 GetPrivateProfileString("Sound", angband_sound_name[i], "", tmp, sizeof(tmp), ini_path);
1201
1202 num = tokenize_whitespace(tmp, SAMPLE_MAX, zz);
1203
1204 for (j = 0; j < num; j++)
1205 {
1206 /* Access the sound */
1207 path_make(wav_path, ANGBAND_DIR_XTRA_SOUND, zz[j]);
1208
1209 /* Save the sound filename, if it exists */
1210 if (check_file(wav_path))
1211 sound_file[i][j] = string_make(zz[j]);
1212 }
1213 }
1214 }
1215
1216 #endif /* USE_SOUND */
1217
1218
1219 /*
1220 * Create the new global palette based on the bitmap palette
1221 * (if any), and the standard 16 entry palette derived from
1222 * "win_clr[]" which is used for the basic 16 Angband colors.
1223 *
1224 * This function is never called before all windows are ready.
1225 *
1226 * This function returns FALSE if the new palette could not be
1227 * prepared, which should normally be a fatal error. XXX XXX
1228 *
1229 * Note that only some machines actually use a "palette".
1230 */
new_palette(void)1231 static int new_palette(void)
1232 {
1233 #ifdef USE_GRAPHICS
1234 HPALETTE hBmPal;
1235 #endif /* USE_GRAPHICS */
1236 HPALETTE hNewPal;
1237 HDC hdc;
1238 int i, nEntries;
1239 int pLogPalSize;
1240 LPLOGPALETTE pLogPal;
1241 LPPALETTEENTRY lppe;
1242
1243 term_data *td;
1244
1245
1246 /* This makes no sense */
1247 if (!paletted) return (TRUE);
1248
1249 /* No bitmap */
1250 lppe = NULL;
1251 nEntries = 0;
1252
1253 #ifdef USE_GRAPHICS
1254
1255 /* Check the bitmap palette */
1256 hBmPal = infGraph.hPalette;
1257
1258 /* Use the bitmap */
1259 if (hBmPal)
1260 {
1261 lppe = ralloc(256 * sizeof(PALETTEENTRY));
1262 nEntries = GetPaletteEntries(hBmPal, 0, 255, lppe);
1263 if ((nEntries == 0) || (nEntries > 220))
1264 {
1265 /* Warn the user */
1266 plog("Please switch to high- or true-color mode.");
1267
1268 /* Cleanup */
1269 free(lppe);
1270
1271 /* Fail */
1272 return (FALSE);
1273 }
1274 }
1275
1276 #endif /* USE_GRAPHICS */
1277
1278 /* Size of palette */
1279 pLogPalSize = sizeof(LOGPALETTE) + (nEntries + 16) * sizeof(PALETTEENTRY);
1280
1281 /* Allocate palette */
1282 pLogPal = (LPLOGPALETTE)ralloc(pLogPalSize);
1283
1284 /* Version */
1285 pLogPal->palVersion = 0x300;
1286
1287 /* Make room for bitmap and normal data */
1288 pLogPal->palNumEntries = nEntries + 16;
1289
1290 /* Save the bitmap data */
1291 for (i = 0; i < nEntries; i++)
1292 {
1293 pLogPal->palPalEntry[i] = lppe[i];
1294 }
1295
1296 /* Save the normal data */
1297 for (i = 0; i < 16; i++)
1298 {
1299 LPPALETTEENTRY p;
1300
1301 /* Access the entry */
1302 p = &(pLogPal->palPalEntry[i+nEntries]);
1303
1304 /* Save the colors */
1305 p->peRed = GetRValue(win_clr[i]);
1306 p->peGreen = GetGValue(win_clr[i]);
1307 p->peBlue = GetBValue(win_clr[i]);
1308
1309 #ifdef SUPPORT_GAMMA
1310
1311 if (gamma_correction > 0)
1312 {
1313 p->peRed = gamma_table[p->peRed];
1314 p->peGreen = gamma_table[p->peGreen];
1315 p->peBlue = gamma_table[p->peBlue];
1316 }
1317
1318 #endif /* SUPPORT_GAMMA */
1319
1320 /* Save the flags */
1321 p->peFlags = PC_NOCOLLAPSE;
1322 }
1323
1324 /* Free something */
1325 if (lppe) free(lppe);
1326
1327 /* Create a new palette, or fail */
1328 hNewPal = CreatePalette(pLogPal);
1329 if (!hNewPal) quit("Cannot create palette!");
1330
1331 /* Free the palette */
1332 free(pLogPal);
1333
1334 /* Main window */
1335 td = &data[0];
1336
1337 /* Realize the palette */
1338 hdc = GetDC(td->w);
1339 SelectPalette(hdc, hNewPal, 0);
1340 i = RealizePalette(hdc);
1341 ReleaseDC(td->w, hdc);
1342 if (i == 0) quit("Cannot realize palette!");
1343
1344 /* Sub-windows */
1345 for (i = 1; i < MAX_TERM_DATA; i++)
1346 {
1347 td = &data[i];
1348
1349 hdc = GetDC(td->w);
1350 SelectPalette(hdc, hNewPal, 0);
1351 ReleaseDC(td->w, hdc);
1352 }
1353
1354 /* Delete old palette */
1355 if (hPal) DeleteObject(hPal);
1356
1357 /* Save new palette */
1358 hPal = hNewPal;
1359
1360 /* Success */
1361 return (TRUE);
1362 }
1363
1364
1365 #ifdef USE_GRAPHICS
1366 /*
1367 * Initialize graphics
1368 */
init_graphics(void)1369 static bool init_graphics(void)
1370 {
1371 /* Initialize once */
1372 /* if (can_use_graphics != arg_graphics) */
1373 {
1374 char buf[1024];
1375 int wid, hgt;
1376 cptr name;
1377
1378 if (arg_graphics == GRAPHICS_DAVID_GERVAIS)
1379 {
1380 wid = 32;
1381 hgt = 32;
1382
1383 name = "32x32.bmp";
1384
1385 use_transparency = TRUE;
1386 }
1387 else if (arg_graphics == GRAPHICS_ADAM_BOLT)
1388 {
1389 wid = 16;
1390 hgt = 16;
1391
1392 name = "16X16.BMP";
1393
1394 use_transparency = TRUE;
1395 }
1396 else
1397 {
1398 wid = 8;
1399 hgt = 8;
1400
1401 name = "8X8.BMP";
1402 }
1403
1404 /* Access the bitmap file */
1405 path_make(buf, ANGBAND_DIR_XTRA_GRAF, name);
1406
1407 /* Load the bitmap or quit */
1408 if (!ReadDIB(data[0].w, buf, &infGraph))
1409 {
1410 plog_fmt("Cannot read bitmap file '%s'", name);
1411 return (FALSE);
1412 }
1413
1414 /* Save the new sizes */
1415 infGraph.CellWidth = wid;
1416 infGraph.CellHeight = hgt;
1417
1418 if (arg_graphics == GRAPHICS_ADAM_BOLT)
1419 {
1420 /* Access the mask file */
1421 path_make(buf, ANGBAND_DIR_XTRA_GRAF, "mask.bmp");
1422
1423 /* Load the bitmap or quit */
1424 if (!ReadDIB(data[0].w, buf, &infMask))
1425 {
1426 plog_fmt("Cannot read bitmap file '%s'", buf);
1427 return (FALSE);
1428 }
1429 }
1430 else if (arg_graphics == GRAPHICS_DAVID_GERVAIS)
1431 {
1432 /* Access the mask file */
1433 path_make(buf, ANGBAND_DIR_XTRA_GRAF, "mask32.bmp");
1434
1435 /* Load the bitmap or quit */
1436 if (!ReadDIB(data[0].w, buf, &infMask))
1437 {
1438 plog_fmt("Cannot read bitmap file '%s'", buf);
1439 return (FALSE);
1440 }
1441 }
1442
1443 /* Activate a palette */
1444 if (!new_palette())
1445 {
1446 /* Free bitmap XXX XXX XXX */
1447
1448 /* Oops */
1449 plog("Cannot activate palette!");
1450 return (FALSE);
1451 }
1452
1453 /* Graphics available */
1454 can_use_graphics = arg_graphics;
1455 }
1456
1457 /* Result */
1458 return (can_use_graphics);
1459 }
1460 #endif /* USE_GRAPHICS */
1461
1462
1463 #ifdef USE_SOUND
1464 /*
1465 * Initialize sound
1466 */
init_sound(void)1467 static bool init_sound(void)
1468 {
1469 /* Initialize once */
1470 if (!can_use_sound)
1471 {
1472 /* Load the prefs */
1473 load_sound_prefs();
1474
1475 /* Sound available */
1476 can_use_sound = TRUE;
1477 }
1478
1479 /* Result */
1480 return (can_use_sound);
1481 }
1482 #endif /* USE_SOUND */
1483
1484
1485 /*
1486 * Resize a window
1487 */
term_window_resize(const term_data * td)1488 static void term_window_resize(const term_data *td)
1489 {
1490 /* Require window */
1491 if (!td->w) return;
1492
1493 /* Resize the window */
1494 SetWindowPos(td->w, 0, 0, 0,
1495 td->size_wid, td->size_hgt,
1496 SWP_NOMOVE | SWP_NOZORDER);
1497
1498 /* Redraw later */
1499 InvalidateRect(td->w, NULL, TRUE);
1500 }
1501
1502
1503 /*
1504 * Force the use of a new "font file" for a term_data
1505 *
1506 * This function may be called before the "window" is ready
1507 *
1508 * This function returns zero only if everything succeeds.
1509 *
1510 * Note that the "font name" must be capitalized!!!
1511 */
term_force_font(term_data * td,cptr path)1512 static errr term_force_font(term_data *td, cptr path)
1513 {
1514 int i;
1515
1516 int wid, hgt;
1517
1518 char *base;
1519
1520 char buf[1024];
1521
1522
1523 /* Forget the old font (if needed) */
1524 if (td->font_id) DeleteObject(td->font_id);
1525
1526 /* Forget old font */
1527 if (td->font_file)
1528 {
1529 bool used = FALSE;
1530
1531 /* Scan windows */
1532 for (i = 0; i < MAX_TERM_DATA; i++)
1533 {
1534 /* Don't check when closing the application */
1535 if (!path) break;
1536
1537 /* Check "screen" */
1538 if ((td != &data[i]) &&
1539 (data[i].font_file) &&
1540 (streq(data[i].font_file, td->font_file)))
1541 {
1542 used = TRUE;
1543 }
1544 }
1545
1546 /* Remove unused font resources */
1547 if (!used) RemoveFontResource(td->font_file);
1548
1549 /* Free the old name */
1550 string_free(td->font_file);
1551
1552 /* Forget it */
1553 td->font_file = NULL;
1554 }
1555
1556
1557 /* No path given */
1558 if (!path) return (1);
1559
1560
1561 /* Local copy */
1562 strnfmt(buf, sizeof(buf), "%s", path);
1563
1564 /* Analyze font path */
1565 base = analyze_font(buf, &wid, &hgt);
1566
1567 /* Verify suffix */
1568 if (!suffix(base, ".FON")) return (1);
1569
1570 /* Verify file */
1571 if (!check_file(buf)) return (1);
1572
1573 /* Load the new font */
1574 if (!AddFontResource(buf)) return (1);
1575
1576 /* Save new font name */
1577 td->font_file = string_make(base);
1578
1579 /* Remove the "suffix" */
1580 base[strlen(base)-4] = '\0';
1581
1582 /* Create the font (using the 'base' of the font file name!) */
1583 td->font_id = CreateFont(hgt, wid, 0, 0, FW_DONTCARE, 0, 0, 0,
1584 ANSI_CHARSET, OUT_DEFAULT_PRECIS,
1585 CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
1586 FIXED_PITCH | FF_DONTCARE, base);
1587
1588 /* Hack -- Unknown size */
1589 if (!wid || !hgt)
1590 {
1591 HDC hdcDesktop;
1592 HFONT hfOld;
1593 TEXTMETRIC tm;
1594
1595 /* all this trouble to get the cell size */
1596 hdcDesktop = GetDC(HWND_DESKTOP);
1597 hfOld = SelectObject(hdcDesktop, td->font_id);
1598 GetTextMetrics(hdcDesktop, &tm);
1599 SelectObject(hdcDesktop, hfOld);
1600 ReleaseDC(HWND_DESKTOP, hdcDesktop);
1601
1602 /* Font size info */
1603 wid = tm.tmAveCharWidth;
1604 hgt = tm.tmHeight;
1605 }
1606
1607 /* Save the size info */
1608 td->font_wid = wid;
1609 td->font_hgt = hgt;
1610
1611 /* Success */
1612 return (0);
1613 }
1614
1615
1616
1617 /*
1618 * Allow the user to change the font for this window.
1619 */
term_change_font(term_data * td)1620 static void term_change_font(term_data *td)
1621 {
1622 OPENFILENAME ofn;
1623
1624 char tmp[1024] = "";
1625
1626 /* Extract a default if possible */
1627 if (td->font_file) strcpy(tmp, td->font_file);
1628
1629 /* Ask for a choice */
1630 memset(&ofn, 0, sizeof(ofn));
1631 ofn.lStructSize = sizeof(ofn);
1632 ofn.hwndOwner = data[0].w;
1633 ofn.lpstrFilter = "Angband Font Files (*.fon)\0*.fon\0";
1634 ofn.nFilterIndex = 1;
1635 ofn.lpstrFile = tmp;
1636 ofn.nMaxFile = 128;
1637 ofn.lpstrInitialDir = ANGBAND_DIR_XTRA_FONT;
1638 ofn.Flags = OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR;
1639 ofn.lpstrDefExt = "fon";
1640
1641 /* Force choice if legal */
1642 if (GetOpenFileName(&ofn))
1643 {
1644 /* Force the font */
1645 if (term_force_font(td, tmp))
1646 {
1647 /* Access the standard font file */
1648 path_make(tmp, ANGBAND_DIR_XTRA_FONT, "8X13.FON");
1649
1650 /* Force the use of that font */
1651 (void)term_force_font(td, tmp);
1652 }
1653
1654 /* Reset the tile info */
1655 td->tile_wid = td->font_wid;
1656 td->tile_hgt = td->font_hgt;
1657
1658 /* Analyze the font */
1659 term_getsize(td);
1660
1661 /* Resize the window */
1662 term_window_resize(td);
1663 }
1664 }
1665
1666
1667 static void windows_map_aux(void);
1668
1669
1670 /*
1671 * Hack -- redraw a term_data
1672 */
term_data_redraw(term_data * td)1673 static void term_data_redraw(term_data *td)
1674 {
1675 if (td->map_active)
1676 {
1677 /* Redraw the map */
1678 windows_map_aux();
1679 }
1680 else
1681 {
1682 /* Activate the term */
1683 Term_activate(&td->t);
1684
1685 /* Redraw the contents */
1686 Term_redraw();
1687
1688 /* Restore the term */
1689 Term_activate(term_screen);
1690 }
1691 }
1692
1693
1694 /*
1695 * Hack -- redraw a term_data
1696 */
term_data_redraw_section(term_data * td,int x1,int y1,int x2,int y2)1697 static void term_data_redraw_section(term_data *td, int x1, int y1, int x2, int y2)
1698 {
1699 /* Activate the term */
1700 Term_activate(&td->t);
1701
1702 /* Redraw the area */
1703 Term_redraw_section(x1, y1, x2, y2);
1704
1705 /* Restore the term */
1706 Term_activate(term_screen);
1707 }
1708
1709
1710
1711 /*** Function hooks needed by "Term" ***/
1712
1713
1714 #if 0
1715
1716 /*
1717 * Initialize a new Term
1718 */
1719 static void Term_init_win(term *t)
1720 {
1721 /* XXX Unused */
1722 }
1723
1724
1725 /*
1726 * Nuke an old Term
1727 */
1728 static void Term_nuke_win(term *t)
1729 {
1730 /* XXX Unused */
1731 }
1732
1733 #endif /* 0 */
1734
1735
1736 /*
1737 * Interact with the User
1738 */
Term_user_win(int n)1739 static errr Term_user_win(int n)
1740 {
1741 /* Unused parameter */
1742 (void)n;
1743
1744 /* Success */
1745 return (0);
1746 }
1747
1748
1749 /*
1750 * React to global changes
1751 */
Term_xtra_win_react(void)1752 static errr Term_xtra_win_react(void)
1753 {
1754 int i;
1755
1756
1757 /* Simple color */
1758 if (colors16)
1759 {
1760 /* Save the default colors */
1761 for (i = 0; i < 256; i++)
1762 {
1763 /* Simply accept the desired colors */
1764 win_pal[i] = angband_color_table[i][0];
1765 }
1766 }
1767
1768 /* Complex color */
1769 else
1770 {
1771 COLORREF code;
1772
1773 byte rv, gv, bv;
1774
1775 bool change = FALSE;
1776
1777 /* Save the default colors */
1778 for (i = 0; i < 256; i++)
1779 {
1780 /* Extract desired values */
1781 rv = angband_color_table[i][1];
1782 gv = angband_color_table[i][2];
1783 bv = angband_color_table[i][3];
1784
1785 #ifdef SUPPORT_GAMMA
1786
1787 if (gamma_correction > 0)
1788 {
1789 rv = gamma_table[rv];
1790 gv = gamma_table[gv];
1791 bv = gamma_table[bv];
1792 }
1793
1794 #endif /* SUPPORT_GAMMA */
1795
1796 /* Extract a full color code */
1797 code = PALETTERGB(rv, gv, bv);
1798
1799 /* Activate changes */
1800 if (win_clr[i] != code)
1801 {
1802 /* Note the change */
1803 change = TRUE;
1804
1805 /* Apply the desired color */
1806 win_clr[i] = code;
1807 }
1808 }
1809
1810 /* Activate the palette if needed */
1811 if (change) (void)new_palette();
1812 }
1813
1814
1815 #ifdef USE_SOUND
1816
1817 /* Handle "arg_sound" */
1818 if (use_sound != arg_sound)
1819 {
1820 /* Initialize (if needed) */
1821 if (arg_sound && !init_sound())
1822 {
1823 /* Warning */
1824 plog("Cannot initialize sound!");
1825
1826 /* Cannot enable */
1827 arg_sound = FALSE;
1828 }
1829
1830 /* Change setting */
1831 use_sound = arg_sound;
1832 }
1833
1834 #endif /* USE_SOUND */
1835
1836
1837 #ifdef USE_GRAPHICS
1838
1839 /* Handle "arg_graphics" */
1840 if (use_graphics != arg_graphics)
1841 {
1842 /* Switch off transparency */
1843 use_transparency = FALSE;
1844
1845 /* Free the bitmap stuff */
1846 FreeDIB(&infGraph);
1847 FreeDIB(&infMask);
1848
1849 /* Initialize (if needed) */
1850 if (arg_graphics && !init_graphics())
1851 {
1852 /* Warning */
1853 plog("Cannot initialize graphics!");
1854
1855 /* Cannot enable */
1856 arg_graphics = GRAPHICS_NONE;
1857 }
1858
1859 /* Change setting */
1860 use_graphics = arg_graphics;
1861
1862 /* Reset visuals */
1863 #ifdef ANGBAND_2_8_1
1864 reset_visuals();
1865 #else /* ANGBAND_2_8_1 */
1866 reset_visuals(TRUE);
1867 #endif /* ANGBAND_2_8_1 */
1868 }
1869
1870 #endif /* USE_GRAPHICS */
1871
1872
1873 /* Clean up windows */
1874 for (i = 0; i < MAX_TERM_DATA; i++)
1875 {
1876 term *old = Term;
1877
1878 term_data *td = &data[i];
1879
1880 /* Update resized windows */
1881 if ((td->cols != td->t.wid) || (td->rows != td->t.hgt))
1882 {
1883 /* Activate */
1884 Term_activate(&td->t);
1885
1886 /* Hack -- Resize the term */
1887 Term_resize(td->cols, td->rows);
1888
1889 /* Redraw the contents */
1890 Term_redraw();
1891
1892 /* Restore */
1893 Term_activate(old);
1894 }
1895 }
1896
1897
1898 /* Success */
1899 return (0);
1900 }
1901
1902
1903 /*
1904 * Process at least one event
1905 */
Term_xtra_win_event(int v)1906 static errr Term_xtra_win_event(int v)
1907 {
1908 MSG msg;
1909
1910 /* Wait for an event */
1911 if (v)
1912 {
1913 /* Block */
1914 if (GetMessage(&msg, NULL, 0, 0))
1915 {
1916 TranslateMessage(&msg);
1917 DispatchMessage(&msg);
1918 }
1919 }
1920
1921 /* Check for an event */
1922 else
1923 {
1924 /* Check */
1925 if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
1926 {
1927 TranslateMessage(&msg);
1928 DispatchMessage(&msg);
1929 }
1930 }
1931
1932 /* Success */
1933 return 0;
1934 }
1935
1936
1937 /*
1938 * Process all pending events
1939 */
Term_xtra_win_flush(void)1940 static errr Term_xtra_win_flush(void)
1941 {
1942 MSG msg;
1943
1944 /* Process all pending events */
1945 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
1946 {
1947 TranslateMessage(&msg);
1948 DispatchMessage(&msg);
1949 }
1950
1951 /* Success */
1952 return (0);
1953 }
1954
1955
1956 /*
1957 * Hack -- clear the screen
1958 *
1959 * Make this more efficient XXX XXX XXX
1960 */
Term_xtra_win_clear(void)1961 static errr Term_xtra_win_clear(void)
1962 {
1963 term_data *td = (term_data*)(Term->data);
1964
1965 HDC hdc;
1966 RECT rc;
1967
1968 /* Rectangle to erase */
1969 rc.left = td->size_ow1;
1970 rc.right = rc.left + td->cols * td->tile_wid;
1971 rc.top = td->size_oh1;
1972 rc.bottom = rc.top + td->rows * td->tile_hgt;
1973
1974 /* Erase it */
1975 hdc = GetDC(td->w);
1976 SetBkColor(hdc, RGB(0, 0, 0));
1977 SelectObject(hdc, td->font_id);
1978 ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1979 ReleaseDC(td->w, hdc);
1980
1981 /* Success */
1982 return 0;
1983 }
1984
1985
1986 /*
1987 * Hack -- make a noise
1988 */
Term_xtra_win_noise(void)1989 static errr Term_xtra_win_noise(void)
1990 {
1991 MessageBeep(MB_ICONASTERISK);
1992 return (0);
1993 }
1994
1995
1996 /*
1997 * Hack -- make a sound
1998 */
Term_xtra_win_sound(int v)1999 static errr Term_xtra_win_sound(int v)
2000 {
2001 #ifdef USE_SOUND
2002 int i;
2003 char buf[1024];
2004 #endif /* USE_SOUND */
2005
2006 /* Sound disabled */
2007 if (!use_sound) return (1);
2008
2009 /* Illegal sound */
2010 if ((v < 0) || (v >= SOUND_MAX)) return (1);
2011
2012 #ifdef USE_SOUND
2013
2014 /* Count the samples */
2015 for (i = 0; i < SAMPLE_MAX; i++)
2016 {
2017 if (!sound_file[v][i])
2018 break;
2019 }
2020
2021 /* No sample */
2022 if (i == 0) return (1);
2023
2024 /* Build the path */
2025 path_make(buf, ANGBAND_DIR_XTRA_SOUND, sound_file[v][Rand_simple(i)]);
2026
2027 #ifdef WIN32
2028
2029 /* Play the sound, catch errors */
2030 return (PlaySound(buf, 0, SND_FILENAME | SND_ASYNC));
2031
2032 #else /* WIN32 */
2033
2034 /* Play the sound, catch errors */
2035 return (sndPlaySound(buf, SND_ASYNC));
2036
2037 #endif /* WIN32 */
2038
2039 #else /* USE_SOUND */
2040
2041 /* Oops */
2042 return (1);
2043
2044 #endif /* USE_SOUND */
2045 }
2046
2047
2048 /*
2049 * Delay for "x" milliseconds
2050 */
Term_xtra_win_delay(int v)2051 static int Term_xtra_win_delay(int v)
2052 {
2053
2054 #ifdef WIN32
2055
2056 /* Sleep */
2057 if (v > 0) Sleep(v);
2058
2059 #else /* WIN32 */
2060
2061 DWORD t;
2062 MSG msg;
2063
2064 /* Final count */
2065 t = GetTickCount() + v;
2066
2067 /* Wait for it */
2068 while (GetTickCount() < t)
2069 {
2070 /* Handle messages */
2071 if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
2072 {
2073 TranslateMessage(&msg);
2074 DispatchMessage(&msg);
2075 }
2076 }
2077
2078 #endif /* WIN32 */
2079
2080 /* Success */
2081 return (0);
2082 }
2083
2084
2085 /*
2086 * Do a "special thing"
2087 */
Term_xtra_win(int n,int v)2088 static errr Term_xtra_win(int n, int v)
2089 {
2090 /* Handle a subset of the legal requests */
2091 switch (n)
2092 {
2093 /* Make a bell sound */
2094 case TERM_XTRA_NOISE:
2095 {
2096 return (Term_xtra_win_noise());
2097 }
2098
2099 /* Make a special sound */
2100 case TERM_XTRA_SOUND:
2101 {
2102 return (Term_xtra_win_sound(v));
2103 }
2104
2105 /* Process random events */
2106 case TERM_XTRA_BORED:
2107 {
2108 return (Term_xtra_win_event(0));
2109 }
2110
2111 /* Process an event */
2112 case TERM_XTRA_EVENT:
2113 {
2114 return (Term_xtra_win_event(v));
2115 }
2116
2117 /* Flush all events */
2118 case TERM_XTRA_FLUSH:
2119 {
2120 return (Term_xtra_win_flush());
2121 }
2122
2123 /* React to global changes */
2124 case TERM_XTRA_REACT:
2125 {
2126 return (Term_xtra_win_react());
2127 }
2128
2129 /* Delay for some milliseconds */
2130 case TERM_XTRA_DELAY:
2131 {
2132 return (Term_xtra_win_delay(v));
2133 }
2134 }
2135
2136 /* Oops */
2137 return 1;
2138 }
2139
2140 #if 0
2141 /*
2142 * Find the square a particular pixel is part of.
2143 */
2144 static void pixel_to_square(int *x, int *y, int ox, int oy)
2145 {
2146 term_data *td = (term_data*)(Term->data);
2147
2148 if (td->map_active)
2149 {
2150 (*x) = (ox - td->size_ow1) / td->map_tile_wid;
2151 (*y) = (oy - td->size_oh1) / td->map_tile_hgt;
2152 }
2153 else
2154 {
2155 (*x) = (ox - td->size_ow1) / td->tile_wid;
2156 (*y) = (oy - td->size_oh1) / td->tile_hgt;
2157
2158 if ((use_bigtile) && ((*y) >= Term->scr->big_y1)
2159 && ((*y) <= Term->scr->big_y2)
2160 && ((*x) >= Term->scr->big_x1))
2161 {
2162 (*x) -= ((*x) - Term->scr->big_x1 + 1) / 2;
2163 }
2164 }
2165 }
2166 #endif /* 0 */
2167
2168 /*
2169 * Find the pixel at the top-left corner of a square.
2170 */
square_to_pixel(int * x,int * y,int ox,int oy)2171 static void square_to_pixel(int *x, int *y, int ox, int oy)
2172 {
2173 term_data *td = (term_data*)(Term->data);
2174
2175 if (td->map_active)
2176 {
2177 (*x) = ox * td->map_tile_wid + td->size_ow1;
2178 (*y) = oy * td->map_tile_hgt + td->size_oh1;
2179 }
2180 else
2181 {
2182 (*y) = oy * td->tile_hgt + td->size_oh1;
2183
2184 if ((use_bigtile) && (oy >= Term->scr->big_y1)
2185 && (oy <= Term->scr->big_y2)
2186 && (ox > Term->scr->big_x1))
2187 {
2188 (*x) = ox * td->tile_wid * 2 + td->size_ow1 -
2189 Term->scr->big_x1 * td->tile_wid;
2190 }
2191 else
2192 {
2193 (*x) = ox * td->tile_wid + td->size_ow1;
2194 }
2195 }
2196 }
2197
2198 /*
2199 * Low level graphics (Assumes valid input).
2200 *
2201 * Draw a "cursor" at (x,y), using a "yellow box".
2202 */
Term_curs_win(int x,int y)2203 static errr Term_curs_win(int x, int y)
2204 {
2205 term_data *td = (term_data*)(Term->data);
2206
2207 RECT rc;
2208 HDC hdc;
2209
2210 int x1, y1;
2211 int tile_wid, tile_hgt;
2212
2213 /* Top left hand corner */
2214 square_to_pixel(&x1, &y1, x, y);
2215
2216 /* Frame the grid */
2217 rc.left = x1;
2218 rc.top = y1;
2219
2220 if (td->map_active)
2221 {
2222 tile_wid = td->map_tile_wid;
2223 tile_hgt = td->map_tile_hgt;
2224
2225 rc.right = rc.left + tile_wid;
2226 }
2227 else
2228 {
2229 tile_wid = td->tile_wid;
2230 tile_hgt = td->tile_hgt;
2231
2232 if (is_bigtiled(x, y))
2233 {
2234 rc.right = rc.left + tile_wid * 2;
2235 }
2236 else
2237 {
2238 rc.right = rc.left + tile_wid;
2239 }
2240 }
2241 rc.bottom = rc.top + tile_hgt;
2242
2243 /* Cursor is done as a yellow "box" */
2244 hdc = GetDC(td->w);
2245 FrameRect(hdc, &rc, hbrYellow);
2246 ReleaseDC(td->w, hdc);
2247
2248 /* Success */
2249 return 0;
2250 }
2251
2252
2253 /*
2254 *
2255 * Erase a "block" of "n" characters starting at (x,y).
2256 */
Term_wipe_win(int x,int y,int n)2257 static errr Term_wipe_win(int x, int y, int n)
2258 {
2259 term_data *td = (term_data*)(Term->data);
2260
2261 HDC hdc;
2262 RECT rc;
2263
2264 int x1, y1, x2, y2;
2265
2266 /*** Find the dimensions ***/
2267 square_to_pixel(&x1, &y1, x, y);
2268 square_to_pixel(&x2, &y2, x + n, y);
2269
2270 /* Rectangle to erase in client coords */
2271 rc.left = x1;
2272 rc.right = x2;
2273 rc.top = y1;
2274 rc.bottom = y1 + td->tile_hgt;
2275
2276 hdc = GetDC(td->w);
2277 SetBkColor(hdc, RGB(0, 0, 0));
2278 SelectObject(hdc, td->font_id);
2279 ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
2280 ReleaseDC(td->w, hdc);
2281
2282 /* Success */
2283 return 0;
2284 }
2285
2286
2287 /*
2288 * Low level graphics. Assumes valid input.
2289 *
2290 * Draw several ("n") chars, with an attr, at a given location.
2291 *
2292 * All "graphic" data is handled by "Term_pict_win()", below.
2293 *
2294 * One would think there is a more efficient method for telling a window
2295 * what color it should be using to draw with, but perhaps simply changing
2296 * it every time is not too inefficient. XXX XXX XXX
2297 */
Term_text_win(int cx,int cy,int n,byte a,cptr s)2298 static errr Term_text_win(int cx, int cy, int n, byte a, cptr s)
2299 {
2300 term_data *td = (term_data*)(Term->data);
2301 RECT rc;
2302 HDC hdc;
2303
2304 int i;
2305
2306 int x, y;
2307
2308 /* Acquire DC */
2309 hdc = GetDC(td->w);
2310
2311 /* Background color */
2312 SetBkColor(hdc, RGB(0, 0, 0));
2313
2314 /* Foreground color */
2315 if (colors16)
2316 {
2317 SetTextColor(hdc, PALETTEINDEX(win_pal[a]));
2318 }
2319 else if (paletted)
2320 {
2321 SetTextColor(hdc, win_clr[a&0x0F]);
2322 }
2323 else
2324 {
2325 SetTextColor(hdc, win_clr[a]);
2326 }
2327
2328 /* Use the font */
2329 SelectObject(hdc, td->font_id);
2330
2331 /* Erase complete rectangle */
2332 Term_wipe_win(cx, cy, n);
2333
2334 /* Get top left corner */
2335 square_to_pixel(&x, &y, cx, cy);
2336
2337 rc.top = y + ((td->tile_hgt - td->font_hgt) / 2);
2338 rc.bottom = rc.top + td->font_hgt;
2339
2340 /* Dump each character */
2341 for (i = 0; i < n; i++)
2342 {
2343 if (is_bigtiled(cx + i, cy))
2344 {
2345 rc.left = x + ((td->tile_wid - td->font_wid) / 2);
2346 rc.right = rc.left + td->font_wid;
2347
2348 /* Dump the text */
2349 ExtTextOut(hdc, rc.left, rc.top, 0, &rc,
2350 s+i, 1, NULL);
2351
2352 /* Advance */
2353 x += td->tile_wid * 2;
2354 }
2355 else
2356 {
2357 rc.left = x + ((td->tile_wid - td->font_wid) / 2);
2358 rc.right = rc.left + td->font_wid;
2359
2360 /* Dump the text */
2361 ExtTextOut(hdc, rc.left, rc.top, 0, &rc,
2362 s+i, 1, NULL);
2363
2364 /* Advance */
2365 x += td->tile_wid;
2366 }
2367 }
2368
2369 /* Release DC */
2370 ReleaseDC(td->w, hdc);
2371
2372 /* Success */
2373 return 0;
2374 }
2375
2376
2377 /*
2378 * Low level graphics. Assumes valid input.
2379 *
2380 * Draw an array of "special" attr/char pairs at the given location.
2381 *
2382 * We use the "Term_pict_win()" function for "graphic" data, which are
2383 * encoded by setting the "high-bits" of both the "attr" and the "char"
2384 * data. We use the "attr" to represent the "row" of the main bitmap,
2385 * and the "char" to represent the "col" of the main bitmap. The use
2386 * of this function is induced by the "higher_pict" flag.
2387 *
2388 * If "graphics" is not available, we simply "wipe" the given grids.
2389 */
Term_pict_win(int x,int y,int n,const byte * ap,const char * cp,const byte * tap,const char * tcp)2390 static errr Term_pict_win(int x, int y, int n, const byte *ap, const char *cp, const byte *tap, const char *tcp)
2391 {
2392 term_data *td = (term_data*)(Term->data);
2393
2394 #ifdef USE_GRAPHICS
2395
2396 int i;
2397 int x1, y1, w1, h1;
2398 int x2, y2, w2, h2, tw2;
2399 int x3, y3;
2400
2401 HDC hdcMask;
2402 HDC hdc;
2403 HDC hdcSrc;
2404 HBITMAP hbmSrcOld;
2405
2406 /* Paranoia */
2407 if (!use_graphics)
2408 {
2409 /* Erase the grids */
2410 return (Term_wipe_win(x, y, n));
2411 }
2412
2413 /* Size of bitmap cell */
2414 w1 = infGraph.CellWidth;
2415 h1 = infGraph.CellHeight;
2416
2417 /* Size of window cell */
2418 if (td->map_active)
2419 {
2420 w2 = td->map_tile_wid;
2421 h2 = td->map_tile_hgt;
2422 tw2 = w2;
2423 }
2424 else
2425 {
2426 w2 = td->tile_wid;
2427 h2 = td->tile_hgt;
2428
2429 /* big tile mode */
2430 if (use_bigtile)
2431 tw2 = 2 * w2;
2432 else
2433 tw2 = w2;
2434 }
2435
2436 /* Starting point */
2437 square_to_pixel(&x2, &y2, x, y);
2438
2439 /* Info */
2440 hdc = GetDC(td->w);
2441
2442 /* More info */
2443 hdcSrc = CreateCompatibleDC(hdc);
2444 hbmSrcOld = SelectObject(hdcSrc, infGraph.hBitmap);
2445
2446 if ((arg_graphics == GRAPHICS_ADAM_BOLT) ||
2447 (arg_graphics == GRAPHICS_DAVID_GERVAIS))
2448 {
2449 hdcMask = CreateCompatibleDC(hdc);
2450 SelectObject(hdcMask, infMask.hBitmap);
2451 }
2452 else
2453 {
2454 hdcMask = NULL;
2455 }
2456
2457 /* Draw attr/char pairs */
2458 for (i = 0; i < n; i++, x2 += w2)
2459 {
2460 byte a = ap[i];
2461 char c = cp[i];
2462
2463 /* Extract picture */
2464 int row = (a & 0x7F);
2465 int col = (c & 0x7F);
2466
2467 /* Location of bitmap cell */
2468 x1 = col * w1;
2469 y1 = row * h1;
2470
2471 if ((arg_graphics == GRAPHICS_ADAM_BOLT) ||
2472 (arg_graphics == GRAPHICS_DAVID_GERVAIS))
2473 {
2474 x3 = (tcp[i] & 0x7F) * w1;
2475 y3 = (tap[i] & 0x7F) * h1;
2476
2477 /* Perfect size */
2478 if ((w1 == tw2) && (h1 == h2))
2479 {
2480 /* Copy the terrain picture from the bitmap to the window */
2481 BitBlt(hdc, x2, y2, tw2, h2, hdcSrc, x3, y3, SRCCOPY);
2482
2483 /* Mask out the tile */
2484 BitBlt(hdc, x2, y2, tw2, h2, hdcMask, x1, y1, SRCAND);
2485
2486 /* Draw the tile */
2487 BitBlt(hdc, x2, y2, tw2, h2, hdcSrc, x1, y1, SRCPAINT);
2488 }
2489
2490 /* Need to stretch */
2491 else
2492 {
2493 /* Set the correct mode for stretching the tiles */
2494 SetStretchBltMode(hdc, COLORONCOLOR);
2495
2496 /* Copy the terrain picture from the bitmap to the window */
2497 StretchBlt(hdc, x2, y2, tw2, h2, hdcSrc, x3, y3, w1, h1, SRCCOPY);
2498
2499 /* Only draw if terrain and overlay are different */
2500 if ((x1 != x3) || (y1 != y3))
2501 {
2502 /* Mask out the tile */
2503 StretchBlt(hdc, x2, y2, tw2, h2, hdcMask, x1, y1, w1, h1, SRCAND);
2504
2505 /* Draw the tile */
2506 StretchBlt(hdc, x2, y2, tw2, h2, hdcSrc, x1, y1, w1, h1, SRCPAINT);
2507 }
2508 }
2509 }
2510 else
2511 {
2512 /* Perfect size */
2513 if ((w1 == tw2) && (h1 == h2))
2514 {
2515 /* Copy the picture from the bitmap to the window */
2516 BitBlt(hdc, x2, y2, tw2, h2, hdcSrc, x1, y1, SRCCOPY);
2517 }
2518
2519 /* Need to stretch */
2520 else
2521 {
2522 /* Set the correct mode for stretching the tiles */
2523 SetStretchBltMode(hdc, COLORONCOLOR);
2524
2525 /* Copy the picture from the bitmap to the window */
2526 StretchBlt(hdc, x2, y2, tw2, h2, hdcSrc, x1, y1, w1, h1, SRCCOPY);
2527 }
2528 }
2529 }
2530
2531 /* Release */
2532 SelectObject(hdcSrc, hbmSrcOld);
2533 DeleteDC(hdcSrc);
2534
2535 if ((arg_graphics == GRAPHICS_ADAM_BOLT) ||
2536 (arg_graphics == GRAPHICS_DAVID_GERVAIS))
2537 {
2538 /* Release */
2539 SelectObject(hdcMask, hbmSrcOld);
2540 DeleteDC(hdcMask);
2541 }
2542
2543 /* Release */
2544 ReleaseDC(td->w, hdc);
2545
2546 #else /* USE_GRAPHICS */
2547
2548 /* Just erase this grid */
2549 return (Term_wipe_win(x, y, n));
2550
2551 #endif /* USE_GRAPHICS */
2552
2553 /* Success */
2554 return 0;
2555 }
2556
2557
2558 static int player_x;
2559 static int player_y;
2560
2561 /*
2562 * Notice that the player has moved
2563 */
win_player_move(int x,int y,vptr dummy)2564 static void win_player_move(int x, int y, vptr dummy)
2565 {
2566 /* Hack - ignore parameter */
2567 (void) dummy;
2568
2569 /* Save for later */
2570 player_x = x;
2571 player_y = y;
2572 }
2573
2574
2575 /*
2576 * Save the information so we can access it later
2577 */
win_map_info(map_block * mb_ptr,const term_map * map,vptr dummy)2578 static void win_map_info(map_block *mb_ptr, const term_map *map, vptr dummy)
2579 {
2580 /* Hack -- ignore parameter */
2581 (void) dummy;
2582
2583 /* Store feature code for later */
2584 if (map->terrain)
2585 {
2586 mb_ptr->a = f_info[map->terrain].x_attr;
2587 mb_ptr->c = f_info[map->terrain].x_char;
2588 }
2589 else
2590 {
2591 mb_ptr->a = 0;
2592 mb_ptr->c = 0;
2593 }
2594 }
2595
windows_map_aux(void)2596 static void windows_map_aux(void)
2597 {
2598 term_data *td = &data[0];
2599 map_block *mb_ptr;
2600 byte a;
2601 char c;
2602 int x, y;
2603
2604 int min_x, min_y, max_x, max_y;
2605
2606 /* Get size */
2607 td->map_tile_wid = (td->tile_wid * td->cols) / MAX_WID;
2608 td->map_tile_hgt = (td->tile_hgt * td->rows) / MAX_HGT;
2609
2610 /* Get bounds */
2611 min_x = player_x - MAX_WID / 2;
2612 max_x = min_x + MAX_WID;
2613
2614 min_y = player_y - MAX_HGT / 2;
2615 max_y = player_y + MAX_HGT;
2616
2617 /* Draw the map */
2618 for (x = min_x; x < max_x; x++)
2619 {
2620 for (y = min_y; y < max_y; y++)
2621 {
2622 if (map_in_bounds(x, y))
2623 {
2624 mb_ptr = map_loc(x, y);
2625
2626 /* Attr / char */
2627 a = mb_ptr->a;
2628 c = mb_ptr->c;
2629
2630 /* Ignore non-graphics */
2631 if ((a & 0x80) && (c & 0x80))
2632 {
2633 Term_pict_win(x - min_x, y - min_y, 1, &a, &c, &a, &c);
2634 }
2635 }
2636 }
2637 }
2638
2639 /* Hilite the player */
2640 Term_curs_win(player_x - min_x, player_y - min_y);
2641 }
2642
2643
2644 /*
2645 * MEGA_HACK - Display a graphical map of the dungeon.
2646 */
windows_map(void)2647 static void windows_map(void)
2648 {
2649 term_data *td = &data[0];
2650 char ch;
2651
2652 /* Only in graphics mode since the fonts can't be scaled */
2653 if (!use_graphics) return;
2654
2655 /* Prevent various menu-actions from working */
2656 initialized = FALSE;
2657
2658 /* Clear screen */
2659 Term_xtra_win_clear();
2660
2661 td->map_active = TRUE;
2662
2663 /* Draw the map */
2664 windows_map_aux();
2665
2666 /* Wait for a keypress, flush key buffer */
2667 Term_inkey(&ch, TRUE, TRUE);
2668 Term_flush();
2669
2670 /* Switch off the map display */
2671 td->map_active = FALSE;
2672
2673 /* Restore screen */
2674 Term_xtra_win_clear();
2675 Term_redraw();
2676
2677 /* We are ready again */
2678 initialized = TRUE;
2679 }
2680
2681
2682 /*** Other routines ***/
2683
2684
2685 /*
2686 * Create and initialize a "term_data" given a title
2687 */
term_data_link(term_data * td)2688 static void term_data_link(term_data *td)
2689 {
2690 term *t = &td->t;
2691
2692 /* Initialize the term */
2693 term_init(t, td->cols, td->rows, td->keys);
2694
2695 /* Use a "software" cursor */
2696 t->soft_cursor = TRUE;
2697
2698 /* Use "Term_pict" for "graphic" data */
2699 t->higher_pict = TRUE;
2700
2701 /* Erase with "black space" */
2702 t->attr_blank = TERM_DARK;
2703 t->char_blank = ' ';
2704
2705 #if 0
2706 /* Prepare the init/nuke hooks */
2707 t->init_hook = Term_init_win;
2708 t->nuke_hook = Term_nuke_win;
2709 #endif /* 0 */
2710
2711 /* Prepare the template hooks */
2712 t->user_hook = Term_user_win;
2713 t->xtra_hook = Term_xtra_win;
2714 t->curs_hook = Term_curs_win;
2715 t->wipe_hook = Term_wipe_win;
2716 t->text_hook = Term_text_win;
2717 t->pict_hook = Term_pict_win;
2718
2719 /* Remember where we came from */
2720 t->data = (vptr)(td);
2721 }
2722
2723
2724 /*
2725 * Create the windows
2726 *
2727 * First, instantiate the "default" values, then read the "ini_file"
2728 * to over-ride selected values, then create the windows, and fonts.
2729 *
2730 * Must use SW_SHOW not SW_SHOWNA, since on 256 color display
2731 * must make active to realize the palette. XXX XXX XXX
2732 */
init_windows(void)2733 static void init_windows(void)
2734 {
2735 int i;
2736
2737 term_data *td;
2738
2739 char buf[1024];
2740
2741
2742 /* Main window */
2743 td = &data[0];
2744 WIPE(td, term_data);
2745 td->s = angband_term_name[0];
2746 td->keys = 1024;
2747 td->rows = 24;
2748 td->cols = 80;
2749 td->visible = TRUE;
2750 td->size_ow1 = 2;
2751 td->size_ow2 = 2;
2752 td->size_oh1 = 2;
2753 td->size_oh2 = 2;
2754 td->pos_x = 30;
2755 td->pos_y = 20;
2756
2757 /* Sub windows */
2758 for (i = 1; i < MAX_TERM_DATA; i++)
2759 {
2760 td = &data[i];
2761 WIPE(td, term_data);
2762 td->s = angband_term_name[i];
2763 td->keys = 16;
2764 td->rows = 24;
2765 td->cols = 80;
2766 td->visible = FALSE;
2767 td->size_ow1 = 1;
2768 td->size_ow2 = 1;
2769 td->size_oh1 = 1;
2770 td->size_oh2 = 1;
2771 td->pos_x = (7 - i) * 30;
2772 td->pos_y = (7 - i) * 20;
2773 }
2774
2775
2776 /* Load prefs */
2777 load_prefs();
2778
2779
2780 /* Main window (need these before term_getsize gets called) */
2781 td = &data[0];
2782 td->dwStyle = (WS_OVERLAPPED | WS_THICKFRAME | WS_SYSMENU |
2783 WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CAPTION |
2784 WS_VISIBLE);
2785 if (td->maximized) td->dwStyle |= WS_MAXIMIZE;
2786 td->dwExStyle = 0;
2787 td->visible = TRUE;
2788
2789 /* Sub windows (need these before term_getsize gets called) */
2790 for (i = 1; i < MAX_TERM_DATA; i++)
2791 {
2792 td = &data[i];
2793 td->dwStyle = (WS_OVERLAPPED | WS_THICKFRAME | WS_SYSMENU | WS_CAPTION);
2794 td->dwExStyle = (WS_EX_TOOLWINDOW);
2795 }
2796
2797
2798 /* All windows */
2799 for (i = 0; i < MAX_TERM_DATA; i++)
2800 {
2801 td = &data[i];
2802
2803 /* Access the standard font file */
2804 path_make(buf, ANGBAND_DIR_XTRA_FONT, td->font_want);
2805
2806 /* Activate the chosen font */
2807 if (term_force_font(td, buf))
2808 {
2809 /* Access the standard font file */
2810 path_make(buf, ANGBAND_DIR_XTRA_FONT, "8X13.FON");
2811
2812 /* Force the use of that font */
2813 (void)term_force_font(td, buf);
2814
2815 /* Oops */
2816 td->tile_wid = 8;
2817 td->tile_hgt = 13;
2818 }
2819
2820 /* Analyze the font */
2821 term_getsize(td);
2822
2823 /* Resize the window */
2824 term_window_resize(td);
2825 }
2826
2827
2828 /* Sub windows (reverse order) */
2829 for (i = MAX_TERM_DATA - 1; i >= 1; --i)
2830 {
2831 td = &data[i];
2832
2833 my_td = td;
2834 td->w = CreateWindowEx(td->dwExStyle, AngList,
2835 td->s, td->dwStyle,
2836 td->pos_x, td->pos_y,
2837 td->size_wid, td->size_hgt,
2838 HWND_DESKTOP, NULL, hInstance, NULL);
2839 my_td = NULL;
2840 if (!td->w) quit("Failed to create sub-window");
2841
2842 if (td->visible)
2843 {
2844 td->size_hack = TRUE;
2845 ShowWindow(td->w, SW_SHOW);
2846 td->size_hack = FALSE;
2847 }
2848
2849 term_data_link(td);
2850 angband_term[i] = &td->t;
2851
2852 if (td->visible)
2853 {
2854 /* Activate the window */
2855 SetActiveWindow(td->w);
2856
2857 /* Bring window to top */
2858 SetWindowPos(td->w, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
2859 }
2860 }
2861
2862
2863 /* Main window */
2864 td = &data[0];
2865
2866 /* Main window */
2867 my_td = td;
2868 td->w = CreateWindowEx(td->dwExStyle, AppName,
2869 td->s, td->dwStyle,
2870 td->pos_x, td->pos_y,
2871 td->size_wid, td->size_hgt,
2872 HWND_DESKTOP, NULL, hInstance, NULL);
2873 my_td = NULL;
2874 if (!td->w) quit_fmt("Failed to create %s window", VERSION_NAME);
2875
2876 term_data_link(td);
2877 term_screen = &td->t;
2878
2879 /* Activate the main window */
2880 SetActiveWindow(td->w);
2881
2882 /* Bring main window back to top */
2883 SetWindowPos(td->w, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
2884
2885 #ifdef SUPPORT_GAMMA
2886
2887 if (gamma_correction > 0)
2888 build_gamma_table(gamma_correction);
2889
2890 #endif /* SUPPORT_GAMMA */
2891
2892 /* New palette XXX XXX XXX */
2893 (void)new_palette();
2894
2895
2896 /* Create a "brush" for drawing the "cursor" */
2897 hbrYellow = CreateSolidBrush(win_clr[TERM_YELLOW]);
2898
2899
2900 /* Process pending messages */
2901 (void)Term_xtra_win_flush();
2902 }
2903
2904
2905 #ifdef USE_SAVER
2906
2907 /*
2908 * Stop the screensaver
2909 */
stop_screensaver(void)2910 static void stop_screensaver(void)
2911 {
2912 if (screensaver)
2913 SendMessage(data[0].w, WM_CLOSE, 0, 0);
2914 else
2915 SendMessage(data[0].w, WM_COMMAND, IDM_OPTIONS_SAVER, 0);
2916 }
2917
2918 #endif /* USE_SAVER */
2919
2920
2921 /*
2922 * Prepare the menus
2923 */
setup_menus(void)2924 static void setup_menus(void)
2925 {
2926 int i;
2927
2928 HMENU hm = GetMenu(data[0].w);
2929
2930 #ifdef USE_SAVER
2931 main_menu = hm;
2932 #endif /* USE_SAVER */
2933
2934 /* Menu "File", Disable all */
2935 EnableMenuItem(hm, IDM_FILE_NEW,
2936 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
2937 EnableMenuItem(hm, IDM_FILE_OPEN,
2938 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
2939 EnableMenuItem(hm, IDM_FILE_SAVE,
2940 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
2941 EnableMenuItem(hm, IDM_FILE_EXIT,
2942 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
2943 EnableMenuItem(hm, IDM_FILE_SCORE,
2944 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
2945
2946
2947 /* No character available */
2948 if (!character_generated)
2949 {
2950 /* Menu "File", Item "New" */
2951 EnableMenuItem(hm, IDM_FILE_NEW, MF_BYCOMMAND | MF_ENABLED);
2952
2953 /* Menu "File", Item "Open" */
2954 EnableMenuItem(hm, IDM_FILE_OPEN, MF_BYCOMMAND | MF_ENABLED);
2955 }
2956
2957 /* A character available */
2958 if (game_in_progress && character_generated && p_ptr->cmd.inkey_flag)
2959 {
2960 /* Menu "File", Item "Save" */
2961 EnableMenuItem(hm, IDM_FILE_SAVE, MF_BYCOMMAND | MF_ENABLED);
2962 }
2963
2964 if (!game_in_progress || !character_generated ||
2965 (p_ptr->cmd.inkey_flag))
2966 {
2967 /* Menu "File", Item "Exit" */
2968 EnableMenuItem(hm, IDM_FILE_EXIT, MF_BYCOMMAND | MF_ENABLED);
2969 }
2970
2971 if (initialized)
2972 {
2973 /* Menu "File", Item "Show Scores" */
2974 EnableMenuItem(hm, IDM_FILE_SCORE, MF_BYCOMMAND | MF_ENABLED);
2975 }
2976
2977
2978 /* Menu "Window::Visibility" */
2979 for (i = 0; i < MAX_TERM_DATA; i++)
2980 {
2981 EnableMenuItem(hm, IDM_WINDOW_VIS_0 + i,
2982 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
2983
2984 CheckMenuItem(hm, IDM_WINDOW_VIS_0 + i,
2985 (data[i].visible ? MF_CHECKED : MF_UNCHECKED));
2986
2987 EnableMenuItem(hm, IDM_WINDOW_VIS_0 + i,
2988 MF_BYCOMMAND | MF_ENABLED);
2989 }
2990
2991 /* Menu "Window::Font" */
2992 for (i = 0; i < MAX_TERM_DATA; i++)
2993 {
2994 EnableMenuItem(hm, IDM_WINDOW_FONT_0 + i,
2995 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
2996
2997 if (data[i].visible)
2998 {
2999 EnableMenuItem(hm, IDM_WINDOW_FONT_0 + i,
3000 MF_BYCOMMAND | MF_ENABLED);
3001 }
3002 }
3003
3004 /* Menu "Window::Increase Tile Width" */
3005 for (i = 0; i < MAX_TERM_DATA; i++)
3006 {
3007 EnableMenuItem(hm, IDM_WINDOW_I_WID_0 + i,
3008 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
3009
3010 if (data[i].visible)
3011 {
3012 EnableMenuItem(hm, IDM_WINDOW_I_WID_0 + i,
3013 MF_BYCOMMAND | MF_ENABLED);
3014
3015 }
3016 }
3017
3018 /* Menu "Window::Decrease Tile Width" */
3019 for (i = 0; i < MAX_TERM_DATA; i++)
3020 {
3021 EnableMenuItem(hm, IDM_WINDOW_D_WID_0 + i,
3022 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
3023
3024 if (data[i].visible)
3025 {
3026 EnableMenuItem(hm, IDM_WINDOW_D_WID_0 + i,
3027 MF_BYCOMMAND | MF_ENABLED);
3028
3029 }
3030 }
3031
3032 /* Menu "Window::Increase Tile Height" */
3033 for (i = 0; i < MAX_TERM_DATA; i++)
3034 {
3035 EnableMenuItem(hm, IDM_WINDOW_I_HGT_0 + i,
3036 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
3037
3038 if (data[i].visible)
3039 {
3040 EnableMenuItem(hm, IDM_WINDOW_I_HGT_0 + i,
3041 MF_BYCOMMAND | MF_ENABLED);
3042
3043 }
3044 }
3045
3046 /* Menu "Window::Decrease Tile Height" */
3047 for (i = 0; i < MAX_TERM_DATA; i++)
3048 {
3049 EnableMenuItem(hm, IDM_WINDOW_D_HGT_0 + i,
3050 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
3051
3052 if (data[i].visible)
3053 {
3054 EnableMenuItem(hm, IDM_WINDOW_D_HGT_0 + i,
3055 MF_BYCOMMAND | MF_ENABLED);
3056
3057 }
3058 }
3059
3060 /* Menu "Options", disable all */
3061 EnableMenuItem(hm, IDM_OPTIONS_GRAPHICS_NONE,
3062 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
3063 EnableMenuItem(hm, IDM_OPTIONS_GRAPHICS_OLD,
3064 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
3065 EnableMenuItem(hm, IDM_OPTIONS_GRAPHICS_ADAM,
3066 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
3067 EnableMenuItem(hm, IDM_OPTIONS_GRAPHICS_DAVID,
3068 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
3069 EnableMenuItem(hm, IDM_OPTIONS_BIGTILE,
3070 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
3071 EnableMenuItem(hm, IDM_OPTIONS_SOUND,
3072 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
3073 EnableMenuItem(hm, IDM_OPTIONS_SAVER,
3074 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
3075 EnableMenuItem(hm, IDM_OPTIONS_LOW_PRIORITY,
3076 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
3077
3078 /* Menu "Options", Item "Map" */
3079 if (p_ptr->cmd.inkey_flag && initialized && (use_graphics != GRAPHICS_NONE))
3080 EnableMenuItem(GetMenu(data[0].w), IDM_OPTIONS_MAP, MF_BYCOMMAND | MF_ENABLED);
3081 else
3082 EnableMenuItem(GetMenu(data[0].w), IDM_OPTIONS_MAP,
3083 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
3084
3085
3086 /* Menu "Options", update all */
3087 CheckMenuItem(hm, IDM_OPTIONS_GRAPHICS_NONE,
3088 (arg_graphics == GRAPHICS_NONE ? MF_CHECKED : MF_UNCHECKED));
3089 CheckMenuItem(hm, IDM_OPTIONS_GRAPHICS_OLD,
3090 (arg_graphics == GRAPHICS_ORIGINAL ? MF_CHECKED : MF_UNCHECKED));
3091 CheckMenuItem(hm, IDM_OPTIONS_GRAPHICS_ADAM,
3092 (arg_graphics == GRAPHICS_ADAM_BOLT ? MF_CHECKED : MF_UNCHECKED));
3093 CheckMenuItem(hm, IDM_OPTIONS_GRAPHICS_DAVID,
3094 (arg_graphics == GRAPHICS_DAVID_GERVAIS ? MF_CHECKED : MF_UNCHECKED));
3095
3096 CheckMenuItem(hm, IDM_OPTIONS_BIGTILE,
3097 (use_bigtile ? MF_CHECKED : MF_UNCHECKED));
3098 CheckMenuItem(hm, IDM_OPTIONS_SOUND,
3099 (arg_sound ? MF_CHECKED : MF_UNCHECKED));
3100 #ifdef USE_SAVER
3101 CheckMenuItem(hm, IDM_OPTIONS_SAVER,
3102 (hwndSaver ? MF_CHECKED : MF_UNCHECKED));
3103 #endif /* USE_SAVER */
3104
3105 CheckMenuItem(hm, IDM_OPTIONS_LOW_PRIORITY,
3106 (low_priority ? MF_CHECKED : MF_UNCHECKED));
3107
3108 #ifdef USE_GRAPHICS
3109 if (initialized && p_ptr->cmd.inkey_flag)
3110 {
3111 EnableMenuItem(hm, IDM_OPTIONS_GRAPHICS_NONE, MF_ENABLED);
3112 EnableMenuItem(hm, IDM_OPTIONS_GRAPHICS_OLD, MF_ENABLED);
3113 EnableMenuItem(hm, IDM_OPTIONS_GRAPHICS_ADAM, MF_ENABLED);
3114 EnableMenuItem(hm, IDM_OPTIONS_GRAPHICS_DAVID, MF_ENABLED);
3115 EnableMenuItem(hm, IDM_OPTIONS_BIGTILE, MF_ENABLED);
3116 }
3117 #endif /* USE_GRAPHICS */
3118
3119 #ifdef USE_SOUND
3120 if (initialized && p_ptr->cmd.inkey_flag)
3121 {
3122 /* Menu "Options", Item "Sound" */
3123 EnableMenuItem(hm, IDM_OPTIONS_SOUND, MF_ENABLED);
3124 }
3125 #endif /* USE_SOUND */
3126
3127 #ifdef USE_SAVER
3128 /* Menu "Options", Item "ScreenSaver" */
3129 EnableMenuItem(hm, IDM_OPTIONS_SAVER,
3130 MF_BYCOMMAND | MF_ENABLED);
3131 #endif /* USE_SAVER */
3132
3133 EnableMenuItem(hm, IDM_OPTIONS_LOW_PRIORITY,
3134 MF_BYCOMMAND | MF_ENABLED);
3135 }
3136
3137
3138 /*
3139 * Check for double clicked (or dragged) savefile
3140 *
3141 * Apparently, Windows copies the entire filename into the first
3142 * piece of the "command line string". Perhaps we should extract
3143 * the "basename" of that filename and append it to the "save" dir.
3144 */
check_for_save_file(LPSTR cmd_line)3145 static void check_for_save_file(LPSTR cmd_line)
3146 {
3147 char *s, *p;
3148
3149 /* First arg */
3150 s = cmd_line;
3151
3152 /* No args */
3153 if (!s || !*s) return;
3154
3155 /* Next arg */
3156 p = strchr(s, ' ');
3157
3158 /* Tokenize */
3159 if (p) *p = '\0';
3160
3161 /* Extract filename */
3162 *savefile = '\0';
3163 strncat(savefile, s, sizeof(savefile) - 1);
3164
3165 /* Validate the file */
3166 validate_file(savefile);
3167
3168 /* Game in progress */
3169 game_in_progress = TRUE;
3170
3171 Term_fresh();
3172
3173 /* Play game */
3174 play_game(FALSE);
3175
3176 /* Quit */
3177 quit(NULL);
3178 }
3179
3180
3181 #ifdef USE_SAVER
3182
3183 #ifdef ALLOW_BORG
3184
3185 /*
3186 * Hook into the inkey() function so that flushing keypresses
3187 * doesn't affect us.
3188 *
3189 * ToDo: Try to implement recording and playing back of games
3190 * by saving/reading the keypresses to/from a file. Note that
3191 * interrupting certain actions (resting, running, and other
3192 * repeated actions) would mess that up, so this would have to
3193 * be switched off when recording.
3194 */
3195
3196 extern char (*inkey_hack)(int flush_first);
3197
3198 static char screensaver_inkey_hack_buffer[1024];
3199
screensaver_inkey_hack(int flush_first)3200 static char screensaver_inkey_hack(int flush_first)
3201 {
3202 static int screensaver_inkey_hack_index = 0;
3203
3204 if (screensaver_inkey_hack_index < sizeof(screensaver_inkey_hack_buffer))
3205 return (screensaver_inkey_hack_buffer[screensaver_inkey_hack_index++]);
3206 else
3207 return ESCAPE;
3208 }
3209
3210 #endif /* ALLOW_BORG */
3211
3212
3213 /*
3214 * Start the screensaver
3215 */
start_screensaver(void)3216 static void start_screensaver(void)
3217 {
3218 bool file_exists;
3219
3220 #ifdef ALLOW_BORG
3221 int i, j;
3222 #endif /* ALLOW_BORG */
3223
3224 /* Set the name for process_player_name() */
3225 strnfmt(op_ptr->full_name, sizeof(op_ptr->full_name), "%s", saverfilename);
3226
3227 /* Set 'savefile' to a valid name */
3228 process_player_name(TRUE);
3229
3230 /* Does the savefile already exist? */
3231 file_exists = check_file(savefile);
3232
3233 /* Don't try to load a non-existant savefile */
3234 if (!file_exists) savefile[0] = '\0';
3235
3236 /* Game in progress */
3237 game_in_progress = TRUE;
3238
3239 Term_fresh();
3240
3241 /* Screensaver mode on */
3242 SendMessage(data[0].w, WM_COMMAND, IDM_OPTIONS_SAVER, 0);
3243
3244 /* Low priority */
3245 SendMessage(data[0].w, WM_COMMAND, IDM_OPTIONS_LOW_PRIORITY, 0);
3246
3247 #ifdef ALLOW_BORG
3248
3249 /*
3250 * MegaHack - Try to start the Borg.
3251 *
3252 * The simulated keypresses will be processed when play_game()
3253 * is called.
3254 */
3255
3256 inkey_hack = screensaver_inkey_hack;
3257 j = 0;
3258
3259 /*
3260 * If no savefile is present or then go through the steps necessary
3261 * to create a random character. If a savefile already is present
3262 * then the simulated keypresses will either clean away any [-more-]
3263 * prompts (if the character is alive), or create a new random
3264 * character.
3265 *
3266 * Luckily it's possible to send the same keypresses no matter if
3267 * the character is alive, dead, or not even yet created.
3268 */
3269 screensaver_inkey_hack_buffer[j++] = ESCAPE; /* Gender */
3270 screensaver_inkey_hack_buffer[j++] = ESCAPE; /* Race */
3271 screensaver_inkey_hack_buffer[j++] = ESCAPE; /* Class */
3272 screensaver_inkey_hack_buffer[j++] = ESCAPE; /* Modify options */
3273 screensaver_inkey_hack_buffer[j++] = ESCAPE; /* Reroll */
3274
3275 if (!file_exists)
3276 {
3277 /* Savefile name */
3278 int n = strlen(saverfilename);
3279 for (i = 0; i < n; i++)
3280 screensaver_inkey_hack_buffer[j++] = saverfilename[i];
3281 }
3282
3283 screensaver_inkey_hack_buffer[j++] = '\r'; /* Return */
3284 screensaver_inkey_hack_buffer[j++] = ESCAPE; /* Character info */
3285
3286 /*
3287 * Make sure the "verify_special" options is off, so that we can
3288 * get into Borg mode without confirmation.
3289 */
3290
3291 screensaver_inkey_hack_buffer[j++] = '='; /* Enter options screen */
3292 screensaver_inkey_hack_buffer[j++] = '2'; /* Disturbance options */
3293
3294 /* Cursor down to "verify_special" */
3295 for (i = 0; i < 10; i++)
3296 screensaver_inkey_hack_buffer[j++] = '2';
3297
3298 screensaver_inkey_hack_buffer[j++] = 'n'; /* Switch off "verify_special" */
3299 screensaver_inkey_hack_buffer[j++] = ESCAPE; /* Leave disturbance options */
3300
3301 /*
3302 * Make sure the "cheat_live" option is set, so that the Borg can
3303 * automatically restart.
3304 */
3305
3306 screensaver_inkey_hack_buffer[j++] = '6'; /* Cheat options */
3307
3308 /* Cursor down to "cheat live" */
3309 for (i = 0; i < OPT_cheat_live - OPT_CHEAT; i++)
3310 screensaver_inkey_hack_buffer[j++] = '2';
3311
3312 screensaver_inkey_hack_buffer[j++] = 'y'; /* Switch on "cheat_live" */
3313 screensaver_inkey_hack_buffer[j++] = ESCAPE; /* Leave cheat options */
3314 screensaver_inkey_hack_buffer[j++] = ESCAPE; /* Leave options */
3315
3316 /*
3317 * Now start the Borg!
3318 */
3319
3320 screensaver_inkey_hack_buffer[j++] = KTRL('Z'); /* Enter borgmode */
3321 screensaver_inkey_hack_buffer[j++] = 'z'; /* Run Borg */
3322 #endif /* ALLOW_BORG */
3323
3324 /* Play game */
3325 play_game((bool)!file_exists);
3326 }
3327
3328 #endif /* USE_SAVER */
3329
3330
3331 /*
3332 * Display a help file
3333 */
display_help(cptr filename)3334 static void display_help(cptr filename)
3335 {
3336 char tmp[1024];
3337
3338 path_make(tmp, ANGBAND_DIR_XTRA_HELP, filename);
3339
3340 if (check_file(tmp))
3341 {
3342 #ifdef HTML_HELP
3343
3344 HtmlHelp(data[0].w, tmp, HH_DISPLAY_TOPIC, 0);
3345
3346 #else /* HTML_HELP */
3347
3348 char buf[1024];
3349
3350 strnfmt(buf, 1024, "winhelp.exe %s", tmp);
3351 WinExec(buf, SW_NORMAL);
3352
3353 #endif /* HTML_HELP */
3354
3355 }
3356 else
3357 {
3358 plog_fmt("Cannot find help file: %s", tmp);
3359 plog("Use the online help files instead.");
3360 }
3361 }
3362
3363
3364 /*
3365 * Process a menu command
3366 */
process_menus(WORD wCmd)3367 static void process_menus(WORD wCmd)
3368 {
3369 int i;
3370
3371 term_data *td;
3372
3373 OPENFILENAME ofn;
3374
3375 /* Analyze */
3376 switch (wCmd)
3377 {
3378 /* New game */
3379 case IDM_FILE_NEW:
3380 {
3381 if (!initialized)
3382 {
3383 plog("You cannot do that yet...");
3384 }
3385 else if (game_in_progress)
3386 {
3387 plog("You can't start a new game while you're still playing!");
3388 }
3389 else
3390 {
3391 game_in_progress = TRUE;
3392 Term_flush();
3393 play_game(TRUE);
3394 quit(NULL);
3395 }
3396 break;
3397 }
3398
3399 /* Open game */
3400 case IDM_FILE_OPEN:
3401 {
3402 if (!initialized)
3403 {
3404 plog("You cannot do that yet...");
3405 }
3406 else if (game_in_progress)
3407 {
3408 plog("You can't open a new game while you're still playing!");
3409 }
3410 else
3411 {
3412 memset(&ofn, 0, sizeof(ofn));
3413 ofn.lStructSize = sizeof(ofn);
3414 ofn.hwndOwner = data[0].w;
3415 ofn.lpstrFilter = "Save Files (*.)\0*\0";
3416 ofn.nFilterIndex = 1;
3417 ofn.lpstrFile = savefile;
3418 ofn.nMaxFile = 1024;
3419 ofn.lpstrInitialDir = ANGBAND_DIR_SAVE;
3420 ofn.Flags = OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR;
3421
3422 if (GetOpenFileName(&ofn))
3423 {
3424 /* Load 'savefile' */
3425 validate_file(savefile);
3426 game_in_progress = TRUE;
3427 Term_flush();
3428 play_game(FALSE);
3429 quit(NULL);
3430 }
3431 }
3432 break;
3433 }
3434
3435 /* Save game */
3436 case IDM_FILE_SAVE:
3437 {
3438 if (game_in_progress && character_generated &&
3439 p_ptr->cmd.inkey_flag)
3440 {
3441 /* Hack -- Forget messages */
3442 msg_flag = FALSE;
3443
3444 /* Save the game */
3445 #ifdef ZANGBAND
3446 do_cmd_save_game(FALSE);
3447 #else /* ZANGBAND */
3448 do_cmd_save_game();
3449 #endif /* ZANGBAND */
3450 }
3451 else
3452 {
3453 /* Paranoia */
3454 plog("You may not do that right now.");
3455 }
3456 break;
3457 }
3458
3459 /* Show scores */
3460 case IDM_FILE_SCORE:
3461 {
3462 if (!initialized)
3463 {
3464 plog("You may not do that right now.");
3465 break;
3466 }
3467
3468 /* Show score */
3469 ingame_score(&initialized, game_in_progress);
3470
3471 break;
3472 }
3473
3474 /* Exit */
3475 case IDM_FILE_EXIT:
3476 {
3477 if (game_in_progress && character_generated)
3478 {
3479 /* Paranoia */
3480 if (!p_ptr->cmd.inkey_flag)
3481 {
3482 plog("You may not do that right now.");
3483 break;
3484 }
3485
3486 /* Hack -- Forget messages */
3487 msg_flag = FALSE;
3488
3489 /* Save the game */
3490 #ifdef ZANGBAND
3491 do_cmd_save_game(FALSE);
3492 #else /* ZANGBAND */
3493 do_cmd_save_game();
3494 #endif /* ZANGBAND */
3495 }
3496 quit(NULL);
3497 break;
3498 }
3499
3500 case IDM_WINDOW_VIS_0:
3501 {
3502 plog("You are not allowed to do that!");
3503
3504 break;
3505 }
3506
3507 /* Window visibility */
3508 case IDM_WINDOW_VIS_1:
3509 case IDM_WINDOW_VIS_2:
3510 case IDM_WINDOW_VIS_3:
3511 case IDM_WINDOW_VIS_4:
3512 case IDM_WINDOW_VIS_5:
3513 case IDM_WINDOW_VIS_6:
3514 case IDM_WINDOW_VIS_7:
3515 {
3516 i = wCmd - IDM_WINDOW_VIS_0;
3517
3518 if ((i < 0) || (i >= MAX_TERM_DATA)) break;
3519
3520 td = &data[i];
3521
3522 if (!td->visible)
3523 {
3524 td->visible = TRUE;
3525 ShowWindow(td->w, SW_SHOW);
3526 term_data_redraw(td);
3527 }
3528 else
3529 {
3530 td->visible = FALSE;
3531 ShowWindow(td->w, SW_HIDE);
3532 }
3533
3534 break;
3535 }
3536
3537 /* Window fonts */
3538 case IDM_WINDOW_FONT_0:
3539 case IDM_WINDOW_FONT_1:
3540 case IDM_WINDOW_FONT_2:
3541 case IDM_WINDOW_FONT_3:
3542 case IDM_WINDOW_FONT_4:
3543 case IDM_WINDOW_FONT_5:
3544 case IDM_WINDOW_FONT_6:
3545 case IDM_WINDOW_FONT_7:
3546 {
3547 i = wCmd - IDM_WINDOW_FONT_0;
3548
3549 if ((i < 0) || (i >= MAX_TERM_DATA)) break;
3550
3551 td = &data[i];
3552
3553 term_change_font(td);
3554
3555 break;
3556 }
3557
3558 /* Increase Tile Width */
3559 case IDM_WINDOW_I_WID_0:
3560 case IDM_WINDOW_I_WID_1:
3561 case IDM_WINDOW_I_WID_2:
3562 case IDM_WINDOW_I_WID_3:
3563 case IDM_WINDOW_I_WID_4:
3564 case IDM_WINDOW_I_WID_5:
3565 case IDM_WINDOW_I_WID_6:
3566 case IDM_WINDOW_I_WID_7:
3567 {
3568 i = wCmd - IDM_WINDOW_I_WID_0;
3569
3570 if ((i < 0) || (i >= MAX_TERM_DATA)) break;
3571
3572 td = &data[i];
3573
3574 td->tile_wid += 1;
3575
3576 term_getsize(td);
3577
3578 term_window_resize(td);
3579
3580 break;
3581 }
3582
3583 /* Decrease Tile Height */
3584 case IDM_WINDOW_D_WID_0:
3585 case IDM_WINDOW_D_WID_1:
3586 case IDM_WINDOW_D_WID_2:
3587 case IDM_WINDOW_D_WID_3:
3588 case IDM_WINDOW_D_WID_4:
3589 case IDM_WINDOW_D_WID_5:
3590 case IDM_WINDOW_D_WID_6:
3591 case IDM_WINDOW_D_WID_7:
3592 {
3593 i = wCmd - IDM_WINDOW_D_WID_0;
3594
3595 if ((i < 0) || (i >= MAX_TERM_DATA)) break;
3596
3597 td = &data[i];
3598
3599 td->tile_wid -= 1;
3600
3601 term_getsize(td);
3602
3603 term_window_resize(td);
3604
3605 break;
3606 }
3607
3608 /* Increase Tile Height */
3609 case IDM_WINDOW_I_HGT_0:
3610 case IDM_WINDOW_I_HGT_1:
3611 case IDM_WINDOW_I_HGT_2:
3612 case IDM_WINDOW_I_HGT_3:
3613 case IDM_WINDOW_I_HGT_4:
3614 case IDM_WINDOW_I_HGT_5:
3615 case IDM_WINDOW_I_HGT_6:
3616 case IDM_WINDOW_I_HGT_7:
3617 {
3618 i = wCmd - IDM_WINDOW_I_HGT_0;
3619
3620 if ((i < 0) || (i >= MAX_TERM_DATA)) break;
3621
3622 td = &data[i];
3623
3624 td->tile_hgt += 1;
3625
3626 term_getsize(td);
3627
3628 term_window_resize(td);
3629
3630 break;
3631 }
3632
3633 /* Decrease Tile Height */
3634 case IDM_WINDOW_D_HGT_0:
3635 case IDM_WINDOW_D_HGT_1:
3636 case IDM_WINDOW_D_HGT_2:
3637 case IDM_WINDOW_D_HGT_3:
3638 case IDM_WINDOW_D_HGT_4:
3639 case IDM_WINDOW_D_HGT_5:
3640 case IDM_WINDOW_D_HGT_6:
3641 case IDM_WINDOW_D_HGT_7:
3642 {
3643 i = wCmd - IDM_WINDOW_D_HGT_0;
3644
3645 if ((i < 0) || (i >= MAX_TERM_DATA)) break;
3646
3647 td = &data[i];
3648
3649 td->tile_hgt -= 1;
3650
3651 term_getsize(td);
3652
3653 term_window_resize(td);
3654
3655 break;
3656 }
3657
3658 case IDM_OPTIONS_GRAPHICS_NONE:
3659 {
3660 /* Paranoia */
3661 if (!p_ptr->cmd.inkey_flag || !initialized)
3662 {
3663 plog("You may not do that right now.");
3664 break;
3665 }
3666
3667 /* Toggle "arg_graphics" */
3668 if (arg_graphics != GRAPHICS_NONE)
3669 {
3670 arg_graphics = GRAPHICS_NONE;
3671
3672 /* React to changes */
3673 Term_xtra_win_react();
3674
3675 /* Hack -- Force redraw */
3676 Term_key_push(KTRL('R'));
3677 }
3678
3679 break;
3680 }
3681
3682 case IDM_OPTIONS_GRAPHICS_OLD:
3683 {
3684 /* Paranoia */
3685 if (!p_ptr->cmd.inkey_flag || !initialized)
3686 {
3687 plog("You may not do that right now.");
3688 break;
3689 }
3690
3691 /* Toggle "arg_graphics" */
3692 if (arg_graphics != GRAPHICS_ORIGINAL)
3693 {
3694 arg_graphics = GRAPHICS_ORIGINAL;
3695
3696 /* React to changes */
3697 Term_xtra_win_react();
3698
3699 /* Hack -- Force redraw */
3700 Term_key_push(KTRL('R'));
3701 }
3702
3703 break;
3704 }
3705
3706 case IDM_OPTIONS_GRAPHICS_ADAM:
3707 {
3708 /* Paranoia */
3709 if (!p_ptr->cmd.inkey_flag || !initialized)
3710 {
3711 plog("You may not do that right now.");
3712 break;
3713 }
3714
3715 /* Toggle "arg_graphics" */
3716 if (arg_graphics != GRAPHICS_ADAM_BOLT)
3717 {
3718 arg_graphics = GRAPHICS_ADAM_BOLT;
3719
3720 /* React to changes */
3721 Term_xtra_win_react();
3722
3723 /* Hack -- Force redraw */
3724 Term_key_push(KTRL('R'));
3725 }
3726
3727 break;
3728 }
3729
3730 case IDM_OPTIONS_GRAPHICS_DAVID:
3731 {
3732 /* Paranoia */
3733 if (!p_ptr->cmd.inkey_flag || !initialized)
3734 {
3735 plog("You may not do that right now.");
3736 break;
3737 }
3738
3739 /* Toggle "arg_graphics" */
3740 if (arg_graphics != GRAPHICS_DAVID_GERVAIS)
3741 {
3742 arg_graphics = GRAPHICS_DAVID_GERVAIS;
3743
3744 /* React to changes */
3745 Term_xtra_win_react();
3746
3747 /* Hack -- Force redraw */
3748 Term_key_push(KTRL('R'));
3749 }
3750
3751 break;
3752 }
3753
3754 case IDM_OPTIONS_BIGTILE:
3755 {
3756 /* Paranoia */
3757 if (!p_ptr->cmd.inkey_flag || !initialized)
3758 {
3759 plog("You may not do that right now.");
3760 break;
3761 }
3762
3763 /* Toggle "use_bigtile" */
3764 toggle_bigtile();
3765
3766 break;
3767 }
3768
3769
3770 case IDM_OPTIONS_SOUND:
3771 {
3772 /* Paranoia */
3773 if (!p_ptr->cmd.inkey_flag || !initialized)
3774 {
3775 plog("You may not do that right now.");
3776 break;
3777 }
3778
3779 /* Toggle "arg_sound" */
3780 arg_sound = !arg_sound;
3781
3782 /* React to changes */
3783 Term_xtra_win_react();
3784
3785 /* Hack -- Force redraw */
3786 Term_key_push(KTRL('R'));
3787
3788 break;
3789 }
3790
3791 #ifdef USE_SAVER
3792
3793 case IDM_OPTIONS_SAVER:
3794 {
3795 if (hwndSaver)
3796 {
3797 DestroyWindow(hwndSaver);
3798 hwndSaver = NULL;
3799 screensaver_active = FALSE;
3800
3801 /* Switch main menu back on */
3802 SetMenu(data[0].w, main_menu);
3803
3804 for (i = MAX_TERM_DATA - 1; i >= 0; --i)
3805 {
3806 td = &data[i];
3807
3808 if (td->visible)
3809 {
3810 /* Turn the Windows back to normal */
3811 SetWindowLong(td->w, GWL_STYLE, td->dwStyle);
3812
3813 /* Push the window to the top */
3814 SetWindowPos(td->w, HWND_NOTOPMOST, 0, 0, 0, 0,
3815 SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE);
3816 }
3817 }
3818
3819 ShowCursor(TRUE);
3820 }
3821 else
3822 {
3823 /* Create a screen saver window */
3824 hwndSaver = CreateWindowEx(WS_EX_TOPMOST, "WindowsScreenSaverClass",
3825 "Angband Screensaver",
3826 WS_POPUP | WS_MAXIMIZE | WS_VISIBLE,
3827 0, 0, GetSystemMetrics(SM_CXSCREEN),
3828 GetSystemMetrics(SM_CYSCREEN),
3829 NULL, NULL, hInstance, NULL);
3830
3831 if (hwndSaver)
3832 {
3833 for (i = MAX_TERM_DATA - 1; i >= 0; --i)
3834 {
3835 td = &data[i];
3836
3837 if (td->visible)
3838 {
3839 /* Switch off border and titlebar */
3840 SetWindowLong(td->w, GWL_STYLE, WS_VISIBLE);
3841
3842 /* Switch off menu */
3843 SetMenu(td->w, NULL);
3844
3845 /* Push the window to the top */
3846 SetWindowPos(td->w, HWND_TOPMOST, 0, 0, 0, 0,
3847 SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE);
3848 }
3849 }
3850
3851 ShowCursor(FALSE);
3852
3853 screensaver_active = TRUE;
3854 }
3855 else
3856 {
3857 plog("Failed to create saver window");
3858 }
3859 }
3860
3861 break;
3862 }
3863
3864 #endif /* USE_SAVER */
3865
3866 case IDM_OPTIONS_LOW_PRIORITY:
3867 {
3868 /* Lower or reset the priority of the current process */
3869 if (low_priority)
3870 SetPriorityClass(GetCurrentProcess(), IDLE_PRIORITY_CLASS);
3871 else
3872 SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
3873
3874 /* Toggle priority */
3875 low_priority = !low_priority;
3876
3877 break;
3878 }
3879
3880 case IDM_OPTIONS_MAP:
3881 {
3882 /* Paranoia */
3883 if (!p_ptr->cmd.inkey_flag || !initialized)
3884 {
3885 plog("You may not do that right now.");
3886 break;
3887 }
3888
3889 windows_map();
3890 break;
3891 }
3892
3893 case IDM_HELP_GENERAL:
3894 {
3895 display_help(HELP_GENERAL);
3896 break;
3897 }
3898
3899 case IDM_HELP_SPOILERS:
3900 {
3901 display_help(HELP_SPOILERS);
3902 break;
3903 }
3904 }
3905 }
3906
3907
3908 /*
3909 * Redraw a section of a window
3910 */
handle_wm_paint(HWND hWnd)3911 static void handle_wm_paint(HWND hWnd)
3912 {
3913 int x1, y1, x2, y2;
3914 PAINTSTRUCT ps;
3915 term_data *td;
3916
3917 /* Acquire proper "term_data" info */
3918 td = (term_data *)GetWindowLong(hWnd, 0);
3919
3920 BeginPaint(hWnd, &ps);
3921
3922 if (td->map_active)
3923 {
3924 /* Redraw the map */
3925 /* ToDo: Only redraw the necessary parts */
3926 windows_map_aux();
3927 }
3928 else
3929 {
3930 /* Get the area that should be updated (rounding up/down) */
3931 /* ToDo: Take the window borders into account */
3932 x1 = (ps.rcPaint.left / td->tile_wid) - 1;
3933 x2 = (ps.rcPaint.right / td->tile_wid) + 1;
3934 y1 = (ps.rcPaint.top / td->tile_hgt) - 1;
3935 y2 = (ps.rcPaint.bottom / td->tile_hgt) + 1;
3936
3937 /* Redraw */
3938 if (td) term_data_redraw_section(td, x1, y1, x2, y2);
3939 }
3940
3941 EndPaint(hWnd, &ps);
3942 }
3943
3944
AngbandWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)3945 static LRESULT FAR PASCAL AngbandWndProc(HWND hWnd, UINT uMsg,
3946 WPARAM wParam, LPARAM lParam)
3947 {
3948 HDC hdc;
3949 term_data *td;
3950 int i;
3951
3952 #ifdef USE_SAVER
3953 static int iMouse = 0;
3954 static WORD xMouse = 0;
3955 static WORD yMouse = 0;
3956
3957 int dx, dy;
3958 #endif /* USE_SAVER */
3959
3960 /* Acquire proper "term_data" info */
3961 td = (term_data *)GetWindowLong(hWnd, 0);
3962
3963 /* Handle message */
3964 switch (uMsg)
3965 {
3966 /* XXX XXX XXX */
3967 case WM_NCCREATE:
3968 {
3969 SetWindowLong(hWnd, 0, (LONG)(my_td));
3970 break;
3971 }
3972
3973 /* XXX XXX XXX */
3974 case WM_CREATE:
3975 {
3976 return 0;
3977 }
3978
3979 case WM_GETMINMAXINFO:
3980 {
3981 MINMAXINFO FAR *lpmmi;
3982 RECT rc;
3983
3984 lpmmi = (MINMAXINFO FAR *)lParam;
3985
3986 /* this message was sent before WM_NCCREATE */
3987 if (!td) return 1;
3988
3989 /* Minimum window size is 80x24 */
3990 rc.left = rc.top = 0;
3991 rc.right = rc.left + 80 * td->tile_wid + td->size_ow1 + td->size_ow2;
3992 rc.bottom = rc.top + 24 * td->tile_hgt + td->size_oh1 + td->size_oh2 + 1;
3993
3994 /* Adjust */
3995 AdjustWindowRectEx(&rc, td->dwStyle, TRUE, td->dwExStyle);
3996
3997 /* Save minimum size */
3998 lpmmi->ptMinTrackSize.x = rc.right - rc.left;
3999 lpmmi->ptMinTrackSize.y = rc.bottom - rc.top;
4000
4001 return 0;
4002 }
4003
4004 case WM_PAINT:
4005 {
4006 handle_wm_paint(hWnd);
4007
4008 return 0;
4009 }
4010
4011 case WM_SYSKEYDOWN:
4012 case WM_KEYDOWN:
4013 {
4014 bool mc = FALSE;
4015 bool ms = FALSE;
4016 bool ma = FALSE;
4017
4018 #ifdef USE_SAVER
4019 if (screensaver_active)
4020 {
4021 stop_screensaver();
4022 return 0;
4023 }
4024 #endif /* USE_SAVER */
4025
4026 /* Extract the modifiers */
4027 if (GetKeyState(VK_CONTROL) & 0x8000) mc = TRUE;
4028 if (GetKeyState(VK_SHIFT) & 0x8000) ms = TRUE;
4029 if (GetKeyState(VK_MENU) & 0x8000) ma = TRUE;
4030
4031 /* Handle "special" keys */
4032 if (special_key[(byte)(wParam)])
4033 {
4034 /* Begin the macro trigger */
4035 Term_keypress(31);
4036
4037 /* Send the modifiers */
4038 if (mc) Term_keypress('C');
4039 if (ms) Term_keypress('S');
4040 if (ma) Term_keypress('A');
4041
4042 /* Extract "scan code" */
4043 i = LOBYTE(HIWORD(lParam));
4044
4045 /* Introduce the scan code */
4046 Term_keypress('x');
4047
4048 /* Encode the hexidecimal scan code */
4049 Term_keypress(hexsym[i/16]);
4050 Term_keypress(hexsym[i%16]);
4051
4052 /* End the macro trigger */
4053 Term_keypress(13);
4054
4055 return 0;
4056 }
4057
4058 break;
4059 }
4060
4061 case WM_CHAR:
4062 {
4063 Term_keypress(wParam);
4064 return 0;
4065 }
4066
4067 #ifdef USE_SAVER
4068
4069 case WM_MBUTTONDOWN:
4070 case WM_RBUTTONDOWN:
4071 case WM_LBUTTONDOWN:
4072 {
4073 if (screensaver_active)
4074 {
4075 stop_screensaver();
4076 return 0;
4077 }
4078
4079 break;
4080 }
4081
4082 case WM_MOUSEMOVE:
4083 {
4084 if (!screensaver_active) break;
4085
4086 if (iMouse)
4087 {
4088 dx = LOWORD(lParam) - xMouse;
4089 dy = HIWORD(lParam) - yMouse;
4090
4091 if (dx < 0) dx = -dx;
4092 if (dy < 0) dy = -dy;
4093
4094 if ((dx > MOUSE_SENS) || (dy > MOUSE_SENS))
4095 {
4096 stop_screensaver();
4097 }
4098 }
4099
4100 /* Save last location */
4101 iMouse = 1;
4102 xMouse = LOWORD(lParam);
4103 yMouse = HIWORD(lParam);
4104
4105 return 0;
4106 }
4107 #endif /* USE_SAVER */
4108
4109 case WM_INITMENU:
4110 {
4111 setup_menus();
4112 return 0;
4113 }
4114
4115 case WM_CLOSE:
4116 {
4117 if (game_in_progress && character_generated)
4118 {
4119 if (!p_ptr->cmd.inkey_flag)
4120 {
4121 plog("You may not do that right now.");
4122 return 0;
4123 }
4124
4125 /* Hack -- Forget messages */
4126 msg_flag = FALSE;
4127
4128 /* Save the game */
4129 #ifdef ZANGBAND
4130 do_cmd_save_game(FALSE);
4131 #else /* ZANGBAND */
4132 do_cmd_save_game();
4133 #endif /* ZANGBAND */
4134 }
4135 quit(NULL);
4136 return 0;
4137 }
4138
4139 case WM_QUIT:
4140 {
4141 quit(NULL);
4142 return 0;
4143 }
4144
4145 case WM_COMMAND:
4146 {
4147 process_menus(LOWORD(wParam));
4148 return 0;
4149 }
4150
4151 case WM_SIZE:
4152 {
4153 /* this message was sent before WM_NCCREATE */
4154 if (!td) return 1;
4155
4156 /* it was sent from inside CreateWindowEx */
4157 if (!td->w) return 1;
4158
4159 /* was sent from WM_SIZE */
4160 if (td->size_hack) return 1;
4161
4162 switch (wParam)
4163 {
4164 case SIZE_MINIMIZED:
4165 {
4166 /* Hide sub-windows */
4167 for (i = 1; i < MAX_TERM_DATA; i++)
4168 {
4169 if (data[i].visible) ShowWindow(data[i].w, SW_HIDE);
4170 }
4171 return 0;
4172 }
4173
4174 case SIZE_MAXIMIZED:
4175 {
4176 /* fall through XXX XXX XXX */
4177 }
4178
4179 case SIZE_RESTORED:
4180 {
4181 int cols = (LOWORD(lParam) - td->size_ow1) / td->tile_wid;
4182 int rows = (HIWORD(lParam) - td->size_oh1) / td->tile_hgt;
4183
4184 /* New size */
4185 if ((td->cols != cols) || (td->rows != rows))
4186 {
4187 /* Save the new size */
4188 td->cols = cols;
4189 td->rows = rows;
4190
4191 /* Activate */
4192 Term_activate(&td->t);
4193
4194 /* Resize the term */
4195 Term_resize(td->cols, td->rows);
4196
4197 /* Redraw later */
4198 InvalidateRect(td->w, NULL, TRUE);
4199 }
4200
4201 td->size_hack = TRUE;
4202
4203 /* Show sub-windows */
4204 for (i = 1; i < MAX_TERM_DATA; i++)
4205 {
4206 if (data[i].visible) ShowWindow(data[i].w, SW_SHOW);
4207 }
4208
4209 td->size_hack = FALSE;
4210
4211 return 0;
4212 }
4213 }
4214 break;
4215 }
4216
4217 case WM_PALETTECHANGED:
4218 {
4219 /* Ignore if palette change caused by itself */
4220 if ((HWND)wParam == hWnd) return 0;
4221
4222 /* Fall through... */
4223 }
4224
4225 case WM_QUERYNEWPALETTE:
4226 {
4227 if (!paletted) return 0;
4228
4229 hdc = GetDC(hWnd);
4230
4231 SelectPalette(hdc, hPal, FALSE);
4232
4233 i = RealizePalette(hdc);
4234
4235 /* if any palette entries changed, repaint the window. */
4236 if (i) InvalidateRect(hWnd, NULL, TRUE);
4237
4238 ReleaseDC(hWnd, hdc);
4239
4240 return 0;
4241 }
4242
4243 case WM_ACTIVATE:
4244 {
4245 if (wParam && !HIWORD(lParam))
4246 {
4247 /* Do something to sub-windows */
4248 for (i = 1; i < MAX_TERM_DATA; i++)
4249 {
4250 SetWindowPos(data[i].w, hWnd, 0, 0, 0, 0,
4251 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
4252 }
4253
4254 /* Focus on main window */
4255 SetFocus(hWnd);
4256
4257 return 0;
4258 }
4259
4260 break;
4261 }
4262 }
4263
4264 return DefWindowProc(hWnd, uMsg, wParam, lParam);
4265 }
4266
4267
AngbandListProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)4268 static LRESULT FAR PASCAL AngbandListProc(HWND hWnd, UINT uMsg,
4269 WPARAM wParam, LPARAM lParam)
4270 {
4271 term_data *td;
4272 HDC hdc;
4273 int i;
4274
4275 #ifdef USE_SAVER
4276 static int iMouse = 0;
4277 static WORD xMouse = 0;
4278 static WORD yMouse = 0;
4279
4280 int dx, dy;
4281 #endif /* USE_SAVER */
4282
4283
4284 /* Acquire proper "term_data" info */
4285 td = (term_data *)GetWindowLong(hWnd, 0);
4286
4287 /* Process message */
4288 switch (uMsg)
4289 {
4290 /* XXX XXX XXX */
4291 case WM_NCCREATE:
4292 {
4293 SetWindowLong(hWnd, 0, (LONG)(my_td));
4294 break;
4295 }
4296
4297 /* XXX XXX XXX */
4298 case WM_CREATE:
4299 {
4300 return 0;
4301 }
4302
4303 case WM_GETMINMAXINFO:
4304 {
4305 #if 0
4306 MINMAXINFO FAR *lpmmi;
4307 RECT rc;
4308
4309 /* this message was sent before WM_NCCREATE */
4310 if (!td) return 1;
4311
4312 lpmmi = (MINMAXINFO FAR *)lParam;
4313
4314 /* Minimum size */
4315 rc.left = rc.top = 0;
4316 rc.right = rc.left + 8 * td->tile_wid + td->size_ow1 + td->size_ow2;
4317 rc.bottom = rc.top + 2 * td->tile_hgt + td->size_oh1 + td->size_oh2;
4318
4319 /* Adjust */
4320 AdjustWindowRectEx(&rc, td->dwStyle, TRUE, td->dwExStyle);
4321
4322 /* Save the minimum size */
4323 lpmmi->ptMinTrackSize.x = rc.right - rc.left;
4324 lpmmi->ptMinTrackSize.y = rc.bottom - rc.top;
4325
4326 /* Maximum window size */
4327 rc.left = rc.top = 0;
4328 rc.right = rc.left + 80 * td->tile_wid + td->size_ow1 + td->size_ow2;
4329 rc.bottom = rc.top + 24 * td->tile_hgt + td->size_oh1 + td->size_oh2;
4330
4331 /* Paranoia */
4332 rc.right += (td->tile_wid - 1);
4333 rc.bottom += (td->tile_hgt - 1);
4334
4335 /* Adjust */
4336 AdjustWindowRectEx(&rc, td->dwStyle, TRUE, td->dwExStyle);
4337
4338 /* Save maximum size */
4339 lpmmi->ptMaxSize.x = rc.right - rc.left;
4340 lpmmi->ptMaxSize.y = rc.bottom - rc.top;
4341
4342 /* Save the maximum size */
4343 lpmmi->ptMaxTrackSize.x = rc.right - rc.left;
4344 lpmmi->ptMaxTrackSize.y = rc.bottom - rc.top;
4345 #endif /* 0 */
4346 return 0;
4347 }
4348
4349 case WM_SIZE:
4350 {
4351 int cols;
4352 int rows;
4353
4354 /* this message was sent before WM_NCCREATE */
4355 if (!td) return 1;
4356
4357 /* it was sent from inside CreateWindowEx */
4358 if (!td->w) return 1;
4359
4360 /* was sent from inside WM_SIZE */
4361 if (td->size_hack) return 1;
4362
4363 td->size_hack = TRUE;
4364
4365 cols = (LOWORD(lParam) - td->size_ow1) / td->tile_wid;
4366 rows = (HIWORD(lParam) - td->size_oh1) / td->tile_hgt;
4367
4368 /* New size */
4369 if ((td->cols != cols) || (td->rows != rows))
4370 {
4371 /* Save old term */
4372 term *old_term = Term;
4373
4374 /* Save the new size */
4375 td->cols = cols;
4376 td->rows = rows;
4377
4378 /* Activate */
4379 Term_activate(&td->t);
4380
4381 /* Resize the term */
4382 Term_resize(td->cols, td->rows);
4383
4384 /* Activate */
4385 Term_activate(old_term);
4386
4387 /* Redraw later */
4388 InvalidateRect(td->w, NULL, TRUE);
4389
4390 /* HACK - Redraw all windows */
4391 p_ptr->window = 0xFFFFFFFF;
4392 window_stuff();
4393 }
4394
4395 td->size_hack = FALSE;
4396
4397 return 0;
4398 }
4399
4400 case WM_PAINT:
4401 {
4402 handle_wm_paint(hWnd);
4403
4404 return 0;
4405 }
4406
4407 case WM_SYSKEYDOWN:
4408 case WM_KEYDOWN:
4409 {
4410 bool mc = FALSE;
4411 bool ms = FALSE;
4412 bool ma = FALSE;
4413
4414 #ifdef USE_SAVER
4415 if (screensaver_active)
4416 {
4417 stop_screensaver();
4418 return 0;
4419 }
4420 #endif /* USE_SAVER */
4421
4422 /* Extract the modifiers */
4423 if (GetKeyState(VK_CONTROL) & 0x8000) mc = TRUE;
4424 if (GetKeyState(VK_SHIFT) & 0x8000) ms = TRUE;
4425 if (GetKeyState(VK_MENU) & 0x8000) ma = TRUE;
4426
4427 /* Handle "special" keys */
4428 if (special_key[(byte)(wParam)])
4429 {
4430 /* Begin the macro trigger */
4431 Term_keypress(31);
4432
4433 /* Send the modifiers */
4434 if (mc) Term_keypress('C');
4435 if (ms) Term_keypress('S');
4436 if (ma) Term_keypress('A');
4437
4438 /* Extract "scan code" */
4439 i = LOBYTE(HIWORD(lParam));
4440
4441 /* Introduce the scan code */
4442 Term_keypress('x');
4443
4444 /* Encode the hexidecimal scan code */
4445 Term_keypress(hexsym[i/16]);
4446 Term_keypress(hexsym[i%16]);
4447
4448 /* End the macro trigger */
4449 Term_keypress(13);
4450
4451 return 0;
4452 }
4453
4454 break;
4455 }
4456
4457 case WM_CHAR:
4458 {
4459 Term_keypress(wParam);
4460 return 0;
4461 }
4462
4463 #ifdef USE_SAVER
4464
4465 case WM_MBUTTONDOWN:
4466 case WM_RBUTTONDOWN:
4467 case WM_LBUTTONDOWN:
4468 {
4469 if (screensaver_active)
4470 {
4471 stop_screensaver();
4472 return 0;
4473 }
4474
4475 break;
4476 }
4477
4478 case WM_MOUSEMOVE:
4479 {
4480 if (!screensaver_active) break;
4481
4482 if (iMouse)
4483 {
4484 dx = LOWORD(lParam) - xMouse;
4485 dy = HIWORD(lParam) - yMouse;
4486
4487 if (dx < 0) dx = -dx;
4488 if (dy < 0) dy = -dy;
4489
4490 if ((dx > MOUSE_SENS) || (dy > MOUSE_SENS))
4491 {
4492 stop_screensaver();
4493 }
4494 }
4495
4496 /* Save last location */
4497 iMouse = 1;
4498 xMouse = LOWORD(lParam);
4499 yMouse = HIWORD(lParam);
4500
4501 return 0;
4502 }
4503 #endif /* USE_SAVER */
4504
4505 case WM_PALETTECHANGED:
4506 {
4507 /* ignore if palette change caused by itself */
4508 if ((HWND)wParam == hWnd) return FALSE;
4509 /* otherwise, fall through!!! */
4510 }
4511
4512 case WM_QUERYNEWPALETTE:
4513 {
4514 if (!paletted) return 0;
4515 hdc = GetDC(hWnd);
4516 SelectPalette(hdc, hPal, FALSE);
4517 i = RealizePalette(hdc);
4518 /* if any palette entries changed, repaint the window. */
4519 if (i) InvalidateRect(hWnd, NULL, TRUE);
4520 ReleaseDC(hWnd, hdc);
4521 return 0;
4522 }
4523
4524 case WM_NCLBUTTONDOWN:
4525 {
4526
4527 #ifdef HTCLOSE
4528 if (wParam == HTCLOSE) wParam = HTSYSMENU;
4529 #endif /* HTCLOSE */
4530
4531 if (wParam == HTSYSMENU)
4532 {
4533 if (td->visible)
4534 {
4535 td->visible = FALSE;
4536 ShowWindow(td->w, SW_HIDE);
4537 }
4538
4539 return 0;
4540 }
4541
4542 break;
4543 }
4544 }
4545
4546 return DefWindowProc(hWnd, uMsg, wParam, lParam);
4547 }
4548
4549
4550 #ifdef USE_SAVER
4551
AngbandSaverProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)4552 LRESULT FAR PASCAL AngbandSaverProc(HWND hWnd, UINT uMsg,
4553 WPARAM wParam, LPARAM lParam)
4554 {
4555 static int iMouse = 0;
4556 static WORD xMouse = 0;
4557 static WORD yMouse = 0;
4558
4559 int dx, dy;
4560
4561
4562 /* Process */
4563 switch (uMsg)
4564 {
4565 /* XXX XXX XXX */
4566 case WM_NCCREATE:
4567 {
4568 break;
4569 }
4570
4571 case WM_SETCURSOR:
4572 {
4573 SetCursor(NULL);
4574 return 0;
4575 }
4576
4577 #if 0
4578 case WM_ACTIVATE:
4579 {
4580 if (LOWORD(wParam) == WA_INACTIVE) break;
4581
4582 /* else fall through */
4583 }
4584 #endif /* 0 */
4585
4586 case WM_LBUTTONDOWN:
4587 case WM_MBUTTONDOWN:
4588 case WM_RBUTTONDOWN:
4589 case WM_KEYDOWN:
4590 {
4591 stop_screensaver();
4592 return 0;
4593 }
4594
4595 case WM_MOUSEMOVE:
4596 {
4597 if (iMouse)
4598 {
4599 dx = LOWORD(lParam) - xMouse;
4600 dy = HIWORD(lParam) - yMouse;
4601
4602 if (dx < 0) dx = -dx;
4603 if (dy < 0) dy = -dy;
4604
4605 if ((dx > MOUSE_SENS) || (dy > MOUSE_SENS))
4606 {
4607 stop_screensaver();
4608 }
4609 }
4610
4611 /* Save last location */
4612 iMouse = 1;
4613 xMouse = LOWORD(lParam);
4614 yMouse = HIWORD(lParam);
4615
4616 return 0;
4617 }
4618
4619 case WM_CLOSE:
4620 {
4621 DestroyWindow(hwndSaver);
4622 if (screensaver)
4623 SendMessage(data[0].w, WM_CLOSE, 0, 0);
4624 hwndSaver = NULL;
4625 return 0;
4626 }
4627 }
4628
4629 /* Oops */
4630 return DefWindowProc(hWnd, uMsg, wParam, lParam);
4631 }
4632
4633 #endif /* USE_SAVER */
4634
4635
4636
4637
4638
4639 /*** Temporary Hooks ***/
4640
4641
4642 /*
4643 * Display warning message (see "z-util.c")
4644 */
hack_plog(cptr str)4645 static void hack_plog(cptr str)
4646 {
4647 /* Give a warning */
4648 if (str)
4649 {
4650 MessageBox(NULL, str, "Warning",
4651 MB_ICONEXCLAMATION | MB_OK);
4652 }
4653 }
4654
4655
4656 /*
4657 * Display error message and quit (see "z-util.c")
4658 */
hack_quit(cptr str)4659 static void hack_quit(cptr str)
4660 {
4661 /* Give a warning */
4662 if (str)
4663 {
4664 MessageBox(NULL, str, "Error",
4665 MB_ICONEXCLAMATION | MB_OK | MB_ICONSTOP);
4666 }
4667
4668 /* Unregister the classes */
4669 UnregisterClass(AppName, hInstance);
4670
4671 /* Destroy the icon */
4672 if (hIcon) DestroyIcon(hIcon);
4673
4674 #ifdef USE_SAVER
4675 if (screensaverSemaphore) CloseHandle(screensaverSemaphore);
4676 #endif /* USE_SAVER */
4677
4678 /* Exit */
4679 exit(0);
4680 }
4681
4682
4683
4684 /*** Various hooks ***/
4685
4686
4687 /*
4688 * Display warning message (see "z-util.c")
4689 */
hook_plog(cptr str)4690 static void hook_plog(cptr str)
4691 {
4692 #ifdef USE_SAVER
4693 if (screensaver_active) return;
4694 #endif /* USE_SAVER */
4695
4696 /* Warning */
4697 if (str)
4698 {
4699 MessageBox(data[0].w, str, "Warning",
4700 MB_ICONEXCLAMATION | MB_OK);
4701 }
4702 }
4703
4704
4705 /*
4706 * Display error message and quit (see "z-util.c")
4707 */
hook_quit(cptr str)4708 static void hook_quit(cptr str)
4709 {
4710 int i;
4711
4712 #ifdef USE_SOUND
4713 int j;
4714 #endif /* USE_SOUND */
4715
4716
4717
4718 #ifdef USE_SAVER
4719 if (!screensaver_active)
4720 #endif /* USE_SAVER */
4721 {
4722 /* Give a warning */
4723 if (str)
4724 {
4725 MessageBox(data[0].w, str, "Error",
4726 MB_ICONEXCLAMATION | MB_OK | MB_ICONSTOP);
4727 }
4728
4729 /* Save the preferences */
4730 save_prefs();
4731 }
4732
4733 /*** Could use 'Term_nuke_win()' XXX XXX XXX */
4734
4735 /* Destroy all windows */
4736 for (i = MAX_TERM_DATA - 1; i >= 0; --i)
4737 {
4738 term_force_font(&data[i], NULL);
4739 if (data[i].font_want) string_free(data[i].font_want);
4740 if (data[i].w) DestroyWindow(data[i].w);
4741 data[i].w = 0;
4742
4743 term_nuke(&data[i].t);
4744 }
4745
4746 #ifdef USE_GRAPHICS
4747 /* Free the bitmap stuff */
4748 FreeDIB(&infGraph);
4749 FreeDIB(&infMask);
4750 #endif /* USE_GRAPHICS */
4751
4752 #ifdef USE_SOUND
4753 /* Free the sound names */
4754 for (i = 0; i < SOUND_MAX; i++)
4755 {
4756 for (j = 0; j < SAMPLE_MAX; j++)
4757 {
4758 if (!sound_file[i][j]) break;
4759
4760 string_free(sound_file[i][j]);
4761 }
4762 }
4763 #endif /* USE_SOUND */
4764
4765 /*** Free some other stuff ***/
4766
4767 DeleteObject(hbrYellow);
4768
4769 if (hPal) DeleteObject(hPal);
4770
4771 UnregisterClass(AppName, hInstance);
4772
4773 if (hIcon) DestroyIcon(hIcon);
4774
4775 /* Free strings */
4776 string_free(ini_file);
4777 string_free(argv0);
4778 string_free(ANGBAND_DIR_XTRA_FONT);
4779 string_free(ANGBAND_DIR_XTRA_GRAF);
4780 string_free(ANGBAND_DIR_XTRA_SOUND);
4781 string_free(ANGBAND_DIR_XTRA_HELP);
4782
4783 #ifdef USE_MUSIC
4784 string_free(ANGBAND_DIR_XTRA_MUSIC);
4785 #endif /* USE_MUSIC */
4786
4787 #ifdef HAS_CLEANUP
4788 cleanup_angband();
4789 #endif /* HAS_CLEANUP */
4790
4791 exit(0);
4792 }
4793
4794
4795
4796 /*** Initialize ***/
4797
4798
4799 /*
4800 * Init some stuff
4801 */
init_stuff(void)4802 static void init_stuff(void)
4803 {
4804 int i;
4805
4806 char path[1024];
4807 #ifdef USE_SAVER
4808 char tmp[1024];
4809 #endif /* USE_SAVER */
4810
4811 /* Get program name with full path */
4812 if (GetModuleFileName(hInstance, path, sizeof(path)) == 0)
4813 show_win_error();
4814
4815 /* Paranoia */
4816 path[sizeof(path) - 1] = '\0';
4817
4818 /* Save the "program name" */
4819 argv0 = string_make(path);
4820
4821 /* Get the name of the "*.ini" file */
4822 strcpy(path + strlen(path) - 4, ".INI");
4823
4824 #ifdef USE_SAVER
4825
4826 /* Try to get the path to the Angband folder */
4827 if (screensaver)
4828 {
4829 /* Extract the filename of the savefile for the screensaver */
4830 GetPrivateProfileString("Angband", "SaverFile", "", saverfilename, sizeof(saverfilename), path);
4831
4832 GetPrivateProfileString("Angband", "AngbandPath", "", tmp, sizeof(tmp), path);
4833
4834 strnmt(path, sizeof(path), "%szangband.ini", tmp);
4835 }
4836
4837 #endif /* USE_SAVER */
4838
4839 /* Save the the name of the ini-file */
4840 ini_file = string_make(path);
4841
4842 /* Analyze the path */
4843 i = strlen(path);
4844
4845 /* Get the path */
4846 for (; i > 0; i--)
4847 {
4848 if (path[i] == '\\')
4849 {
4850 /* End of path */
4851 break;
4852 }
4853 }
4854
4855 /* Add "lib" to the path */
4856 strcpy(path + i + 1, "lib\\");
4857
4858 /* Validate the path */
4859 validate_dir(path);
4860
4861 /* Init the file paths */
4862 init_file_paths(path);
4863
4864 /* Hack -- Validate the paths */
4865 validate_dir(ANGBAND_DIR_APEX);
4866 validate_dir(ANGBAND_DIR_BONE);
4867 validate_dir(ANGBAND_DIR_DATA);
4868 validate_dir(ANGBAND_DIR_EDIT);
4869
4870 validate_dir(ANGBAND_DIR_SCRIPT);
4871
4872 validate_dir(ANGBAND_DIR_FILE);
4873 validate_dir(ANGBAND_DIR_HELP);
4874 validate_dir(ANGBAND_DIR_INFO);
4875 validate_dir(ANGBAND_DIR_PREF);
4876 validate_dir(ANGBAND_DIR_SAVE);
4877 validate_dir(ANGBAND_DIR_USER);
4878 validate_dir(ANGBAND_DIR_XTRA);
4879
4880 /* Build the filename */
4881 path_make(path, ANGBAND_DIR_FILE, "news.txt");
4882
4883 /* Hack -- Validate the "news.txt" file */
4884 validate_file(path);
4885
4886
4887 /* Build the "font" path */
4888 path_make(path, ANGBAND_DIR_XTRA, "font");
4889
4890 /* Allocate the path */
4891 ANGBAND_DIR_XTRA_FONT = string_make(path);
4892
4893 /* Validate the "font" directory */
4894 validate_dir(ANGBAND_DIR_XTRA_FONT);
4895
4896 /* Build the filename */
4897 path_make(path, ANGBAND_DIR_XTRA_FONT, "8X13.FON");
4898
4899 /* Hack -- Validate the basic font */
4900 validate_file(path);
4901
4902
4903 #ifdef USE_GRAPHICS
4904
4905 /* Build the "graf" path */
4906 path_make(path, ANGBAND_DIR_XTRA, "graf");
4907
4908 /* Allocate the path */
4909 ANGBAND_DIR_XTRA_GRAF = string_make(path);
4910
4911 /* Validate the "graf" directory */
4912 validate_dir(ANGBAND_DIR_XTRA_GRAF);
4913
4914 #endif /* USE_GRAPHICS */
4915
4916
4917 #ifdef USE_SOUND
4918
4919 /* Build the "sound" path */
4920 path_make(path, ANGBAND_DIR_XTRA, "sound");
4921
4922 /* Allocate the path */
4923 ANGBAND_DIR_XTRA_SOUND = string_make(path);
4924
4925 /* Validate the "sound" directory */
4926 validate_dir(ANGBAND_DIR_XTRA_SOUND);
4927
4928 #endif /* USE_SOUND */
4929
4930 #ifdef USE_MUSIC
4931
4932 /* Build the "music" path */
4933 path_make(path, ANGBAND_DIR_XTRA, "music");
4934
4935 /* Allocate the path */
4936 ANGBAND_DIR_XTRA_MUSIC = string_make(path);
4937
4938 /* Validate the "music" directory */
4939 validate_dir(ANGBAND_DIR_XTRA_MUSIC);
4940
4941 #endif /* USE_MUSIC */
4942
4943 /* Build the "help" path */
4944 path_make(path, ANGBAND_DIR_XTRA, "help");
4945
4946 /* Allocate the path */
4947 ANGBAND_DIR_XTRA_HELP = string_make(path);
4948
4949 #if 0
4950 /* Validate the "help" directory */
4951 validate_dir(ANGBAND_DIR_XTRA_HELP);
4952 #endif /* 0 */
4953 }
4954
4955
4956 /*
4957 * Test to see if we need to work-around bugs in
4958 * the windows ascii-drawing routines.
4959 */
broken_ascii(void)4960 bool broken_ascii(void)
4961 {
4962 OSVERSIONINFO Dozeversion;
4963 Dozeversion.dwOSVersionInfoSize = sizeof(Dozeversion);
4964
4965 if (GetVersionEx(&Dozeversion))
4966 {
4967 /* Win XP is b0rken */
4968 if ((Dozeversion.dwPlatformId >= VER_PLATFORM_WIN32_NT) &&
4969 (Dozeversion.dwMajorVersion >= 5))
4970 {
4971 return (TRUE);
4972 }
4973 }
4974
4975 return (FALSE);
4976 }
4977
4978
4979
WinMain(HINSTANCE hInst,HINSTANCE hPrevInst,LPSTR lpCmdLine,int nCmdShow)4980 int FAR PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrevInst,
4981 LPSTR lpCmdLine, int nCmdShow)
4982 {
4983 int i;
4984
4985 WNDCLASS wc;
4986 HDC hdc;
4987 MSG msg;
4988
4989 /* Unused parameter */
4990 (void)nCmdShow;
4991
4992 #ifdef USE_SAVER
4993 if (lpCmdLine && ((*lpCmdLine == '-') || (*lpCmdLine == '/')))
4994 {
4995 lpCmdLine++;
4996
4997 switch (*lpCmdLine)
4998 {
4999 case 's':
5000 case 'S':
5001 {
5002 screensaver = TRUE;
5003
5004 /* Only run one screensaver at the time */
5005 screensaverSemaphore = CreateSemaphore(NULL, 0, 1, "AngbandSaverSemaphore");
5006
5007 if (!screensaverSemaphore) exit(0);
5008
5009 if (GetLastError() == ERROR_ALREADY_EXISTS)
5010 {
5011 CloseHandle(screensaverSemaphore);
5012 exit(0);
5013 }
5014
5015 break;
5016 }
5017
5018 case 'P':
5019 case 'p':
5020 case 'C':
5021 case 'c':
5022 case 'A':
5023 case 'a':
5024 {
5025 /*
5026 * ToDo: implement preview, configuration, and changing
5027 * the password (as well as checking it).
5028 */
5029 exit(0);
5030 }
5031 }
5032 }
5033
5034 #endif /* USE_SAVER */
5035
5036 /* Initialize */
5037 if (hPrevInst == NULL)
5038 {
5039 wc.style = CS_CLASSDC;
5040 wc.lpfnWndProc = AngbandWndProc;
5041 wc.cbClsExtra = 0;
5042 wc.cbWndExtra = 4; /* one long pointer to term_data */
5043 wc.hInstance = hInst;
5044 wc.hIcon = hIcon = LoadIcon(hInst, "ANGBAND");
5045 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
5046 wc.hbrBackground = GetStockObject(BLACK_BRUSH);
5047 wc.lpszMenuName = "ANGBAND";
5048 wc.lpszClassName = AppName;
5049
5050 if (!RegisterClass(&wc)) exit(1);
5051
5052 wc.lpfnWndProc = AngbandListProc;
5053 wc.lpszMenuName = NULL;
5054 wc.lpszClassName = AngList;
5055
5056 if (!RegisterClass(&wc)) exit(2);
5057
5058 #ifdef USE_SAVER
5059
5060 wc.style = CS_VREDRAW | CS_HREDRAW | CS_SAVEBITS | CS_DBLCLKS;
5061 wc.lpfnWndProc = AngbandSaverProc;
5062 wc.hCursor = NULL;
5063 wc.lpszMenuName = NULL;
5064 wc.lpszClassName = "WindowsScreenSaverClass";
5065
5066 if (!RegisterClass(&wc)) exit(3);
5067
5068 #endif /* USE_SAVER */
5069
5070 }
5071
5072 /* Save globally */
5073 hInstance = hInst;
5074
5075 /* Temporary hooks */
5076 plog_aux = hack_plog;
5077 quit_aux = hack_quit;
5078 core_aux = hack_quit;
5079
5080 /* Prepare the filepaths */
5081 init_stuff();
5082
5083 /* Initialize the keypress analyzer */
5084 for (i = 0; special_key_list[i]; i++)
5085 {
5086 special_key[special_key_list[i]] = TRUE;
5087 }
5088
5089 /* Determine if display is 16/256/true color */
5090 hdc = GetDC(NULL);
5091 colors16 = (GetDeviceCaps(hdc, BITSPIXEL) == 4);
5092 paletted = ((GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) ? TRUE : FALSE);
5093 ReleaseDC(NULL, hdc);
5094
5095 /* Initialize the colors */
5096 for (i = 0; i < 256; i++)
5097 {
5098 byte rv, gv, bv;
5099
5100 /* Extract desired values */
5101 rv = angband_color_table[i][1];
5102 gv = angband_color_table[i][2];
5103 bv = angband_color_table[i][3];
5104
5105 /* Extract the "complex" code */
5106 win_clr[i] = PALETTERGB(rv, gv, bv);
5107
5108 /* Save the "simple" code */
5109 angband_color_table[i][0] = win_pal[i];
5110 }
5111
5112 /* Prepare the windows */
5113 init_windows();
5114
5115 /* Activate hooks */
5116 plog_aux = hook_plog;
5117 quit_aux = hook_quit;
5118 core_aux = hook_quit;
5119
5120 /* Set the system suffix */
5121 ANGBAND_SYS = "win";
5122
5123 if (broken_ascii())
5124 {
5125 ANGBAND_SYS = "w2k";
5126 }
5127
5128 /* Initialize */
5129 init_angband();
5130
5131 /* We are now initialized */
5132 initialized = TRUE;
5133
5134 #ifdef USE_SAVER
5135 if (screensaver)
5136 {
5137 /* Start the screensaver */
5138 start_screensaver();
5139
5140 /* Paranoia */
5141 quit(NULL);
5142 }
5143 #endif /* USE_SAVER */
5144
5145 /* Did the user double click on a save file? */
5146 check_for_save_file(lpCmdLine);
5147
5148 /* Save the hooks into the overhead map */
5149 set_callback((callback_type) win_map_info, CALL_MAP_INFO, NULL);
5150
5151 /* Save player movement hook */
5152 set_callback((callback_type) win_player_move, CALL_PLAYER_MOVE, NULL);
5153
5154 /* Prompt the user */
5155 prtf(17, 23, "[Choose 'New' or 'Open' from the 'File' menu]");
5156 Term_fresh();
5157
5158 /* Process messages forever */
5159 while (GetMessage(&msg, NULL, 0, 0))
5160 {
5161 TranslateMessage(&msg);
5162 DispatchMessage(&msg);
5163 }
5164
5165 /* Paranoia */
5166 quit(NULL);
5167
5168 /* Paranoia */
5169 return (0);
5170 }
5171
5172 #endif /* WINDOWS */
5173