root/trunk/src/main-win.c

Revision 542, 96.0 kB (checked in by ajps, 9 months ago)

Split out ui-event and ui-menu from ui.c, partly in preparation for other ui-* files. Indulge in some renaming and recommenting of some data structures and things, e.g. event_type becomes ui_event_data, hopefully to distinguish it better from the game event stuff.

Line 
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@thangorodrim.net>.
72  */
73
74 #include "angband.h"
75 #define uint unsigned int
76
77 #if (defined(WINDOWS) && !defined(USE_SDL))
78
79
80 #define HAS_CLEANUP
81
82
83 /*
84  * Use HTML-Help.
85  */
86 /* #define HTML_HELP */
87
88 #ifdef HTML_HELP
89 # define HELP_GENERAL "angband.chm"
90 # define HELP_SPOILERS "angband.chm"
91 #else /* HTML_HELP */
92 # define HELP_GENERAL "angband.hlp"
93 # define HELP_SPOILERS "spoilers.hlp"
94 #endif /* HTML_HELP */
95
96
97
98 #ifdef ALLOW_BORG
99
100 /*
101  * Hack -- allow use of "screen saver" mode
102  */
103 #define USE_SAVER
104
105 #endif /* ALLOW_BORG */
106
107
108 /*
109  * Menu constants -- see "ANGBAND.RC"
110  */
111
112 #define IDM_FILE_NEW                    100
113 #define IDM_FILE_OPEN                   101
114 #define IDM_FILE_SAVE                   110
115 #define IDM_FILE_EXIT                   130
116
117 #define IDM_WINDOW_VIS_0                200
118 #define IDM_WINDOW_VIS_1                201
119 #define IDM_WINDOW_VIS_2                202
120 #define IDM_WINDOW_VIS_3                203
121 #define IDM_WINDOW_VIS_4                204
122 #define IDM_WINDOW_VIS_5                205
123 #define IDM_WINDOW_VIS_6                206
124 #define IDM_WINDOW_VIS_7                207
125
126 #define IDM_WINDOW_FONT_0               210
127 #define IDM_WINDOW_FONT_1               211
128 #define IDM_WINDOW_FONT_2               212
129 #define IDM_WINDOW_FONT_3               213
130 #define IDM_WINDOW_FONT_4               214
131 #define IDM_WINDOW_FONT_5               215
132 #define IDM_WINDOW_FONT_6               216
133 #define IDM_WINDOW_FONT_7               217
134
135 #define IDM_WINDOW_BIZ_0                230
136 #define IDM_WINDOW_BIZ_1                231
137 #define IDM_WINDOW_BIZ_2                232
138 #define IDM_WINDOW_BIZ_3                233
139 #define IDM_WINDOW_BIZ_4                234
140 #define IDM_WINDOW_BIZ_5                235
141 #define IDM_WINDOW_BIZ_6                236
142 #define IDM_WINDOW_BIZ_7                237
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_LOW_PRIORITY    420
186 #define IDM_OPTIONS_SAVER           430
187 #define IDM_OPTIONS_MAP             440
188
189 #define IDM_HELP_GENERAL                901
190 #define IDM_HELP_SPOILERS               902
191
192
193 /*
194  * This may need to be removed for some compilers XXX XXX XXX
195  */
196 #define STRICT
197
198 /*
199  * Exclude parts of WINDOWS.H that are not needed
200  */
201 #define NOCOMM            /* Comm driver APIs and definitions */
202 #define NOLOGERROR        /* LogError() and related definitions */
203 #define NOPROFILER        /* Profiler APIs */
204 #define NOLFILEIO         /* _l* file I/O routines */
205 #define NOOPENFILE        /* OpenFile and related definitions */
206 #define NORESOURCE        /* Resource management */
207 #define NOATOM            /* Atom management */
208 #define NOLANGUAGE        /* Character test routines */
209 #define NOLSTRING         /* lstr* string management routines */
210 #define NODBCS            /* Double-byte character set routines */
211 #define NOKEYBOARDINFO    /* Keyboard driver routines */
212 #define NOCOLOR           /* COLOR_* color values */
213 #define NODRAWTEXT        /* DrawText() and related definitions */
214 #define NOSCALABLEFONT    /* Truetype scalable font support */
215 #define NOMETAFILE        /* Metafile support */
216 #define NOSYSTEMPARAMSINFO /* SystemParametersInfo() and SPI_* definitions */
217 #define NODEFERWINDOWPOS  /* DeferWindowPos and related definitions */
218 #define NOKEYSTATES       /* MK_* message key state flags */
219 #define NOWH              /* SetWindowsHook and related WH_* definitions */
220 #define NOCLIPBOARD       /* Clipboard APIs and definitions */
221 #define NOICONS           /* IDI_* icon IDs */
222 #define NOMDI             /* MDI support */
223 #define NOHELP            /* Help support */
224
225 /* Not defined since it breaks Borland C++ 5.5 */
226 /* #define NOCTLMGR */    /* Control management and controls */
227
228 /*
229  * Exclude parts of WINDOWS.H that are not needed (Win32)
230  */
231 #define WIN32_LEAN_AND_MEAN
232 #define NONLS             /* All NLS defines and routines */
233 #define NOSERVICE         /* All Service Controller routines, SERVICE_ equates, etc. */
234 #define NOKANJI           /* Kanji support stuff. */
235 #define NOMCX             /* Modem Configuration Extensions */
236
237 /*
238  * Include the "windows" support file
239  */
240 #include <windows.h>
241 #include <windowsx.h>
242
243 #ifdef USE_SOUND
244
245 /*
246  * Exclude parts of MMSYSTEM.H that are not needed
247  */
248 #define MMNODRV          /* Installable driver support */
249 #define MMNOWAVE         /* Waveform support */
250 #define MMNOMIDI         /* MIDI support */
251 #define MMNOAUX          /* Auxiliary audio support */
252 #define MMNOTIMER        /* Timer support */
253 #define MMNOJOY          /* Joystick support */
254 #define MMNOMCI          /* MCI support */
255 #define MMNOMMIO         /* Multimedia file I/O support */
256 #define MMNOMMSYSTEM     /* General MMSYSTEM functions */
257
258 #include <mmsystem.h>
259
260 #endif /* USE_SOUND */
261
262 #include <commdlg.h>
263 #include <shellapi.h>
264
265 /*
266  * Include the support for loading bitmaps
267  */
268 #ifdef USE_GRAPHICS
269 # include "win/readdib.h"
270 #endif /* USE_GRAPHICS */
271
272 /*
273  * Hack -- Fake declarations from "dos.h" XXX XXX XXX
274  */
275 #define INVALID_FILE_NAME (DWORD)0xFFFFFFFF
276
277 /*
278  * Silliness in WIN32 drawing routine
279  */
280 #define MoveTo(H,X,Y) MoveToEx(H, X, Y, NULL)
281
282 /*
283  * Silliness for Windows 95
284  */
285 #ifndef WS_EX_TOOLWINDOW
286 # define WS_EX_TOOLWINDOW 0
287 #endif /* WS_EX_TOOLWINDOW */
288
289 /*
290  * Foreground color bits (hard-coded by DOS)
291  */
292 #define VID_BLACK       0x00
293 #define VID_BLUE        0x01
294 #define VID_GREEN       0x02
295 #define VID_CYAN        0x03
296 #define VID_RED         0x04
297 #define VID_MAGENTA     0x05
298 #define VID_YELLOW      0x06
299 #define VID_WHITE       0x07
300
301 /*
302  * Bright text (hard-coded by DOS)
303  */
304 #define VID_BRIGHT      0x08
305
306 /*
307  * Background color bits (hard-coded by DOS)
308  */
309 #define VUD_BLACK       0x00
310 #define VUD_BLUE        0x10
311 #define VUD_GREEN       0x20
312 #define VUD_CYAN        0x30
313 #define VUD_RED         0x40
314 #define VUD_MAGENTA     0x50
315 #define VUD_YELLOW      0x60
316 #define VUD_WHITE       0x70
317
318 /*
319  * Blinking text (hard-coded by DOS)
320  */
321 #define VUD_BRIGHT      0x80
322
323 /*
324  * Font settings
325  */
326 #define DEFAULT_FONT    "8X13.FON"
327
328
329
330 /*
331  * Forward declare
332  */
333 typedef struct _term_data term_data;
334
335 /*
336  * Extra "term" data
337  *
338  * Note the use of "font_want" for the names of the font file requested by
339  * the user, and the use of "font_file" for the currently active font file.
340  *
341  * The "font_file" is uppercased, and takes the form "8X13.FON", while
342  * "font_want" can be in almost any form as long as it could be construed
343  * as attempting to represent the name of a font.
344  */
345 struct _term_data
346 {
347         term t;
348
349         cptr s;
350
351         HWND w;
352
353         DWORD dwStyle;
354         DWORD dwExStyle;
355
356         uint keys;
357
358         byte rows;
359         byte cols;
360
361         uint pos_x;
362         uint pos_y;
363         uint size_wid;
364         uint size_hgt;
365         uint size_ow1;
366         uint size_oh1;
367         uint size_ow2;
368         uint size_oh2;
369
370         bool size_hack;
371
372         bool xtra_hack;
373
374         bool visible;
375         bool maximized;
376
377         bool bizarre;
378
379         char *font_want;
380         char *font_file;
381
382         HFONT font_id;
383
384         uint font_wid;
385         uint font_hgt;
386
387         uint tile_wid;
388         uint tile_hgt;
389
390         uint map_tile_wid;
391         uint map_tile_hgt;
392
393         bool map_active;
394 };
395
396
397 /*
398  * Maximum number of windows XXX XXX XXX
399  */
400 #define MAX_TERM_DATA 8
401
402
403 /*
404  * An array of term_data's
405  */
406 static term_data data[MAX_TERM_DATA];
407
408 /*
409  * Hack -- global "window creation" pointer
410  */
411 static term_data *my_td;
412
413 /*
414  * game in progress
415  */
416 bool game_in_progress = FALSE;
417
418 /*
419  * note when "open"/"new" become valid
420  */
421 bool initialized = FALSE;
422
423 /*
424  * screen paletted, i.e. 256 colors
425  */
426 bool paletted = FALSE;
427
428 /*
429  * 16 colors screen, don't use RGB()
430  */
431 bool colors16 = FALSE;
432
433 static bool low_priority = FALSE;
434
435 /*
436  * Saved instance handle
437  */
438 static HINSTANCE hInstance;
439
440 /*
441  * Yellow brush for the cursor
442  */
443 static HBRUSH hbrYellow;
444
445 /*
446  * An icon
447  */
448 static HICON hIcon;
449
450 /*
451  * A palette
452  */
453 static HPALETTE hPal;
454
455
456 #ifdef USE_SAVER
457
458 /*
459  * The screen saver window
460  */
461 static HWND hwndSaver;
462
463 static bool screensaver = FALSE;
464 static bool screensaver_active = FALSE;
465
466 static HANDLE screensaverSemaphore;
467
468 static char saverfilename[1024];
469
470 static HMENU main_menu;
471
472 #define MOUSE_SENS 10
473
474 #endif /* USE_SAVER */
475
476
477 #ifdef USE_GRAPHICS
478
479 /*
480  * Flag set once "graphics" has been initialized
481  */
482 static bool can_use_graphics = FALSE;
483
484 /*
485  * The global bitmap
486  */
487 static DIBINIT infGraph;
488
489 /*
490  * The global bitmap mask
491  */
492 static DIBINIT infMask;
493
494 #endif /* USE_GRAPHICS */
495
496
497 #ifdef USE_SOUND
498
499 /*
500  * Flag set once "sound" has been initialized
501  */
502 static bool can_use_sound = FALSE;
503
504 #define SAMPLE_MAX 16
505
506 /*
507  * An array of sound file names
508  */
509 static char *sound_file[MSG_MAX][SAMPLE_MAX];
510
511 #endif /* USE_SOUND */
512
513
514 /*
515  * Full path to ANGBAND.INI
516  */
517 static char *ini_file = NULL;
518
519 /*
520  * Name of application
521  */
522 static cptr AppName = VERSION_NAME;
523
524 /*
525  * Name of sub-window type
526  */
527 static cptr AngList = "AngList";
528
529 /*
530  * Directory names
531  */
532 static char *ANGBAND_DIR_XTRA_FONT;
533 static char *ANGBAND_DIR_XTRA_GRAF;
534 static char *ANGBAND_DIR_XTRA_SOUND;
535 static char *ANGBAND_DIR_XTRA_HELP;
536
537 /*
538  * The "complex" color values
539  */
540 static COLORREF win_clr[MAX_COLORS];
541
542
543 /*
544  * The "simple" color values
545  *
546  * See "main-ibm.c" for original table information
547  *
548  * The entries below are taken from the "color bits" defined above.
549  *
550  * Note that many of the choices below suck, but so do crappy monitors.
551  */
552 static byte win_pal[MAX_COLORS] =
553 {
554         VID_BLACK,                                      /* Dark */
555         VID_WHITE,                                      /* White */
556         VID_CYAN,                                       /* Slate XXX */
557         VID_RED | VID_BRIGHT,           /* Orange XXX */
558         VID_RED,                                        /* Red */
559         VID_GREEN,                                      /* Green */
560         VID_BLUE,                                       /* Blue */
561         VID_YELLOW,                                     /* Umber XXX */
562         VID_BLACK | VID_BRIGHT,         /* Light Dark */
563         VID_CYAN | VID_BRIGHT,          /* Light Slate XXX */
564         VID_MAGENTA,                            /* Violet XXX */
565         VID_YELLOW | VID_BRIGHT,        /* Yellow */
566         VID_MAGENTA | VID_BRIGHT,       /* Light Red XXX */
567         VID_GREEN | VID_BRIGHT,         /* Light Green */
568         VID_BLUE | VID_BRIGHT,          /* Light Blue */
569         VID_YELLOW                                      /* Light Umber XXX */
570 };
571
572
573 #ifdef SUPPORT_GAMMA
574 static int gamma_correction;
575 #endif /* SUPPORT_GAMMA */
576
577
578 /*
579  * Hack -- define which keys are "special"
580  */
581 static bool special_key[256];
582
583 /*
584  * Hack -- initialization list for "special_key"
585  *
586  * We ignore the modifier keys (shift, control, alt, num lock, scroll lock),
587  * and the normal keys (escape, tab, return, letters, numbers, etc), but we
588  * catch the keypad keys (with and without numlock set, including keypad 5),
589  * the function keys (including the "menu" key which maps to F10), and the
590  * "pause" key (between scroll lock and numlock).  We also catch a few odd
591  * keys which I do not recognize, but which are listed among keys which we
592  * do catch, so they should be harmless to catch.
593  */
594 static const byte special_key_list[] =
595 {
596         VK_CLEAR,               /* 0x0C (KP<5>) */
597
598         VK_PAUSE,               /* 0x13 (pause) */
599
600         VK_PRIOR,               /* 0x21 (KP<9>) */
601         VK_NEXT,                /* 0x22 (KP<3>) */
602         VK_END,                 /* 0x23 (KP<1>) */
603         VK_HOME,                /* 0x24 (KP<7>) */
604         VK_LEFT,                /* 0x25 (KP<4>) */
605         VK_UP,                  /* 0x26 (KP<8>) */
606         VK_RIGHT,               /* 0x27 (KP<6>) */
607         VK_DOWN,                /* 0x28 (KP<2>) */
608         VK_SELECT,              /* 0x29 (?) */
609         VK_PRINT,               /* 0x2A (?) */
610         VK_EXECUTE,             /* 0x2B (?) */
611         VK_SNAPSHOT,    /* 0x2C (?) */
612         VK_INSERT,              /* 0x2D (KP<0>) */
613         VK_DELETE,              /* 0x2E (KP<.>) */
614         VK_HELP,                /* 0x2F (?) */
615
616 #if 0
617         VK_NUMPAD0,             /* 0x60 (KP<0>) */
618         VK_NUMPAD1,             /* 0x61 (KP<1>) */
619         VK_NUMPAD2,             /* 0x62 (KP<2>) */
620         VK_NUMPAD3,             /* 0x63 (KP<3>) */
621         VK_NUMPAD4,             /* 0x64 (KP<4>) */
622         VK_NUMPAD5,             /* 0x65 (KP<5>) */
623         VK_NUMPAD6,             /* 0x66 (KP<6>) */
624         VK_NUMPAD7,             /* 0x67 (KP<7>) */
625         VK_NUMPAD8,             /* 0x68 (KP<8>) */
626         VK_NUMPAD9,             /* 0x69 (KP<9>) */
627         VK_MULTIPLY,    /* 0x6A (KP<*>) */
628         VK_ADD,                 /* 0x6B (KP<+>) */
629         VK_SEPARATOR,   /* 0x6C (?????) */
630         VK_SUBTRACT,    /* 0x6D (KP<->) */
631         VK_DECIMAL,             /* 0x6E (KP<.>) */
632         VK_DIVIDE,              /* 0x6F (KP</>) */
633 #endif /* 0 */
634
635         VK_F1,                  /* 0x70 */
636         VK_F2,                  /* 0x71 */
637         VK_F3,                  /* 0x72 */
638         VK_F4,                  /* 0x73 */
639         VK_F5,                  /* 0x74 */
640         VK_F6,                  /* 0x75 */
641         VK_F7,                  /* 0x76 */
642         VK_F8,                  /* 0x77 */
643         VK_F9,                  /* 0x78 */
644         VK_F10,                 /* 0x79 */
645         VK_F11,                 /* 0x7A */
646         VK_F12,                 /* 0x7B */
647         VK_F13,                 /* 0x7C */
648         VK_F14,                 /* 0x7D */
649         VK_F15,                 /* 0x7E */
650         VK_F16,                 /* 0x7F */
651         VK_F17,                 /* 0x80 */
652         VK_F18,                 /* 0x81 */
653         VK_F19,                 /* 0x82 */
654         VK_F20,                 /* 0x83 */
655         VK_F21,                 /* 0x84 */
656         VK_F22,                 /* 0x85 */
657         VK_F23,                 /* 0x86 */
658         VK_F24,                 /* 0x87 */
659
660         0
661 };
662
663 #include "game-cmd.h"
664
665 static game_command cmd = { CMD_NULL, 0 };
666
667 #if 0
668 /*
669  * Hack -- given a pathname, point at the filename
670  */
671 static cptr extract_file_name(cptr s)
672 {
673         cptr p;
674
675         /* Start at the end */
676         p = s + strlen(s) - 1;
677
678         /* Back up to divider */
679         while ((p >= s) && (*p != ':') && (*p != '\\')) p--;
680
681         /* Return file name */
682         return (p+1);
683 }
684 #endif /* 0 */
685
686
687 static void show_win_error(void)
688 {
689         LPVOID lpMsgBuf;
690
691         FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
692                       NULL, GetLastError(),
693                       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
694                       (LPTSTR) &lpMsgBuf, 0, NULL);
695
696         MessageBox(NULL, lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION);
697
698         LocalFree(lpMsgBuf);
699 }
700
701
702 /*
703  * Hack -- given a simple filename, extract the "font size" info
704  *
705  * Return a pointer to a static buffer holding the capitalized base name.
706  */
707 static char *analyze_font(char *path, int *wp, int *hp)
708 {
709         int wid, hgt;
710
711         char *s, *p;
712
713         /* Start at the end */
714         p = path + strlen(path) - 1;
715
716         /* Back up to divider */
717         while ((p >= path) && (*p != ':') && (*p != '\\')) --p;
718
719         /* Advance to file name */
720         ++p;
721
722         /* Capitalize */
723         for (s = p; *s; ++s)
724         {
725                 /* Capitalize (be paranoid) */
726                 if (islower((unsigned char)*s)) *s = toupper((unsigned char)*s);
727         }
728
729         /* Find first 'X' */
730         s = strchr(p, 'X');
731
732         /* Extract font width */
733         wid = atoi(p);
734
735         /* Extract height */
736         hgt = s ? atoi(s+1) : 0;
737
738         /* Save results */
739         (*wp) = wid;
740         (*hp) = hgt;
741
742         /* Result */
743         return (p);
744 }
745
746
747 /*
748  * Check for existance of a directory
749  */
750 static bool check_dir(cptr s)
751 {
752         int i;
753
754         char path[1024];
755
756         DWORD attrib;
757
758         /* Copy it */
759         my_strcpy(path, s, sizeof(path));
760
761         /* Check length */
762         i = strlen(path);
763
764         /* Remove trailing backslash */
765         if (i && (path[i-1] == '\\')) path[--i] = '\0';
766
767         /* Examine */
768         attrib = GetFileAttributes(path);
769
770         /* Require valid filename */
771         if (attrib == INVALID_FILE_NAME) return (FALSE);
772
773         /* Require directory */
774         if (!(attrib & FILE_ATTRIBUTE_DIRECTORY)) return (FALSE);
775
776         /* Success */
777         return (TRUE);
778 }
779
780
781 /*
782  * Validate a file
783  */
784 static void validate_file(cptr s)
785 {
786         /* Verify or fail */
787         if (!file_exists(s))
788                 quit_fmt("Cannot find required file:\n%s", s);
789 }
790
791
792 /*
793  * Validate a directory
794  */
795 static void validate_dir(cptr s)
796 {
797         /* Verify or fail */
798         if (!check_dir(s))
799         {
800                 quit_fmt("Cannot find required directory:\n%s", s);
801         }
802 }
803
804
805 /*
806  * Get the "size" for a window
807  */
808 static void term_getsize(term_data *td)
809 {
810         RECT rc;
811
812         int wid, hgt;
813
814         /* Paranoia */
815         if (td->cols < 1) td->cols = 1;
816         if (td->rows < 1) td->rows = 1;
817
818         /* Window sizes */
819         wid = td->cols * td->tile_wid + td->size_ow1 + td->size_ow2;
820         hgt = td->rows * td->tile_hgt + td->size_oh1 + td->size_oh2;
821
822         /* Client window size */
823         rc.left = 0;
824         rc.right = rc.left + wid;
825         rc.top = 0;
826         rc.bottom = rc.top + hgt;
827
828         /* Get total window size (without menu for sub-windows) */
829         AdjustWindowRectEx(&rc, td->dwStyle, TRUE, td->dwExStyle);
830
831         /* Total size */
832         td->size_wid = rc.right - rc.left;
833         td->size_hgt = rc.bottom - rc.top;
834
835         /* See CreateWindowEx */
836         if (!td->w) return;
837
838         /* Extract actual location */
839         GetWindowRect(td->w, &rc);
840
841         /* Save the location */
842         td->pos_x = rc.left;
843         td->pos_y = rc.top;
844 }
845
846
847 /*
848  * Write the "prefs" for a single term
849  */
850 static void save_prefs_aux(term_data *td, cptr sec_name)
851 {
852         char buf[1024];
853
854         RECT rc;
855
856         WINDOWPLACEMENT lpwndpl;
857
858         /* Paranoia */
859         if (!td->w) return;
860
861         /* Visible */
862         strcpy(buf, td->visible ? "1" : "0");
863         WritePrivateProfileString(sec_name, "Visible", buf, ini_file);
864
865         /* Font */
866         strcpy(buf, td->font_file ? td->font_file : DEFAULT_FONT);
867         WritePrivateProfileString(sec_name, "Font", buf, ini_file);
868
869         /* Bizarre */
870         strcpy(buf, td->bizarre ? "1" : "0");
871         WritePrivateProfileString(sec_name, "Bizarre", buf, ini_file);
872
873         /* Tile size (x) */
874         wsprintf(buf, "%d", td->tile_wid);
875         WritePrivateProfileString(sec_name, "TileWid", buf, ini_file);
876
877         /* Tile size (y) */
878         wsprintf(buf, "%d", td->tile_hgt);
879         WritePrivateProfileString(sec_name, "TileHgt", buf, ini_file);
880
881         /* Window size (x) */
882         wsprintf(buf, "%d", td->cols);
883         WritePrivateProfileString(sec_name, "NumCols", buf, ini_file);
884
885         /* Window size (y) */
886         wsprintf(buf, "%d", td->rows);
887         WritePrivateProfileString(sec_name, "NumRows", buf, ini_file);
888
889         /* Get window placement and dimensions */
890         lpwndpl.length = sizeof(WINDOWPLACEMENT);
891         GetWindowPlacement(td->w, &lpwndpl);
892
893         /* Acquire position in *normal* mode (not minimized) */
894         rc = lpwndpl.rcNormalPosition;
895
896         /* Get information about the placement of the window */
897         if (lpwndpl.flags & SW_SHOWMAXIMIZED)
898                 td->maximized = TRUE;
899         else