1 /* File: main-win.c */
2 
3 /* Purpose: Support for Windows Angband */
4 
5 /*
6  * Written (2.7.8) by Skirmantas Kligys (kligys@scf.usc.edu)
7  *
8  * Based loosely on "main-mac.c" and "main-xxx.c" and suggestions
9  * by Ben Harrison (benh@voicenet.com).
10  *
11  * Upgrade to Angband 2.7.9v6 by Ben Harrison (benh@voicenet.com),
12  * Ross E Becker (beckerr@cis.ohio-state.edu), and Chris R. Martin
13  * (crm7479@tam2000.tamu.edu).
14  *
15  * Note that the "Windows" version requires several extra files, which
16  * must be placed in various places.  These files are distributed in a
17  * special "ext-win.zip" archive, with instructions on where to place
18  * the various files.  For example, we require that all font files,
19  * bitmap files, and sound files, be placed into the "lib/xtra/font/",
20  * "/lib/xtra/graf/", and "lib/xtra/sound/" directories, respectively.
21  *
22  * See "h-config.h" for the extraction of the "WINDOWS" flag based
23  * on the "_Windows", "__WINDOWS__", "__WIN32__", "WIN32", "__WINNT__",
24  * or "__NT__" flags.  If your compiler uses a different compiler flag,
25  * add it to "h-config.h", or, simply place it in the "Makefile".
26  *
27  *
28  * This file still needs some work, possible problems are indicated by
29  * the string "XXX XXX XXX" in any comment.
30  *
31  * XXX XXX XXX
32  * The "Term_xtra_win_clear()" function should probably do a low-level
33  * clear of the current window, and redraw the borders and other things.
34  *
35  * XXX XXX XXX
36  * The user should be able to select the "bitmap" for a window independant
37  * from the "font", and should be allowed to select any bitmap file which
38  * is strictly smaller than the font file.  Currently, bitmap selection
39  * always imitates the font selection unless the "Font" and "Graf" lines
40  * are used in the "ANGBAND.INI" file.  This may require the addition
41  * of a menu item for each window to select the bitmaps.
42  *
43  * XXX XXX XXX
44  * The various "warning" messages assume the existance of the "screen.w"
45  * window, I think, and only a few calls actually check for its existance,
46  * this may be okay since "NULL" means "on top of all windows". (?)
47  *
48  * XXX XXX XXX
49  * Special "Windows Help Files" can be placed into "lib/xtra/help/" for
50  * use with the "winhelp.exe" program.  These files *may* be available
51  * at the ftp site somewhere.
52  *
53  * XXX XXX XXX
54  * The "prepare menus" command should "gray out" any menu command which
55  * is not allowed at the current time.  This will simplify the actual
56  * processing of menu commands, which can assume the command is legal.
57  *
58  * XXX XXX XXX
59  * Remove the old "FontFile" entries from the "*.ini" file, and remove
60  * the entire section about "sounds", after renaming a few sound files.
61  */
62 
63 
64 #include "c-angband.h"
65 
66 #ifdef USE_WIN
67 
68 #define MNU_SUPPORT
69 
70 /*
71  * Extract the "WIN32" flag from the compiler
72  */
73 #if defined(__WIN32__) || defined(__WINNT__) || defined(__NT__)
74 # ifndef WIN32
75 #  define WIN32
76 # endif
77 #endif
78 
79 /*
80  * XXX XXX XXX Hack -- broken sound libraries
81  */
82 #ifdef BEN_HACK
83 # undef USE_SOUND
84 #endif
85 
86 
87 /*
88  * Menu constants -- see "ANGBAND.RC"
89  */
90 
91 #define IDM_FILE_NEW			101
92 #define IDM_FILE_OPEN			102
93 #define IDM_FILE_SAVE			103
94 #define IDM_FILE_EXIT			104
95 #define IDM_FILE_QUIT			105
96 
97 #define IDM_TEXT_SCREEN			201
98 #define IDM_TEXT_MIRROR			202
99 #define IDM_TEXT_RECALL			203
100 #define IDM_TEXT_CHOICE			204
101 #define IDM_TEXT_TERM_4			205
102 #define IDM_TEXT_TERM_5			206
103 #define IDM_TEXT_TERM_6			207
104 #define IDM_TEXT_TERM_7			208
105 
106 #define IDM_WINDOWS_SCREEN		211
107 #define IDM_WINDOWS_MIRROR		212
108 #define IDM_WINDOWS_RECALL		213
109 #define IDM_WINDOWS_CHOICE		214
110 #define IDM_WINDOWS_TERM_4		215
111 #define IDM_WINDOWS_TERM_5		216
112 #define IDM_WINDOWS_TERM_6		217
113 #define IDM_WINDOWS_TERM_7		218
114 
115 #define IDM_GRAPHICS_OFF	221
116 #define IDM_GRAPHICS_BIG_TILE	222
117 #define IDM_GRAPHICS_TILESET_1	223
118 #define IDM_GRAPHICS_TILESET_2	224
119 #define IDM_GRAPHICS_TILESET_3	225
120 #define IDM_GRAPHICS_TILESET_4	226
121 #define IDM_GRAPHICS_TILESET_5	227
122 #define IDM_GRAPHICS_TILESET_6	228
123 #define IDM_GRAPHICS_TILESET_7	229
124 #define IDM_GRAPHICS_TILESET_8	230
125 
126 #define IDM_OPTIONS_SOUND		301
127 #define IDM_OPTIONS_MOUSE		302
128 #define IDM_OPTIONS_UNUSED		231
129 #define IDM_OPTIONS_SAVER		232
130 
131 #define IDM_HELP_GENERAL		901
132 #define IDM_HELP_SPOILERS		902
133 #define IDM_HELP_ABOUT			903
134 
135 /*
136  * exclude parts of WINDOWS.H that are not needed
137  */
138 #define NOSOUND           /* Sound APIs and definitions */
139 #define NOCOMM            /* Comm driver APIs and definitions */
140 #define NOLOGERROR        /* LogError() and related definitions */
141 #define NOPROFILER        /* Profiler APIs */
142 #define NOLFILEIO         /* _l* file I/O routines */
143 #define NOOPENFILE        /* OpenFile and related definitions */
144 #define NORESOURCE        /* Resource management */
145 #define NOATOM            /* Atom management */
146 #define NOLANGUAGE        /* Character test routines */
147 #define NOLSTRING         /* lstr* string management routines */
148 #define NODBCS            /* Double-byte character set routines */
149 #define NOKEYBOARDINFO    /* Keyboard driver routines */
150 #define NOCOLOR           /* COLOR_* color values */
151 #define NODRAWTEXT        /* DrawText() and related definitions */
152 #define NOSCALABLEFONT    /* Truetype scalable font support */
153 #define NOMETAFILE        /* Metafile support */
154 #define NOSYSTEMPARAMSINFO /* SystemParametersInfo() and SPI_* definitions */
155 #define NODEFERWINDOWPOS  /* DeferWindowPos and related definitions */
156 #define NOKEYSTATES       /* MK_* message key state flags */
157 #define NOWH              /* SetWindowsHook and related WH_* definitions */
158 #define NOCLIPBOARD       /* Clipboard APIs and definitions */
159 #define NOICONS           /* IDI_* icon IDs */
160 #define NOMDI             /* MDI support */
161 #define NOCTLMGR          /* Control management and controls */
162 #define NOHELP            /* Help support */
163 
164 /*
165  * exclude parts of WINDOWS.H that are not needed (Win32)
166  */
167 #define WIN32_LEAN_AND_MEAN
168 #define NONLS             /* All NLS defines and routines */
169 #define NOSERVICE         /* All Service Controller routines, SERVICE_ equates, etc. */
170 #define NOKANJI           /* Kanji support stuff. */
171 #define NOMCX             /* Modem Configuration Extensions */
172 
173 /*
174  * Include the "windows" support file
175  */
176 #ifndef WIN32_LEAN_AND_MEAN
177 #define WIN32_LEAN_AND_MEAN
178 #endif
179 #ifndef _WINSOCK2API_
180 //#include <winsock2.h>
181 #endif
182 
183 
184 /*
185  * exclude parts of MMSYSTEM.H that are not needed
186  */
187 #define MMNODRV          /* Installable driver support */
188 #define MMNOWAVE         /* Waveform support */
189 #define MMNOMIDI         /* MIDI support */
190 #define MMNOAUX          /* Auxiliary audio support */
191 #define MMNOTIMER        /* Timer support */
192 #define MMNOJOY          /* Joystick support */
193 #define MMNOMCI          /* MCI support */
194 #define MMNOMMIO         /* Multimedia file I/O support */
195 #define MMNOMMSYSTEM     /* General MMSYSTEM functions */
196 
197 /*
198  * Include the ??? files
199  */
200 #include <mmsystem.h>
201 #include <commdlg.h>
202 
203 /*
204  * Include the support for loading bitmaps
205  */
206 #ifdef USE_GRAPHICS
207 # include "win/readdib.h"
208 #endif
209 
210 /*
211  * Hack -- allow use of the Borg as a screen-saver
212  */
213 #ifdef ALLOW_BORG
214 # define ALLOW_SCRSAVER
215 #endif
216 
217 /*
218  * Cannot include "dos.h", so we define some things by hand.
219  */
220 #ifdef WIN32
221 #define INVALID_FILE_NAME (DWORD)0xFFFFFFFF
222 #else /* WIN32 */
223 #define FA_LABEL    0x08        /* Volume label */
224 #define FA_DIREC    0x10        /* Directory */
225 unsigned _cdecl _dos_getfileattr(const char *, unsigned *);
226 #endif /* WIN32 */
227 
228 /*
229  * Silliness in WIN32 drawing routine
230  */
231 #ifdef WIN32
232 # define MoveTo(H,X,Y) MoveToEx(H, X, Y, NULL)
233 #endif /* WIN32 */
234 
235 /*
236  * Silliness for Windows 95
237  */
238 #ifndef WS_EX_TOOLWINDOW
239 # define WS_EX_TOOLWINDOW 0
240 #endif
241 
242 /*
243  * Foreground color bits (hard-coded by DOS)
244  */
245 #define VID_BLACK	0x00
246 #define VID_BLUE	0x01
247 #define VID_GREEN	0x02
248 #define VID_CYAN	0x03
249 #define VID_RED		0x04
250 #define VID_MAGENTA	0x05
251 #define VID_YELLOW	0x06
252 #define VID_WHITE	0x07
253 
254 /*
255  * Bright text (hard-coded by DOS)
256  */
257 #define VID_BRIGHT	0x08
258 
259 /*
260  * Background color bits (hard-coded by DOS)
261  */
262 #define VUD_BLACK	0x00
263 #define VUD_BLUE	0x10
264 #define VUD_GREEN	0x20
265 #define VUD_CYAN	0x30
266 #define VUD_RED		0x40
267 #define VUD_MAGENTA	0x50
268 #define VUD_YELLOW	0x60
269 #define VUD_WHITE	0x70
270 
271 /*
272  * Blinking text (hard-coded by DOS)
273  */
274 #define VUD_BRIGHT	0x80
275 
276 
277 /*
278  * Forward declare
279  */
280 typedef struct _term_data term_data;
281 
282 /*
283  * Extra "term" data
284  *
285  * Note the use of "font_want" and "graf_want" for the names of the
286  * font/graf files requested by the user, and the use of "font_file"
287  * and "graf_file" for the currently active font/graf files.
288  *
289  * The "font_file" and "graf_file" are capitilized, and are of the
290  * form "8X13.FON" and "8X13.BMP", while "font_want" and "graf_want"
291  * can be in almost any form as long as it could be construed as
292  * attempting to represent the name of a font or bitmap or file.
293  */
294 struct _term_data
295 {
296 	term     t;
297 
298 	cptr     s;
299 
300 	HWND     w;
301 
302 #ifdef USE_GRAPHICS
303 
304 #endif
305 
306 	DWORD    dwStyle;
307 	DWORD    dwExStyle;
308 
309 	uint     keys;
310 
311 	uint     rows;
312 	uint     cols;
313 
314 	uint     pos_x;
315 	uint     pos_y;
316 	uint     size_wid;
317 	uint     size_hgt;
318 	uint     client_wid;
319 	uint     client_hgt;
320 	uint     size_ow1;
321 	uint     size_oh1;
322 	uint     size_ow2;
323 	uint     size_oh2;
324 
325 	byte     visible;
326 
327 	byte     size_hack;
328 
329 	cptr     font_want;
330 	cptr     graf_want;
331 
332 	cptr     font_file;
333 
334 	HFONT    font_id;
335 
336 	uint     font_wid;
337 	uint     font_hgt;
338 };
339 
340 #ifdef USE_GRAPHICS
341 /*
342 * Flag set once "graphics" has been initialized
343 */
344 static bool can_use_graphics = FALSE;
345 
346 /*
347 * The global bitmap
348 */
349 static DIBINIT infGraph;
350 
351 /*
352 * The global bitmap mask
353 */
354 static DIBINIT infMask;
355 
356 #endif
357 /*
358  * Maximum number of windows XXX XXX XXX XXX
359  */
360 #define MAX_TERM_DATA 8
361 
362 /*
363  * An array of term_data's
364  */
365 static term_data win_data[MAX_TERM_DATA];
366 
367 /*
368  * Mega-Hack -- global "window creation" pointer
369  */
370 static term_data *td_ptr;
371 
372 /*
373  * Even bigger hack than the above -- global edit control handle [grk]
374  */
375 static HWND editmsg;
376 static HWND old_focus = NULL;
377 LRESULT APIENTRY SubClassFunc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam);
378 WNDPROC lpfnOldWndProc;
379 
380 /*
381  * Various boolean flags
382  */
383 bool game_in_progress  = FALSE;  /* game in progress */
384 bool initialized       = FALSE;  /* note when "open"/"new" become valid */
385 bool paletted          = FALSE;  /* screen paletted, i.e. 256 colors */
386 bool colors16          = FALSE;  /* 16 colors screen, don't use RGB() */
387 bool use_mouse         = FALSE;  /* game accepts mouse */
388 
389 /*
390  * Saved instance handle
391  */
392 static HINSTANCE hInstance;
393 
394 /*
395  * Yellow brush for the cursor
396  */
397 static HBRUSH hbrYellow;
398 
399 /*
400  * Black brush for the chat window edit control
401  */
402 static HBRUSH hbrBlack;
403 
404 /*
405  * An icon
406  */
407 static HICON hIcon;
408 
409 /*
410  * A palette
411  */
412 static HPALETTE hPal;
413 
414 #ifdef ALLOW_SCRSAVER
415 
416 /*
417  * The screen saver
418  */
419 static HWND hwndSaver;
420 
421 #endif
422 
423 /*
424  * Full path to ANGBAND.INI
425  */
426 static cptr ini_file = NULL;
427 
428 /*
429  * Name of application
430  */
431 static cptr AppName  = "ANGBAND";
432 
433 /*
434  * Name of sub-window type
435  */
436 static cptr AngList  = "AngList";
437 static int next_graphics = 0;
438 static int loaded_graphics = 0;
439 /*
440  * Directory names
441  */
442 static cptr ANGBAND_DIR_XTRA_FONT;
443 #define ANGBAND_DIR_XTRA_HELP ".\\lib\\text"
444 
445 #ifdef USE_SOUND
446 
447 /*
448  * Flag set once "sound" has been initialized
449  */
450 static bool can_use_sound = FALSE;
451 
452 #endif /* USE_SOUND */
453 
454 /*
455  * The Angband color set:
456  *   Black, White, Slate, Orange,    Red, Blue, Green, Umber
457  *   D-Gray, L-Gray, Violet, Yellow, L-Red, L-Blue, L-Green, L-Umber
458  *
459  * Colors 8 to 15 are basically "enhanced" versions of Colors 0 to 7.
460  * Note that on B/W machines, all non-zero colors can be white (on black).
461  *
462  * Note that all characters are assumed to be drawn on a black background.
463  * This may require calling "Term_wipe()" before "Term_text()", etc.
464  *
465  * XXX XXX XXX See "main-ibm.c" for a method to allow color editing
466  *
467  * XXX XXX XXX The color codes below were taken from "main-ibm.c".
468  */
469 static COLORREF win_clr[16] =
470 {
471     PALETTERGB(0x00, 0x00, 0x00),  /* 0 0 0  Dark */
472     PALETTERGB(0xFF, 0xFF, 0xFF),  /* 4 4 4  White */
473     PALETTERGB(0x90, 0x90, 0x90),  /* 2 2 2  Slate */
474     PALETTERGB(0xFF, 0x80, 0x00),  /* 4 2 0  Orange */
475     PALETTERGB(0xFF, 0x20, 0x20),  /* 3 0 0  Red (was 2,0,0) */
476     PALETTERGB(0x20, 0x8D, 0x44),  /* 0 2 1  Green */
477     PALETTERGB(0x20, 0x50, 0xC0),  /* 0 0 4  Blue */
478     PALETTERGB(0x8D, 0x44, 0x20),  /* 2 1 0  Umber */
479     PALETTERGB(0x60, 0x60, 0x60),  /* 1 1 1  Lt. Dark */
480     PALETTERGB(0xC0, 0xC0, 0xC0),  /* 3 3 3  Lt. Slate */
481     PALETTERGB(0xB0, 0x30, 0xFF),  /* 4 0 4  Violet (was 2,0,2) */
482     PALETTERGB(0xEF, 0xDF, 0x40),  /* 4 4 0  Yellow */
483     // PALETTERGB(0xFF, 0x70, 0x50),  /* 4 0 0  Lt. Red (was 4,1,3) */
484     PALETTERGB(0xFF, 0x80, 0x80),  /* 4 0 0  Lt. Red (was 4,1,3) */
485     PALETTERGB(0x30, 0xFF, 0x30),  /* 0 4 0  Lt. Green */
486     PALETTERGB(0x30, 0xD0, 0xFF),  /* 0 4 4  Lt. Blue */
487     PALETTERGB(0xFF, 0xA8, 0x20)   /* 3 2 1  Lt. Umber */
488 
489 
490 #if 0
491 	PALETTERGB(0x00, 0x00, 0x00),  /* 0 0 0  Dark */
492 	PALETTERGB(0xFF, 0xFF, 0xFF),  /* 4 4 4  White */
493 	PALETTERGB(0x8D, 0x8D, 0x8D),  /* 2 2 2  Slate */
494 	PALETTERGB(0xFF, 0x8D, 0x00),  /* 4 2 0  Orange */
495 	PALETTERGB(0xD7, 0x00, 0x00),  /* 3 0 0  Red (was 2,0,0) */
496 	PALETTERGB(0x00, 0x8D, 0x44),  /* 0 2 1  Green */
497 	PALETTERGB(0x00, 0x00, 0xFF),  /* 0 0 4  Blue */
498 	PALETTERGB(0x8D, 0x44, 0x00),  /* 2 1 0  Umber */
499 	PALETTERGB(0x54, 0x54, 0x54),  /* 1 1 1  Lt. Dark */
500 	PALETTERGB(0xD7, 0xD7, 0xD7),  /* 3 3 3  Lt. Slate */
501 	PALETTERGB(0xFF, 0x00, 0xFF),  /* 4 0 4  Violet (was 2,0,2) */
502 	PALETTERGB(0xFF, 0xFF, 0x00),  /* 4 4 0  Yellow */
503 	PALETTERGB(0xFF, 0x44, 0xD7),  /* 4 0 0  Lt. Red (was 4,1,3) */
504 	PALETTERGB(0x00, 0xFF, 0x00),  /* 0 4 0  Lt. Green */
505 	PALETTERGB(0x00, 0xFF, 0xFF),  /* 0 4 4  Lt. Blue */
506 	PALETTERGB(0xD7, 0x8D, 0x44)   /* 3 2 1  Lt. Umber */
507 #endif
508 };
509 
510 
511 /*
512  * Palette indices for 16 colors
513  *
514  * See "main-ibm.c" for original table information
515  *
516  * The entries below are taken from the "color bits" defined above.
517  *
518  * Note that many of the choices below suck, but so do crappy monitors.
519  */
520 static BYTE win_pal[16] =
521 {
522 	VID_BLACK,			/* Dark */
523 	VID_WHITE,			/* White */
524 	VID_CYAN,			/* Slate XXX */
525 	VID_RED | VID_BRIGHT,	/* Orange XXX */
526 	VID_RED,			/* Red */
527 	VID_GREEN,			/* Green */
528 	VID_BLUE,			/* Blue */
529 	VID_YELLOW,			/* Umber XXX */
530 	VID_BLACK | VID_BRIGHT,	/* Light Dark */
531 	VID_CYAN | VID_BRIGHT,	/* Light Slate XXX */
532 	VID_MAGENTA,		/* Violet XXX */
533 	VID_YELLOW | VID_BRIGHT,	/* Yellow */
534 	VID_MAGENTA | VID_BRIGHT,	/* Light Red XXX */
535 	VID_GREEN | VID_BRIGHT,	/* Light Green */
536 	VID_BLUE | VID_BRIGHT,	/* Light Blue */
537 	VID_YELLOW			/* Light Umber XXX */
538 };
539 
540 /* [grk]
541  * A gross hack to allow the client to scroll the dungeon display.
542  * This is required for large graphical tiles where we cant have an
543  * 66x22 tile display except in very high screen resolutions.
544  * When the server supports player recentering this can go.
545  *
546  * When we receive a request to plot a tile at a location, we
547  * shift the x-coordinate by this value. If the resultant
548  * x-coordinate is negative we just ignore it and plot nothing.
549  *
550  * We only need scrolling along the x axis.
551  */
552 static char x_offset = 0;
553 
554 /* Hack -- set focus to chat message control */
set_chat_focus(void)555 void set_chat_focus( void )
556 {
557 	old_focus = GetFocus();
558 	SetFocus(editmsg);
559 }
560 
unset_chat_focus(void)561 void unset_chat_focus( void )
562 {
563 	/* Set focus back to original window */
564 	if(old_focus) SetFocus(old_focus);
565 }
566 
set_graphics_next(int mode)567 void set_graphics_next(int mode)
568 {
569 	// char buf[1024];
570 
571 	next_graphics = mode;
572 	if (next_graphics != use_graphics)
573 	{
574 		MessageBox(NULL, "You need to restart MAngband in order for the changes to take effect","MAngband",MB_OK);
575 
576 		/*
577 		save_prefs();
578 		*/
579 
580 		/* Access the "graphic" mappings */
581 		//sprintf(buf, "%s-%s.prf", (use_graphics ? "graf" : "font"), ANGBAND_SYS);
582 
583 		/* Load the file */
584 		//process_pref_file(buf);
585 	}
586 }
587 
stretch_chat_ctrl(void)588 void stretch_chat_ctrl( void )
589 {
590 	/* Resize the edit control */
591 	SetWindowPos(editmsg, 0, 2, win_data[4].client_hgt-21,
592 	             win_data[4].client_wid-6, 20,
593 	             SWP_NOZORDER);
594 }
595 
win32_window_visible(int i)596 int win32_window_visible(int i)
597 {
598 	return (bool)win_data[i].visible;
599 }
600 
601 /*
602  * Hack -- given a pathname, point at the filename
603  */
extract_file_name(cptr s)604 static cptr extract_file_name(cptr s)
605 {
606 	cptr p;
607 
608 	/* Start at the end */
609 	p = s + strlen(s) - 1;
610 
611 	/* Back up to divider */
612 	while ((p >= s) && (*p != ':') && (*p != '\\')) p--;
613 
614 	/* Return file name */
615 	return (p+1);
616 }
617 
618 
619 
620 /*
621  * Check for existance of a file
622  */
check_file(cptr s)623 static bool check_file(cptr s)
624 {
625 	char path[1024];
626 
627 #ifdef WIN32
628 
629 	DWORD attrib;
630 
631 #else /* WIN32 */
632 
633 	unsigned int attrib;
634 
635 #endif /* WIN32 */
636 
637 	/* Copy it */
638 	strcpy(path, s);
639 
640 #ifdef WIN32
641 
642 	/* Examine */
643 	attrib = GetFileAttributes(path);
644 
645 	/* Require valid filename */
646 	if (attrib == INVALID_FILE_NAME) return (FALSE);
647 
648 	/* Prohibit directory */
649 	if (attrib & FILE_ATTRIBUTE_DIRECTORY) return (FALSE);
650 
651 #else /* WIN32 */
652 
653 	/* Examine and verify */
654 	if (_dos_getfileattr(path, &attrib)) return (FALSE);
655 
656 	/* Prohibit something */
657 	if (attrib & FA_LABEL) return (FALSE);
658 
659 	/* Prohibit directory */
660 	if (attrib & FA_DIREC) return (FALSE);
661 
662 #endif /* WIN32 */
663 
664 	/* Success */
665 	return (TRUE);
666 }
667 
668 
669 /*
670  * Check for existance of a directory
671  */
check_dir(cptr s)672 static bool check_dir(cptr s)
673 {
674 	int i;
675 
676 	char path[1024];
677 
678 #ifdef WIN32
679 
680 	DWORD attrib;
681 
682 #else /* WIN32 */
683 
684 	unsigned int attrib;
685 
686 #endif /* WIN32 */
687 
688 	/* Copy it */
689 	strcpy(path, s);
690 
691 	/* Check length */
692 	i = strlen(path);
693 
694 	/* Remove trailing backslash */
695 	if (i && (path[i-1] == '\\')) path[--i] = '\0';
696 
697 #ifdef WIN32
698 
699 	/* Examine */
700 	attrib = GetFileAttributes(path);
701 
702 	/* Require valid filename */
703 	if (attrib == INVALID_FILE_NAME) return (FALSE);
704 
705 	/* Require directory */
706 	if (!(attrib & FILE_ATTRIBUTE_DIRECTORY)) return (FALSE);
707 
708 #else /* WIN32 */
709 
710 	/* Examine and verify */
711 	if (_dos_getfileattr(path, &attrib)) return (FALSE);
712 
713 	/* Prohibit something */
714 	if (attrib & FA_LABEL) return (FALSE);
715 
716 	/* Require directory */
717 	if (!(attrib & FA_DIREC)) return (FALSE);
718 
719 #endif /* WIN32 */
720 
721 	/* Success */
722 	return (TRUE);
723 }
724 
725 
726 /*
727  * Validate a file
728  */
validate_file(cptr s)729 static void validate_file(cptr s)
730 {
731 	/* Verify or fail */
732 	if (!check_file(s))
733 	{
734 		quit_fmt("Cannot find required file:\n%s", s);
735 	}
736 }
737 
738 
739 /*
740  * Validate a directory
741  */
validate_dir(cptr s)742 static void validate_dir(cptr s)
743 {
744 	/* Verify or fail */
745 	if (!check_dir(s))
746 	{
747 		quit_fmt("Cannot find required directory:\n%s", s);
748 	}
749 }
750 
751 
752 /*
753  * Get the "size" for a window
754  */
term_getsize(term_data * td)755 static void term_getsize(term_data *td)
756 {
757 	RECT        rc;
758 
759 	/* Paranoia */
760 	if (td->cols < 1) td->cols = 1;
761 	if (td->rows < 1) td->rows = 1;
762 
763 	/* Paranoia */
764 	if (conn_state && td == &win_data[0])
765 	{
766 /*		if (td->cols < Setup.min_col) td->cols = Setup.min_col;
767 		if (td->rows < Setup.min_row) td->rows = Setup.min_row;
768 		if (td->cols > Setup.max_col + SCREEN_CLIP_X) td->cols = Setup.max_col + SCREEN_CLIP_X;
769 		if (td->rows > Setup.max_row + SCREEN_CLIP_Y) td->rows = Setup.max_row + SCREEN_CLIP_Y; */
770 	}
771 
772 	/* Window sizes */
773 	td->client_wid = td->cols * td->font_wid + td->size_ow1 + td->size_ow2;
774 	td->client_hgt = td->rows * td->font_hgt + td->size_oh1 + td->size_oh2 + 1;
775 
776 	/* Fake window size */
777 	rc.left = rc.top = 0;
778 	rc.right = rc.left + td->client_wid;
779 	rc.bottom = rc.top + td->client_hgt;
780 
781 	/* Adjust */
782 	AdjustWindowRectEx(&rc, td->dwStyle, TRUE, td->dwExStyle);
783 
784 	/* Total size */
785 	td->size_wid = rc.right - rc.left;
786 	td->size_hgt = rc.bottom - rc.top;
787 
788 	/* See CreateWindowEx */
789 	if (!td->w) return;
790 
791 	/* Extract actual location */
792 	GetWindowRect(td->w, &rc);
793 
794 	/* Save the location */
795 	td->pos_x = rc.left;
796 	td->pos_y = rc.top;
797 }
798 
799 
800 /*
801  * Write the "preference" data for single term
802  */
save_prefs_aux(term_data * td,cptr sec_name)803 static void save_prefs_aux(term_data *td, cptr sec_name)
804 {
805 	char buf[32];
806 
807 	RECT rc;
808 
809 	if (!td->w) return;
810 
811 	/* Visible (Sub-windows) */
812 	if (td != &win_data[0])
813 	{
814 		//strcpy(buf, td->visible ? "1" : "0");
815 		conf_set_int(sec_name, "Visible", td->visible);
816 	}
817 
818 	/* Desired font */
819 	if (td->font_file)
820 	{
821 		/* Short-hand */
822 		if (!strncmp(td->font_file, ANGBAND_DIR_XTRA_FONT, strlen(ANGBAND_DIR_XTRA_FONT)))
823 		{
824 			strcpy(buf, td->font_file + strlen(ANGBAND_DIR_XTRA_FONT) + 1);
825 			conf_set_string(sec_name, "Font", buf);
826 		}
827 		else
828 		/* Full path */
829 		conf_set_string(sec_name, "Font", td->font_file);
830 	}
831 
832 	/* Bad Hack :( -- since we allow slight overhead, make sure we're in bounds */
833 /*	if (td == &win_data[0] && Setup.max_col && !(window_flag[0] & PW_PLAYER_2) && td->cols > Setup.max_col) td->cols = Setup.max_col; // Compact
834 	if (td == &win_data[0] && Setup.max_row && !(window_flag[0] & PW_STATUS)   && td->rows > Setup.max_row) td->rows = Setup.max_row; // Status line	 */
835 
836 	/* Current size (x) */
837 	//wsprintf(buf, "%d", td->cols);
838 	conf_set_int(sec_name, "Columns", td->cols);
839 
840 	/* Current size (y) */
841 	//wsprintf(buf, "%d", td->rows);
842 	conf_set_int(sec_name, "Rows", td->rows);
843 
844 	/* Acquire position */
845 	if (GetWindowRect(td->w, &rc))
846 	{
847 		/* Current position (x) */
848 		//wsprintf(buf, "%d", rc.left);
849 		conf_set_int(sec_name, "PositionX", rc.left);
850 
851 		/* Current position (y) */
852 		//wsprintf(buf, "%d", rc.top);
853 		conf_set_int(sec_name, "PositionY", rc.top);
854 	}
855 }
856 
857 
858 /*
859  * Write the "preference" data to the .INI file
860  *
861  * We assume that the windows have all been initialized
862  */
save_prefs(void)863 static void save_prefs(void)
864 {
865 #ifdef USE_GRAPHICS
866 	conf_set_int("Windows32", "Graphics", next_graphics);
867 #endif
868 #ifdef USE_SOUND
869 	conf_set_int("Windows32", "Sound", use_sound);
870 #endif
871 	conf_set_int("Windows32", "GameMouse", use_mouse);
872 
873 	save_prefs_aux(&win_data[0], "Main window");
874 
875 	/* XXX XXX XXX XXX */
876 
877 	save_prefs_aux(&win_data[1], "Mirror window");
878 
879 	save_prefs_aux(&win_data[2], "Recall window");
880 
881 	save_prefs_aux(&win_data[3], "Choice window");
882 
883 	save_prefs_aux(&win_data[4], "Term-4 window");
884 
885 	save_prefs_aux(&win_data[5], "Term-5 window");
886 
887 	save_prefs_aux(&win_data[6], "Term-6 window");
888 
889 	save_prefs_aux(&win_data[7], "Term-7 window");
890 }
891 
892 
893 /*
894  * Load preference for a single term
895  */
load_prefs_aux(term_data * td,cptr sec_name)896 static void load_prefs_aux(term_data *td, cptr sec_name)
897 {
898 	char tmp[128];
899 
900 	/* Visibility (Sub-window) */
901 	if (td != &win_data[0])
902 	{
903 		/* Extract visibility */
904 		td->visible = (conf_get_int(sec_name, "Visible", td->visible) != 0);
905 	}
906 
907 	/* Desired font, with default */
908 	strcpy(tmp, conf_get_string(sec_name, "Font", "8X13.FON"));
909 	td->font_want = string_make(extract_file_name(tmp));
910 
911 	/* Desired graf, with default */
912 	//strcpy(tmp, conf_get_string(sec_name, "Graf", GFXBMP[use_graphics]));
913 	//td->graf_want = string_make(extract_file_name(tmp));
914 
915 	/* Window size */
916 	td->cols = conf_get_int(sec_name, "Columns", td->cols);
917 	td->rows = conf_get_int(sec_name, "Rows", td->rows);
918 
919 	/* Window position */
920 	td->pos_x = conf_get_int(sec_name, "PositionX", td->pos_x);
921 	td->pos_y =	conf_get_int(sec_name, "PositionY", td->pos_y);
922 }
923 
924 /*
925  * Load the preferences from the .INI file
926  */
load_prefs(void)927 static void load_prefs(void)
928 {
929 	char buffer[20] = {'\0'};
930 	DWORD bufferLen = sizeof(buffer);
931 
932 #ifdef USE_GRAPHICS
933 	/* Extract the "use_graphics" flag */
934 	loaded_graphics = conf_get_int("Windows32", "Graphics", 0);
935 	set_graphics(loaded_graphics);
936 	set_graphics_next(loaded_graphics);
937 #endif
938 
939 #ifdef USE_SOUND
940 	/* Extract the "use_sound" flag */
941 	use_sound = (conf_get_int("Windows32", "Sound", 0) != 0);
942 #endif
943 
944 	/* Extract the "use_mouse" flag */
945 	use_mouse = (conf_get_int("Windows32", "GameMouse", 1) == 1);
946 
947 	/* Load window prefs */
948 	load_prefs_aux(&win_data[0], "Main window");
949 
950 	/* XXX XXX XXX XXX */
951 
952 	load_prefs_aux(&win_data[1], "Mirror window");
953 
954 	load_prefs_aux(&win_data[2], "Recall window");
955 
956 	load_prefs_aux(&win_data[3], "Choice window");
957 
958 	load_prefs_aux(&win_data[4], "Term-4 window");
959 
960 	load_prefs_aux(&win_data[5], "Term-5 window");
961 
962 	load_prefs_aux(&win_data[6], "Term-6 window");
963 
964 	load_prefs_aux(&win_data[7], "Term-7 window");
965 
966 	/* Pull nick/pass */
967 	my_strcpy(nick, conf_get_string("MAngband", "nick", "PLAYER"), MAX_CHARS);
968 	my_strcpy(pass, conf_get_string("MAngband", "pass", "passwd"), MAX_CHARS);
969 	my_strcpy(server_name, conf_get_string("MAngband", "host", ""), MAX_CHARS);
970 
971 	/* Pull username from Windows */
972 	if ( GetUserName(buffer, &bufferLen) ) {
973 		/* Cut */
974 		buffer[16] = '\0';
975 		strcpy(real_name, buffer);
976 
977 	}
978 	else
979 	{
980 		/* XXX Default real name */
981 		strcpy(real_name, "PLAYER");
982 	}
983 }
984 
985 
986 /*
987  * Create the new global palette based on the bitmap palette
988  * (if any) from the given bitmap xxx, and the standard 16
989  * entry palette derived from "win_clr[]" which is used for
990  * the basic 16 Angband colors.
991  *
992  * This function is never called before all windows are ready.
993  */
new_palette(void)994 static int new_palette(void)
995 {
996 	HPALETTE       hBmPal;
997 	HPALETTE       hNewPal;
998 	HDC            hdc;
999 	int            i, nEntries;
1000 	int            pLogPalSize;
1001 	int            lppeSize;
1002 	LPLOGPALETTE   pLogPal;
1003 	LPPALETTEENTRY lppe;
1004 
1005 
1006 	/* Cannot handle palettes */
1007 	if (!paletted) return (TRUE);
1008 
1009 	/* No palette */
1010 	hBmPal = NULL;
1011 
1012 	/* No bitmap */
1013 	lppeSize = 0;
1014 	lppe = NULL;
1015 	nEntries = 0;
1016 
1017 #ifdef USE_GRAPHICS
1018 
1019 	/* Check the bitmap palette */
1020 	hBmPal = infGraph.hPalette;
1021 
1022 	/* Use the bitmap */
1023 	if (hBmPal)
1024 	{
1025 		lppeSize = 256*sizeof(PALETTEENTRY);
1026 		lppe = (LPPALETTEENTRY)ralloc(lppeSize);
1027 		nEntries = GetPaletteEntries(hBmPal, 0, 255, lppe);
1028 		if (nEntries == 0) {
1029 			plog("Corrupted bitmap palette");
1030 			FREE(lppe);
1031 			return (FALSE);
1032 		}
1033 		else if (nEntries > 220) {
1034 			plog("Bitmap must have no more than 220 colors");
1035 			FREE(lppe);
1036 			return (FALSE);
1037 		}
1038 	}
1039 
1040 #endif
1041 
1042 	/* Size of palette */
1043 	pLogPalSize = sizeof(LOGPALETTE) + (16+nEntries)*sizeof(PALETTEENTRY);
1044 
1045 	/* Allocate palette */
1046 	pLogPal = (LPLOGPALETTE)ralloc(pLogPalSize);
1047 
1048 	/* Version */
1049 	pLogPal->palVersion = 0x300;
1050 
1051 	/* Make room for bitmap and normal data */
1052 	pLogPal->palNumEntries = nEntries + 16;
1053 
1054 	/* Save the bitmap data */
1055 	for (i = 0; i < nEntries; i++)
1056 	{
1057 		pLogPal->palPalEntry[i] = lppe[i];
1058 	}
1059 
1060 	/* Save the normal data */
1061 	for (i = 0; i < 16; i++)
1062 	{
1063 		LPPALETTEENTRY p;
1064 
1065 		/* Access the entry */
1066 		p = &(pLogPal->palPalEntry[i+nEntries]);
1067 
1068 		/* Save the colors */
1069 		p->peRed = GetRValue(win_clr[i]);
1070 		p->peGreen = GetGValue(win_clr[i]);
1071 		p->peBlue = GetBValue(win_clr[i]);
1072 
1073 		/* Save the flags */
1074 		p->peFlags = PC_NOCOLLAPSE;
1075 	}
1076 
1077 	/* Free something */
1078 	if (lppe) FREE(lppe);
1079 
1080 	/* Create a new palette, or fail */
1081 	hNewPal = CreatePalette(pLogPal);
1082 	if (!hNewPal) quit("Cannot create palette");
1083 
1084 	/* Free the palette */
1085 	FREE(pLogPal);
1086 
1087 
1088 	hdc = GetDC(win_data[0].w);
1089 	SelectPalette(hdc, hNewPal, 0);
1090 	i = RealizePalette(hdc);
1091 	ReleaseDC(win_data[0].w, hdc);
1092 	if (i == 0) quit("Cannot realize palette");
1093 
1094 	/* Check windows */
1095 	for (i = 1; i < MAX_TERM_DATA; i++)
1096 	{
1097 		hdc = GetDC(win_data[i].w);
1098 		SelectPalette(hdc, hNewPal, 0);
1099 		ReleaseDC(win_data[i].w, hdc);
1100 	}
1101 
1102 	/* Delete old palette */
1103 	if (hPal) DeleteObject(hPal);
1104 
1105 	/* Save new palette */
1106 	hPal = hNewPal;
1107 
1108 	/* Success */
1109 	return (TRUE);
1110 }
1111 
1112 
1113 #ifdef USE_SOUND
1114 /*
1115  * Initialize sound
1116  */
init_sound(void)1117 static bool init_sound(void)
1118 {
1119 	/* Initialize once */
1120 	if (!can_use_sound)
1121 	{
1122 		/* Load the prefs */
1123 		load_sound_prefs();
1124 
1125 		/* Sound available */
1126 		can_use_sound = TRUE;
1127 	}
1128 
1129 	/* Result */
1130 	return (can_use_sound);
1131 }
1132 #endif /* USE_SOUND */
1133 
1134 
1135 /*
1136  * Resize a window
1137  */
term_window_resize(term_data * td)1138 static void term_window_resize(term_data *td)
1139 {
1140 
1141 	/* Require window */
1142 	if (!td->w) return;
1143 
1144 	/* Resize the window */
1145 	SetWindowPos(td->w, 0, 0, 0,
1146 	             td->size_wid, td->size_hgt,
1147 	             SWP_NOMOVE | SWP_NOZORDER);
1148 
1149 	/* Redraw later */
1150 	InvalidateRect(td->w, NULL, TRUE);
1151 }
1152 
1153 /*
1154  * See if any other term is already using font_file
1155  */
term_font_inuse(term_data * td)1156 static bool term_font_inuse(term_data* td)
1157 {
1158 	int i;
1159 	bool used = FALSE;
1160 
1161 	/* Scan windows */
1162 	for (i = 0; i < MAX_TERM_DATA; i++)
1163 	{
1164 		/* Check "screen" */
1165 		if ((td != &win_data[i]) &&
1166 		    (win_data[i].font_file) &&
1167 		    (streq(win_data[i].font_file, td->font_file)))
1168 		{
1169 			used = TRUE;
1170 			break;
1171 		}
1172 	}
1173 	return used;
1174 }
1175 
1176 /*
1177  * Force the use of a new "font file" for a term_data
1178  *
1179  * This function may be called before the "window" is ready
1180  *
1181  * This function returns zero only if everything succeeds.
1182  */
term_force_font(term_data * td,cptr name)1183 static errr term_force_font(term_data *td, cptr name)
1184 {
1185 	int i;
1186 
1187 	int wid, hgt;
1188 
1189 	cptr s;
1190 
1191 	char base[16];
1192 
1193 	char base_font[16];
1194 
1195 	char buf[1024];
1196 
1197 
1198 	/* Forget the old font (if needed) */
1199 	if (td->font_id) DeleteObject(td->font_id);
1200 
1201 	/* Forget old font */
1202 	if (td->font_file)
1203 	{
1204 		bool used = term_font_inuse(td);
1205 
1206 		/* Remove unused font resources */
1207 		if (!used) RemoveFontResource(td->font_file);
1208 
1209 		/* Free the old name */
1210 		string_free(td->font_file);
1211 
1212 		/* Forget it */
1213 		td->font_file = NULL;
1214 	}
1215 
1216 
1217 	/* No name given */
1218 	if (!name) return (1);
1219 
1220 	/* Extract the base name (with suffix) */
1221 	s = extract_file_name(name);
1222 
1223 	/* Extract font width */
1224 	wid = atoi(s);
1225 
1226 	/* Default font height */
1227 	hgt = 0;
1228 
1229 	/* Copy, capitalize, remove suffix, extract width */
1230 	for (i = 0; (i < 16 - 1) && s[i] && (s[i] != '.'); i++)
1231 	{
1232 		/* Capitalize */
1233 		base[i] = FORCEUPPER(s[i]);
1234 
1235 		/* Extract "hgt" when found */
1236 		if (base[i] == 'X') hgt = atoi(s+i+1);
1237 	}
1238 
1239 	/* Terminate */
1240 	base[i] = '\0';
1241 
1242 
1243 	/* Build base_font */
1244 	strcpy(base_font, base);
1245 	strcat(base_font, ".FON");
1246 
1247 
1248 	/* Access the font file */
1249 	path_build(buf, 1024, ANGBAND_DIR_XTRA_FONT, base_font);
1250 
1251 
1252 	/* Verify file */
1253 	if (!check_file(buf)) return (1);
1254 
1255 
1256 	/* Save new font name */
1257 	td->font_file = string_make(buf);
1258 
1259 	/* If this font is used for the first time */
1260 	if (!term_font_inuse(td))
1261 	{
1262 		/* Load the new font or quit */
1263 		if (!AddFontResource(buf))
1264 		{
1265 			quit_fmt("Font file corrupted:\n%s", buf);
1266 		}
1267 	}
1268 
1269 	/* Create the font XXX XXX XXX Note use of "base" */
1270 	td->font_id = CreateFont(hgt, wid, 0, 0, FW_DONTCARE, 0, 0, 0,
1271 	                         ANSI_CHARSET, OUT_DEFAULT_PRECIS,
1272 	                         CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
1273 	                         FIXED_PITCH | FF_DONTCARE, base);
1274 
1275 
1276 	/* Hack -- Unknown size */
1277 	if (!wid || !hgt)
1278 	{
1279 		HDC         hdcDesktop;
1280 		HFONT       hfOld;
1281 		TEXTMETRIC  tm;
1282 
1283 		/* all this trouble to get the cell size */
1284 		hdcDesktop = GetDC(HWND_DESKTOP);
1285 		hfOld = SelectObject(hdcDesktop, td->font_id);
1286 		GetTextMetrics(hdcDesktop, &tm);
1287 		SelectObject(hdcDesktop, hfOld);
1288 		ReleaseDC(HWND_DESKTOP, hdcDesktop);
1289 
1290 		/* Font size info */
1291 		wid = tm.tmAveCharWidth;
1292 		hgt = tm.tmHeight;
1293 	}
1294 
1295 	/* Save the size info */
1296 	td->font_wid = wid;
1297 	td->font_hgt = hgt;
1298 
1299 
1300 	/* Analyze the font */
1301 	term_getsize(td);
1302 
1303 	/* Resize the window */
1304 	term_window_resize(td);
1305 
1306 	/* Success */
1307 	return (0);
1308 }
1309 
1310 
1311 #ifdef USE_GRAPHICS
1312 
1313 /*
1314  * Force the use of a new "graf file" for a term_data
1315  *
1316  * This function is never called before the windows are ready
1317  *
1318  * This function returns zero only if everything succeeds.
1319  */
term_force_graf(term_data * td,graphics_mode * gm)1320 static errr term_force_graf(term_data *td, graphics_mode *gm)
1321 {
1322 	int i, is_png = 0;
1323 
1324 	int wid, hgt;
1325 
1326 	cptr s;
1327 
1328 	char buf[1024];
1329 
1330 	/* No name */
1331 	if (!gm->file) return (1);
1332 
1333 	/* Extract the base name (with suffix) */
1334 	s = gm->file;
1335 
1336 	/* Extract font width */
1337 	wid = gm->cell_width;
1338 
1339 	/* Default font height */
1340 	hgt = gm->cell_height;
1341 
1342 	/* Require actual sizes */
1343 	if (!wid || !hgt) return (1);
1344 
1345 	/* Check if we need PNG loader */
1346 	if (isuffix(s, ".png")) is_png = TRUE;
1347 
1348 	/* Access the graf file */
1349 	path_build(buf, 1024, ANGBAND_DIR_XTRA_GRAF, gm->file);
1350 
1351 	/* Verify file */
1352 	if (!check_file(buf)) return (1);
1353 
1354 	/* Note: PNG loader will extract the mask from the alpha
1355 	 * channel, or assume colorkey is at pixel0,0 */
1356 	if (is_png)
1357 	{
1358 		/* Load the png or quit */
1359  		if (!ReadDIB2_PNG(td->w, buf, &infGraph, &infMask, FALSE))
1360 		{
1361 			quit_fmt("Cannot read file '%s'", buf);
1362 		}
1363 	}
1364 	else
1365 	{
1366 		/* Load the bitmap or quit */
1367 		if (!ReadDIB(td->w, buf, &infGraph))
1368 		{
1369 			quit_fmt("Bitmap corrupted:\n%s", buf);
1370 		}
1371 
1372 		/* Load mask, if appropriate */
1373 		if (!STRZERO(gm->mask))
1374 		{
1375 			/* Access the mask file */
1376 			path_build(buf, sizeof(buf), ANGBAND_DIR_XTRA_GRAF, gm->mask);
1377 
1378 			/* Load the bitmap or quit */
1379 			if (!ReadDIB(win_data[0].w, buf, &infMask))
1380 			{
1381 				quit_fmt("Cannot read bitmap mask file '%s'", buf);
1382 			}
1383 		}
1384 	}
1385 	/* Save the new sizes */
1386 	infGraph.CellWidth = wid;
1387 	infGraph.CellHeight = hgt;
1388 
1389 	/* Copy the picture from the bitmap to the window */
1390 //	BitBlt(hdc, x2, y2, w1, h1, hdcSrc, x1, y1, SRCCOPY);
1391 
1392 	/* Activate a palette */
1393 	if (!new_palette())
1394 	{
1395 		/* Free bitmap XXX XXX XXX */
1396 
1397 		/* Oops */
1398 		plog("Cannot activate palette!");
1399 		return (FALSE);
1400 	}
1401 	/* Graphics available */
1402 	can_use_graphics = use_graphics;
1403 
1404 	/* Success */
1405 	return (can_use_graphics);
1406 }
1407 
1408 #endif
1409 
1410 
1411 /*
1412  * Allow the user to change the font (and graf) for this window.
1413  *
1414  * XXX XXX XXX This is only called for non-graphic windows
1415  */
term_change_font(term_data * td)1416 static void term_change_font(term_data *td)
1417 {
1418 	OPENFILENAME ofn;
1419 	TCHAR fullFileName[2048];
1420 	char tmp[1024] = "";
1421 
1422 	/* Extract a default if possible */
1423 	if (td->font_file) strcpy(tmp, td->font_file);
1424 
1425 	/* No default? Let's build it */
1426 	if (STRZERO(tmp))
1427 	{
1428 		strnfmt(tmp, 1024, "%s%s", ANGBAND_DIR_XTRA_FONT, "\\*.fon");
1429 	}
1430 
1431 	/* Resolve absolute path */
1432 	if (_fullpath(fullFileName, tmp, 2048) == NULL)
1433 	{
1434 		/* Complete and utter despair... */
1435 		strcpy(fullFileName, "\\*.fon");
1436 	}
1437 
1438 	/* Ask for a choice */
1439 	memset(&ofn, 0, sizeof(ofn));
1440 	ofn.lStructSize = sizeof(ofn);
1441 	ofn.hwndOwner = win_data[0].w;
1442 	ofn.lpstrFilter = "Font Files (*.fon)\0*.fon\0";
1443 	ofn.nFilterIndex = 1;
1444 	ofn.lpstrFile = fullFileName;
1445 	ofn.nMaxFile = 128;
1446 	ofn.lpstrInitialDir = NULL;
1447 
1448 	ofn.Flags = OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR;
1449 	ofn.lpstrDefExt = "fon";
1450 
1451 	/* Force choice if legal */
1452 	if (GetOpenFileName(&ofn))
1453 	{
1454 		/* Force the font */
1455 		if (term_force_font(td, fullFileName))
1456 		{
1457 			/* Oops */
1458 			(void)term_force_font(td, "8X13.FON");
1459 		}
1460 	}
1461 }
1462 
1463 
1464 #ifdef USE_GRAPHICS
1465 
1466 #if 0 /* Manual change disabled */
1467 /*
1468  * Allow the user to change the graf (and font) for a window
1469  *
1470  * XXX XXX XXX This is only called for graphic windows, and
1471  * changes the font and the bitmap for the window, and is
1472  * only called if "use_graphics" is true.
1473  */
1474 static void term_change_bitmap(term_data *td)
1475 {
1476 	OPENFILENAME ofn;
1477 
1478 	char tmp[128] = "";
1479 
1480 	/* Ask for a choice */
1481 	memset(&ofn, 0, sizeof(ofn));
1482 	ofn.lStructSize = sizeof(ofn);
1483 	ofn.hwndOwner = win_data[0].w;
1484 	ofn.lpstrFilter = "Bitmap Files (*.bmp)\0*.bmp\0";
1485 	ofn.nFilterIndex = 1;
1486 	ofn.lpstrFile = tmp;
1487 	ofn.nMaxFile = 128;
1488 	ofn.lpstrInitialDir = ANGBAND_DIR_XTRA_GRAF;
1489 	ofn.Flags = OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR;
1490 	ofn.lpstrDefExt = "bmp";
1491 
1492 	/* Force choice if legal */
1493 	if (GetOpenFileName(&ofn))
1494 	{
1495 		/* XXX XXX XXX */
1496 
1497 		/* Force the requested font and bitmap */
1498 		if (
1499 		    term_force_graf(td, tmp))
1500 		{
1501 			graphics_mode *gm;
1502 			/* Force the "standard" font */
1503 			//(void)term_force_font(td, "8X13.FON");
1504 
1505 			/* Force the "standard" bitmap */
1506 			gm = get_graphics_mode((byte)use_graphics);
1507 			(void)term_force_graf(td, gm ? gm->file : "");
1508 		}
1509 	}
1510 }
1511 #endif
1512 
1513 #endif
1514 
1515 
1516 /*
1517  * Hack -- redraw a term_data
1518  */
term_data_redraw(term_data * td)1519 static void term_data_redraw(term_data *td)
1520 {
1521 	/* Activate the term */
1522 	Term_activate(&td->t);
1523 
1524 	/* Redraw the contents */
1525 	Term_redraw();
1526 
1527 	/* Restore the term */
1528 	Term_activate(term_screen);
1529 }
1530 /*
1531  * Hack -- resize term_data
1532  */
term_data_resize(term_data * td,bool redraw)1533 static void term_data_resize(term_data *td, bool redraw)
1534 {
1535 	/* Activate the term */
1536 	Term_activate(&td->t);
1537 
1538 	/* Redraw the contents */
1539 	if (redraw)	Term_redraw();
1540 
1541 	/* Resize! */
1542 	Term_resize(td->cols, td->rows);
1543 
1544 	/* Restore the term */
1545 	Term_activate(term_screen);
1546 }
1547 
1548 
1549 
1550 
1551 
1552 /*** Function hooks needed by "Term" ***/
1553 
1554 /*
1555  * Interact with the User
1556  */
Term_user_win(int n)1557 static errr Term_user_win(int n)
1558 {
1559 	/* Success */
1560 	return (0);
1561 }
1562 
1563 
1564 /*
1565  * React to global changes
1566  */
Term_xtra_win_react(void)1567 static errr Term_xtra_win_react(void)
1568 {
1569 	int i;
1570 
1571 /*	I added this USE_GRAPHICS because we lost color support as well. -GP */
1572 #ifdef USE_GRAPHICS
1573 	static old_use_graphics = FALSE;
1574 
1575 
1576 	/* XXX XXX XXX Check "color_table[]" */
1577 
1578 
1579 	/* Simple color */
1580 	if (colors16)
1581 	{
1582 		/* Save the default colors */
1583 		for (i = 0; i < 16; i++)
1584 		{
1585 			/* Simply accept the desired colors */
1586 			win_pal[i] = color_table[i][0];
1587 		}
1588 	}
1589 
1590 	/* Complex color */
1591 	else
1592 	{
1593 		COLORREF code;
1594 
1595 		byte rv, gv, bv;
1596 
1597 		bool change = FALSE;
1598 
1599 		/* Save the default colors */
1600 		for (i = 0; i < 16; i++)
1601 		{
1602 			/* Extract desired values */
1603 			rv = color_table[i][1];
1604 			gv = color_table[i][2];
1605 			bv = color_table[i][3];
1606 
1607 			/* Extract a full color code */
1608 			code = PALETTERGB(rv, gv, bv);
1609 
1610 			/* Activate changes */
1611 			if (win_clr[i] != code)
1612 			{
1613 				/* Note the change */
1614 				change = TRUE;
1615 
1616 				/* Apply the desired color */
1617 				win_clr[i] = code;
1618 			}
1619 		}
1620 
1621 		/* Activate the palette if needed */
1622 		if (change) (void)new_palette();
1623 	}
1624 #endif	/* no color support -gp */
1625 
1626 #ifdef USE_SOUND
1627     /* Initialize sound (if needed) */
1628     if (use_sound && !init_sound())
1629     {
1630         /* Warning */
1631         plog("Cannot initialize sound!");
1632 
1633         /* Cannot enable */
1634         use_sound = FALSE;
1635     }
1636 #endif /* USE_SOUND */
1637 
1638 #ifdef USE_GRAPHICS
1639 
1640 	/* XXX XXX XXX Check "use_graphics" */
1641 	if (use_graphics && !old_use_graphics)
1642 	{
1643 		/*
1644 		 * Code for reacting to graphical changes.
1645 		 */
1646 	}
1647 
1648 	/* Remember */
1649 	old_use_graphics = use_graphics;
1650 
1651 #endif
1652 
1653 
1654 	/* Clean up windows */
1655 	for (i = 0; i < MAX_TERM_DATA; i++)
1656 	{
1657 		term *old = Term;
1658 
1659 		term_data *td = &win_data[i];
1660 
1661 		/* Skip non-changes XXX XXX XXX */
1662 		if ((td->cols == td->t.wid) && (td->rows == td->t.hgt)) continue;
1663 
1664 		/* Activate */
1665 		Term_activate(&td->t);
1666 
1667 
1668 		InvalidateRect(td->w, NULL, TRUE);
1669 		/* Hack -- Resize the term */
1670 		//Term_resize(td->cols, td->rows);
1671 
1672 		/* Redraw the contents */
1673 		Term_redraw();
1674 
1675 		/* Restore */
1676 		Term_activate(old);
1677 	}
1678 
1679 
1680 	/* Success */
1681 	return (0);
1682 }
1683 
1684 
1685 /*
1686  * Process at least one event
1687  */
Term_xtra_win_event(int v)1688 static errr Term_xtra_win_event(int v)
1689 {
1690 	MSG msg;
1691 
1692 	/* Wait for an event */
1693 	if (v)
1694 	{
1695 		/* Block */
1696 		if (GetMessage(&msg, NULL, 0, 0))
1697 		{
1698 			TranslateMessage(&msg);
1699 			DispatchMessage(&msg);
1700 		}
1701 	}
1702 
1703 	/* Check for an event */
1704 	else
1705 	{
1706 		/* Check */
1707 		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
1708 		{
1709 			TranslateMessage(&msg);
1710 			DispatchMessage(&msg);
1711 		}
1712 	}
1713 
1714 	/* Success */
1715 	return 0;
1716 }
1717 
1718 
1719 /*
1720  * Process all pending events
1721  */
Term_xtra_win_flush(void)1722 static errr Term_xtra_win_flush(void)
1723 {
1724 	MSG msg;
1725 
1726 	/* Process all pending events */
1727 	while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
1728 	{
1729 		TranslateMessage(&msg);
1730 		DispatchMessage(&msg);
1731 	}
1732 
1733 	/* Success */
1734 	return (0);
1735 }
1736 
1737 
1738 /*
1739  * Hack -- clear the screen
1740  *
1741  * XXX XXX XXX Make this more efficient
1742  */
Term_xtra_win_clear(void)1743 static errr Term_xtra_win_clear(void)
1744 {
1745 	term_data *td = (term_data*)(Term->data);
1746 
1747 	HDC  hdc;
1748 	RECT rc;
1749 
1750 	/* Rectangle to erase */
1751 	rc.left   = td->size_ow1;
1752 	rc.right  = rc.left + td->cols * td->font_wid;
1753 	rc.top    = td->size_oh1;
1754 	rc.bottom = rc.top + td->rows * td->font_hgt;
1755 
1756 	/* Erase it */
1757 	hdc = GetDC(td->w);
1758 	SetBkColor(hdc, RGB(0, 0, 0));
1759 	SelectObject(hdc, td->font_id);
1760 	ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1761 	ReleaseDC(td->w, hdc);
1762 
1763 	/* Success */
1764 	return 0;
1765 }
1766 
1767 
1768 /*
1769  * Hack -- make a noise
1770  */
Term_xtra_win_noise(void)1771 static errr Term_xtra_win_noise(void)
1772 {
1773 	MessageBeep(MB_ICONASTERISK);
1774 	return (0);
1775 }
1776 
1777 
1778 /*
1779  * Hack -- make a sound
1780  */
Term_xtra_win_sound(int v)1781 static errr Term_xtra_win_sound(int v)
1782 {
1783 #ifdef USE_SOUND
1784 	char buf[MSG_LEN];
1785 	int s = sound_count(v);
1786 
1787 	/* Illegal sound */
1788 	if (!s) return (-1);
1789 
1790 	/* Random sample */
1791 	s = randint0(s);
1792 
1793 	/* Build the path */
1794 	path_build(buf, sizeof(buf), ANGBAND_DIR_XTRA_SOUND, sound_file[v][s]);
1795 
1796 	/* Play the sound */
1797 	return PlaySound(buf, NULL, SND_FILENAME | SND_ASYNC);
1798 #else
1799 	/* Oops */
1800 	return (1);
1801 #endif /* USE_SOUND */
1802 }
1803 
1804 
1805 /*
1806  * Delay for "x" milliseconds
1807  */
Term_xtra_win_delay(int v)1808 int Term_xtra_win_delay(int v)
1809 {
1810 
1811 #ifdef WIN32
1812 
1813 	/* Sleep */
1814 	Sleep(v);
1815 
1816 #else /* WIN32 */
1817 
1818 	DWORD t;
1819 	MSG   msg;
1820 
1821 	/* Final count */
1822 	t = GetTickCount() + v;
1823 
1824 	/* Wait for it */
1825 	while (GetTickCount() < t)
1826 	{
1827 		/* Handle messages */
1828 		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
1829 		{
1830 			TranslateMessage(&msg);
1831 			DispatchMessage(&msg);
1832 		}
1833 	}
1834 
1835 #endif /* WIN32 */
1836 
1837 	/* Success */
1838 	return (0);
1839 }
1840 
1841 
1842 /*
1843  * Do a "special thing"
1844  */
Term_xtra_win(int n,int v)1845 static errr Term_xtra_win(int n, int v)
1846 {
1847 	/* Handle a subset of the legal requests */
1848 	switch (n)
1849 	{
1850 		/* Make a bell sound */
1851 		case TERM_XTRA_NOISE:
1852 		return (Term_xtra_win_noise());
1853 
1854 		/* Make a special sound */
1855 		case TERM_XTRA_SOUND:
1856 		return (Term_xtra_win_sound(v));
1857 
1858 		/* Process random events */
1859 		case TERM_XTRA_BORED:
1860 		return (Term_xtra_win_event(0));
1861 
1862 		/* Process an event */
1863 		case TERM_XTRA_EVENT:
1864 		return (Term_xtra_win_event(v));
1865 
1866 		/* Flush all events */
1867 		case TERM_XTRA_FLUSH:
1868 		return (Term_xtra_win_flush());
1869 
1870 		/* Clear the screen */
1871 		case TERM_XTRA_CLEAR:
1872 		return (Term_xtra_win_clear());
1873 
1874 		/* React to global changes */
1875 		case TERM_XTRA_REACT:
1876 		return (v == 0 ? Term_xtra_win_react() : 0);
1877 
1878 		/* Delay for some milliseconds */
1879 		case TERM_XTRA_DELAY:
1880 		return (Term_xtra_win_delay(v));
1881 	}
1882 
1883 	/* Oops */
1884 	return 1;
1885 }
1886 
1887 
1888 
1889 /*
1890  * Low level graphics (Assumes valid input).
1891  *
1892  * Erase a "block" of "n" characters starting at (x,y).
1893  */
Term_wipe_win(int x,int y,int n)1894 static errr Term_wipe_win(int x, int y, int n)
1895 {
1896 	term_data *td = (term_data*)(Term->data);
1897 
1898 	HDC  hdc;
1899 	RECT rc;
1900 
1901 #ifdef USE_GRAPHICS
1902 	/* [grk] Client-side scrolling support
1903 	 * This is a kludge see declaration of x_offset */
1904 //	if(td == &win_data[0]){
1905 //		x = x - x_offset;
1906 //		if(x+n<13) return 0;
1907 //		if(x<13){
1908 //			n = n + (x-13);
1909 //			x = 13;
1910 //		}
1911 //	}
1912 #endif
1913 	/* Rectangle to erase in client coords */
1914 	rc.left   = x * td->font_wid + td->size_ow1;
1915 	rc.right  = rc.left + n * td->font_wid;
1916 	rc.top    = y * td->font_hgt + td->size_oh1;
1917 	rc.bottom = rc.top + td->font_hgt;
1918 
1919 	hdc = GetDC(td->w);
1920 	SetBkColor(hdc, RGB(0, 0, 0));
1921 	SelectObject(hdc, td->font_id);
1922 	ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1923 	ReleaseDC(td->w, hdc);
1924 
1925 	/* Success */
1926 	return 0;
1927 }
1928 
1929 
1930 /*
1931  * Low level graphics (Assumes valid input).
1932  * Draw a "cursor" at (x,y), using a "yellow box".
1933  */
Term_curs_win(int x,int y)1934 static errr Term_curs_win(int x, int y)
1935 {
1936 	term_data *td = (term_data*)(Term->data);
1937 
1938 	RECT   rc;
1939 	HDC    hdc;
1940 
1941 	/* Frame the grid */
1942 	rc.left   = x * td->font_wid + td->size_ow1;
1943 	rc.right  = rc.left + td->font_wid;
1944 	rc.top    = y * td->font_hgt + td->size_oh1;
1945 	rc.bottom = rc.top + td->font_hgt;
1946 
1947 	/* Cursor is done as a yellow "box" */
1948 	hdc = GetDC(win_data[0].w);
1949 	FrameRect(hdc, &rc, hbrYellow);
1950 	ReleaseDC(win_data[0].w, hdc);
1951 
1952 	/* Success */
1953 	return 0;
1954 }
1955 
1956 
1957 /*
1958  * Low level graphics.  Assumes valid input.
1959  * Draw a "special" attr/char at the given location.
1960  *
1961  * XXX XXX XXX We use the "Term_pict_win()" function for "graphic" data,
1962  * which are encoded by setting the "high-bits" of both the "attr" and
1963  * the "char" data.  We use the "attr" to represent the "row" of the main
1964  * bitmap, and the "char" to represent the "col" of the main bitmap.  The
1965  * use of this function is induced by the "higher_pict" flag.
1966  *
1967  * If we are called for anything but the "screen" window, or if the global
1968  * "use_graphics" flag is off, we simply "wipe" the given grid.
1969  */
1970 // static errr Term_pict_win(int x, int y, byte a, char c)
Term_pict_win(int x,int y,int n,const byte * ap,const char * cp,const byte * tap,const char * tcp)1971 static errr Term_pict_win(int x, int y, int n, const byte *ap, const char *cp, const byte *tap, const char *tcp)
1972 {
1973 	term_data *td = (term_data*)(Term->data);
1974 
1975 #ifdef USE_GRAPHICS
1976 
1977 	HDC  hdc;
1978 	HDC hdcSrc;
1979 	HDC hdcMask;
1980 	HBITMAP hbmSrcOld;
1981 	int row, col;
1982 	int i;
1983 	int x1, y1, w1, h1;
1984 	int x2, y2, w2, h2;
1985 	int x3, y3;
1986 	graphics_mode *gm;
1987 
1988 	/* Paranoia -- handle weird requests */
1989 	if (!use_graphics)
1990 	{
1991 		/* First, erase the grid */
1992 		return (Term_wipe_win(x, y, 1));
1993 	}
1994 
1995 	gm = get_graphics_mode((byte)use_graphics);
1996 
1997 	Term_wipe_win(x, y, n);
1998 
1999 #ifdef USE_GRAPHICS
2000 	/* [grk] Client-side scrolling support
2001 	 * This is a kludge see declaration of x_offset */
2002 //	if(td == &win_data[0]){
2003 //		x = x - x_offset;
2004 //		if(x<13) return 0;
2005 //	}
2006 #endif
2007 
2008 	/* Extract picture info */
2009 //	row = ((int)ap & 0x7F);
2010 //	col = ((int)cp & 0x7F);
2011 
2012 	/* Size of bitmap cell */
2013 	w1 = infGraph.CellWidth;
2014 	h1 = infGraph.CellHeight;
2015 
2016 	/* Location of bitmap cell */
2017 //	x1 = col * w1;
2018 //	y1 = row * h1;
2019 
2020 	/* Size of window cell */
2021 	w2 = td->font_wid;
2022 	h2 = td->font_hgt;
2023 
2024 	/* Location of window cell */
2025 	x2 = x * w2 + td->size_ow1;
2026 	y2 = y * h2 + td->size_oh1;
2027 
2028 	/* Info */
2029 	hdc = GetDC(td->w);
2030 
2031 	/* More info */
2032 	hdcSrc = CreateCompatibleDC(hdc);
2033 	hbmSrcOld = SelectObject(hdcSrc, infGraph.hBitmap);
2034 
2035 	if (gm->transparent)
2036 	{
2037 		hdcMask = CreateCompatibleDC(hdc);
2038 		SelectObject(hdcMask, infMask.hBitmap);
2039 	}
2040 	else
2041 	{
2042 		hdcMask = NULL;
2043 	}
2044 
2045 	/* Draw attr/char pairs */
2046 	for (i = 0; i < n; i++, x2 += w2)
2047 	{
2048 		byte a = ap[i];
2049 		char c = cp[i];
2050 
2051 		/* Extract picture */
2052 		int row = (a & 0x7F);
2053 		int col = (c & 0x7F);
2054 
2055 		/* Location of bitmap cell */
2056 		x1 = col * w1;
2057 		y1 = row * h1;
2058 
2059 		if (gm->transparent)
2060 		{
2061 			x3 = (tcp[i] & 0x7F) * w1;
2062 			y3 = (tap[i] & 0x7F) * h1;
2063 
2064 			/* Perfect size */
2065 			if ((w1 == w2) && (h1 == h2))
2066 			{
2067 				/* Copy the terrain picture from the bitmap to the window */
2068 				BitBlt(hdc, x2, y2, w2, h2, hdcSrc, x3, y3, SRCCOPY);
2069 
2070 				/* Only draw if terrain and overlay are different */
2071 				if ((x1 != x3) || (y1 != y3))
2072 				{
2073 					/* Mask out the tile */
2074 					BitBlt(hdc, x2, y2, w2, h2, hdcMask, x1, y1, SRCAND);
2075 
2076 					/* Draw the tile */
2077 					BitBlt(hdc, x2, y2, w2, h2, hdcSrc, x1, y1, SRCPAINT);
2078 				}
2079 			}
2080 
2081 			/* Need to stretch */
2082 			else
2083 			{
2084 				/* Set the correct mode for stretching the tiles */
2085 				SetStretchBltMode(hdc, COLORONCOLOR);
2086 
2087 				/* Copy the terrain picture from the bitmap to the window */
2088 				StretchBlt(hdc, x2, y2, w2, h2, hdcSrc, x3, y3, w1, h1, SRCCOPY);
2089 
2090 				/* Only draw if terrain and overlay are different */
2091 				if ((x1 != x3) || (y1 != y3))
2092 				{
2093 					/* Mask out the tile */
2094 					StretchBlt(hdc, x2, y2, w2, h2, hdcMask, x1, y1, w1, h1, SRCAND);
2095 
2096 					/* Draw the tile */
2097 					StretchBlt(hdc, x2, y2, w2, h2, hdcSrc, x1, y1, w1, h1, SRCPAINT);
2098 				}
2099 			}
2100 		}
2101 		else
2102 		{
2103 			/* Perfect size */
2104 			if ((w1 == w2) && (h1 == h2))
2105 			{
2106 				/* Copy the picture from the bitmap to the window */
2107 				BitBlt(hdc, x2, y2, w2, h2, hdcSrc, x1, y1, SRCCOPY);
2108 			}
2109 
2110 			/* Need to stretch */
2111 			else
2112 			{
2113 				/* Set the correct mode for stretching the tiles */
2114 				SetStretchBltMode(hdc, COLORONCOLOR);
2115 
2116 				/* Copy the picture from the bitmap to the window */
2117 				StretchBlt(hdc, x2, y2, w2, h2, hdcSrc, x1, y1, w1, h1, SRCCOPY);
2118 			}
2119 		}
2120 	}
2121 
2122 	/* Release */
2123 	SelectObject(hdcSrc, hbmSrcOld);
2124 	DeleteDC(hdcSrc);
2125 
2126 	if (gm->transparent)
2127 	{
2128 		/* Release */
2129 		SelectObject(hdcMask, hbmSrcOld);
2130 		DeleteDC(hdcMask);
2131 	}
2132 
2133 	/* Release */
2134 	ReleaseDC(td->w, hdc);
2135 
2136 #else
2137 
2138 	/* Just erase this grid */
2139 	return (Term_wipe_win(x, y, 1));
2140 
2141 #endif
2142 
2143 	/* Success */
2144 	return 0;
2145 }
2146 
2147 
2148 /*
2149  * Low level graphics.  Assumes valid input.
2150  * Draw several ("n") chars, with an attr, at a given location.
2151  *
2152  * All "graphic" data is handled by "Term_pict_win()", above.
2153  *
2154  * XXX XXX XXX Note that this function assumes the font is monospaced.
2155  *
2156  * XXX XXX XXX One would think there is a more efficient method for
2157  * telling a window what color it should be using to draw with, but
2158  * perhaps simply changing it every time is not too inefficient.
2159  */
Term_text_win(int x,int y,int n,byte a,const char * s)2160 static errr Term_text_win(int x, int y, int n, byte a, const char *s)
2161 {
2162 	term_data *td = (term_data*)(Term->data);
2163 	RECT rc;
2164 	HDC  hdc;
2165 
2166 #ifdef USE_GRAPHICS
2167 	/* [grk] Client-side scrolling support
2168 	 * This is a kludge see declaration of x_offset */
2169 //	if(td == &win_data[0] && (y!=0) ){
2170 //		if(x>13){
2171 //			x = x - x_offset;
2172 //			if(x<13) return 0;
2173 //		}
2174 //	}
2175 #endif
2176 
2177 	/* Location */
2178 	rc.left   = x * td->font_wid + td->size_ow1;
2179 	rc.right  = rc.left + n * td->font_wid;
2180 	rc.top    = y * td->font_hgt + td->size_oh1;
2181 	rc.bottom = rc.top + td->font_hgt;
2182 
2183 	/* Acquire DC */
2184 	hdc = GetDC(td->w);
2185 
2186 	/* Background color */
2187 	SetBkColor(hdc, RGB(0, 0, 0));
2188 
2189 	/* Foreground color */
2190 	if (colors16)
2191 	{
2192 		SetTextColor(hdc, PALETTEINDEX(win_pal[a&0x0F]));
2193 	}
2194 	else
2195 	{
2196 		SetTextColor(hdc, win_clr[a&0x0F]);
2197 	}
2198 
2199 	/* Use the font */
2200 	SelectObject(hdc, td->font_id);
2201 
2202 	/* Dump the text */
2203 	ExtTextOut(hdc, rc.left, rc.top, ETO_OPAQUE | ETO_CLIPPED, &rc,
2204 	           s, n, NULL);
2205 
2206 	/* Release DC */
2207 	ReleaseDC(td->w, hdc);
2208 
2209 	/* Success */
2210 	return 0;
2211 }
2212 
2213 
2214 /*** Other routines ***/
2215 
2216 
2217 /*
2218  * Create and initialize a "term_data" given a title
2219  */
term_data_link(term_data * td)2220 static void term_data_link(term_data *td)
2221 {
2222 	term *t = &td->t;
2223 
2224 	/* Initialize the term */
2225 	term_init(t, td->cols, td->rows, td->keys);
2226 
2227 	/* Use a "software" cursor */
2228 	t->soft_cursor = TRUE;
2229 
2230 	/* Use "Term_pict" for "graphic" data */
2231 	t->higher_pict = TRUE;
2232 
2233 	/* Erase with "white space" */
2234 	t->attr_blank = TERM_WHITE;
2235 	t->char_blank = ' ';
2236 
2237 	/* Prepare the template hooks */
2238 	t->user_hook = Term_user_win;
2239 	t->xtra_hook = Term_xtra_win;
2240 	t->wipe_hook = Term_wipe_win;
2241 	t->curs_hook = Term_curs_win;
2242 	t->pict_hook = Term_pict_win;
2243 	t->text_hook = Term_text_win;
2244 
2245 	/* Remember where we came from */
2246 	t->data = (vptr)(td);
2247 }
2248 
2249 
2250 /*
2251  * Create the windows
2252  *
2253  * First, instantiate the "default" values, then read the "ini_file"
2254  * to over-ride selected values, then create the windows, and fonts.
2255  *
2256  * XXX XXX XXX Need to work on the default window positions
2257  *
2258  * Must use SW_SHOW not SW_SHOWNA, since on 256 color display
2259  * must make active to realize the palette. (?)
2260  */
init_windows(void)2261 static void init_windows(void)
2262 {
2263 	int i;
2264 	static char version[20];
2265 	term_data *td;
2266 	HFONT editfont;
2267 
2268 	/* Main window */
2269 	td = &win_data[0];
2270 	WIPE(td, term_data);
2271 
2272     sprintf(version, "Mangband %d.%d.%d",
2273 			CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_PATCH);
2274 	td->s = version;
2275 	td->keys = 1024;
2276 	td->rows = 24;
2277 	td->cols = 80;
2278 	td->visible = TRUE;
2279 	td->size_ow1 = 2;
2280 	td->size_ow2 = 2;
2281 	td->size_oh1 = 2;
2282 	td->size_oh2 = 2;
2283 	td->pos_x = 0;
2284 	td->pos_y = 0;
2285 
2286 	/* Sub-windows */
2287 	for (i = 1; i < MAX_TERM_DATA; i++)
2288 	{
2289 		/* Mirror window */
2290 		td = &win_data[i];
2291 		WIPE(td, term_data);
2292 		td->s = ang_term_name[i];
2293 		td->keys = 16;
2294 		td->rows = 24;
2295 		td->cols = 80;
2296 		td->visible = TRUE;
2297 		td->size_ow1 = 1;
2298 		td->size_ow2 = 1;
2299 		td->size_oh1 = 1;
2300 		/* Hack - give term4 space for edit control [grk] */
2301 		if(i!=4) td->size_oh2 = 1;
2302 		else td->size_oh2 = 30;
2303 		td->pos_x = 0;
2304 		td->pos_y = 0;
2305 	}
2306 
2307 
2308 	/* Load .INI preferences */
2309 	load_prefs();
2310 
2311 
2312 	/* Need these before term_getsize gets called */
2313 	win_data[0].dwStyle = (WS_OVERLAPPED | WS_SYSMENU | WS_THICKFRAME |
2314 	                   WS_MINIMIZEBOX | WS_CAPTION | WS_VISIBLE);
2315 	win_data[0].dwExStyle = 0;
2316 
2317 	/* Windows */
2318 	for (i = 1; i < MAX_TERM_DATA; i++)
2319 	{
2320 		win_data[i].dwStyle = (WS_OVERLAPPED | WS_THICKFRAME | WS_SYSMENU);
2321 		win_data[i].dwExStyle = (WS_EX_TOOLWINDOW);
2322 	}
2323 
2324 
2325 	/* Windows */
2326 	for (i = 0; i < MAX_TERM_DATA; i++)
2327 	{
2328 		if (term_force_font(&win_data[i], win_data[i].font_want))
2329 		{
2330 			(void)term_force_font(&win_data[i], "8X13.FON");
2331 		}
2332 	}
2333 
2334 
2335 	/* Screen window */
2336 	td_ptr = &win_data[0];
2337 	td_ptr->w = CreateWindowEx(td_ptr->dwExStyle, AppName,
2338 	                           td_ptr->s, td_ptr->dwStyle,
2339 	                           td_ptr->pos_x, td_ptr->pos_y,
2340 	                           td_ptr->size_wid, td_ptr->size_hgt,
2341 	                           HWND_DESKTOP, NULL, hInstance, NULL);
2342 	if (!td_ptr->w) quit("Failed to create Angband window");
2343 	td_ptr = NULL;
2344 	term_data_link(&win_data[0]);
2345 	ang_term[0] = &win_data[0].t;
2346 
2347 	/* Windows */
2348 	for (i = 1; i < MAX_TERM_DATA; i++)
2349 	{
2350 		td_ptr = &win_data[i];
2351 		td_ptr->w = CreateWindowEx(td_ptr->dwExStyle, AngList,
2352 		                           td_ptr->s, td_ptr->dwStyle,
2353 		                           td_ptr->pos_x, td_ptr->pos_y,
2354 		                           td_ptr->size_wid, td_ptr->size_hgt,
2355 		                           HWND_DESKTOP, NULL, hInstance, NULL);
2356 		if (!td_ptr->w) quit("Failed to create sub-window");
2357 		if (td_ptr->visible)
2358 		{
2359 			td_ptr->size_hack = TRUE;
2360 			ShowWindow(td_ptr->w, SW_SHOW);
2361 			td_ptr->size_hack = FALSE;
2362 		}
2363 		td_ptr = NULL;
2364 		term_data_link(&win_data[i]);
2365 		ang_term[i] = &win_data[i].t;
2366 	}
2367 
2368 	/* hack [grk] */
2369 	editmsg = CreateWindowEx(WS_EX_STATICEDGE,"EDIT",NULL,WS_CHILD|ES_AUTOHSCROLL|ES_OEMCONVERT|WS_VISIBLE,
2370 						 2,win_data[4].client_hgt-24,win_data[4].client_wid-8,20,win_data[4].w,NULL,hInstance,NULL);
2371 	editfont=CreateFont(16,0,0,0,FW_NORMAL,FALSE,FALSE,FALSE,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,PROOF_QUALITY,DEFAULT_PITCH,"Arial");
2372 	SendMessage(editmsg, WM_SETFONT, (int)editfont, (int)NULL );
2373 	stretch_chat_ctrl();
2374 
2375 	SendMessage(editmsg, EM_LIMITTEXT, 590, 0L);
2376 	lpfnOldWndProc = (WNDPROC)SetWindowLongPtr(editmsg, GWL_WNDPROC, (DWORD) SubClassFunc);
2377 
2378 	/* Activate the screen window */
2379 	SetActiveWindow(win_data[0].w);
2380 
2381 	/* Bring main screen back to top */
2382 	SetWindowPos(win_data[0].w, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
2383 
2384 
2385 #ifdef USE_GRAPHICS
2386 
2387 	/* Handle "graphics" mode */
2388 	if (use_graphics)
2389 	{
2390 		/* XXX XXX XXX Force the "standard" bitmap */
2391 		graphics_mode *gm = get_graphics_mode((byte)use_graphics);
2392 
2393 		(void)term_force_graf(&win_data[0], gm);
2394 	}
2395 
2396 #endif
2397 
2398 #ifdef USE_SOUND
2399 	/* Handle sound module */
2400 	Term_xtra_win_react();
2401 #endif
2402 
2403 	/* New palette XXX XXX XXX */
2404 	(void)new_palette();
2405 
2406 
2407 	/* Create a "brush" for drawing the "cursor" */
2408 	hbrYellow = CreateSolidBrush(win_clr[TERM_YELLOW]);
2409 
2410 	/* Create a "brush" for drawing the chat window edit control background */
2411 	hbrBlack = CreateSolidBrush(0);
2412 
2413 	/* Process pending messages */
2414 	(void)Term_xtra_win_flush();
2415 }
2416 
2417 
has_addr_aux(cptr pmsgbuf,int mode,char * addrbuf,size_t addrmax,size_t * addrlen)2418 static char* has_addr_aux(cptr pmsgbuf, int mode, char* addrbuf, size_t addrmax, size_t* addrlen)
2419 {
2420 	int offset,breakpoint,nicklen;
2421 	char * startmsg;
2422 	char search_for = ':';
2423 	offset = 0;
2424 	if (mode == 1)
2425 	{
2426 		search_for = ' ';
2427 		if (pmsgbuf[0] != '#')
2428 		{
2429 			*addrlen = 0;
2430 			return pmsgbuf;
2431 		}
2432 	}
2433 	for (startmsg = pmsgbuf; *startmsg ; startmsg++ ) {
2434 		if( *startmsg==search_for ) break;
2435 	};
2436 	if( *startmsg  && (startmsg-pmsgbuf<addrmax) ) {
2437 		strncpy(addrbuf,pmsgbuf,(startmsg-pmsgbuf)+1);
2438 		nicklen=strlen(addrbuf);
2439 		startmsg+=1;
2440 		while (*startmsg == ' ') startmsg+=1;
2441 	} else {
2442 		startmsg=pmsgbuf;
2443 		nicklen=0;
2444 	};
2445 	*addrlen = nicklen;
2446 	return startmsg;
2447 }
has_addr(cptr msg,char * addrbuf,size_t addrmax,size_t * addrlen)2448 static char* has_addr(cptr msg, char* addrbuf, size_t addrmax, size_t* addrlen)
2449 {
2450 	char *r;
2451 	/* Check channel */
2452 	r = has_addr_aux(msg, 1, addrbuf, addrmax, addrlen);
2453 	if (*addrlen > 0) return r;
2454 
2455 	/* Check privmsg */
2456 	r = has_addr_aux(msg, 0, addrbuf, addrmax, addrlen);
2457 	if (*addrlen > 0) return r;
2458 
2459 	/* OK, got nothing */
2460 	*addrlen = 0;
2461 	return msg;
2462 }
2463 
2464 /* hack - edit control subclass [grk] */
SubClassFunc(HWND hWnd,UINT Message,WPARAM wParam,LPARAM lParam)2465 LRESULT APIENTRY SubClassFunc(   HWND hWnd,
2466                UINT Message,
2467                WPARAM wParam,
2468                LPARAM lParam)
2469 {
2470 	char pmsgbuf[1000]; /* overkill */
2471 	char pmsg[MSG_LEN + 2];
2472 	char nickbuf[30];
2473 
2474 	/* Allow ESCAPE to return focus to main window. */
2475 	if( Message == WM_KEYDOWN ) {
2476 		if( wParam == VK_ESCAPE ){
2477 		unset_chat_focus();
2478 		return 0;
2479 		}
2480 		if (wParam == 33) { /* PGUP */
2481 			cmd_chat_cycle(-1);
2482 			return 0;
2483 		}
2484 		if (wParam == 34) { /* PGDN */
2485 			cmd_chat_cycle(+1);
2486 			return 0;
2487 		}
2488 	}
2489 
2490 	if ( Message == WM_CHAR ) {
2491 		/* Is this RETURN ? */
2492 		if( wParam == 13 || wParam == 10000) {
2493 			int CUTOFF=0;
2494 			int msglen=0;
2495 			memset(nickbuf,0,22);
2496 
2497 			/* Get the controls text and send it */
2498 			msglen = GetWindowText(editmsg, pmsgbuf, 999);
2499 
2500 			/* Send the text in chunks of CUTOFF characters,
2501 			   or nearest break before CUTOFF chars */
2502 
2503 			if( msglen == 0 ){
2504 			    unset_chat_focus();
2505 			    return 0;
2506 			}
2507 			/* Max message length depends on our nick (known)
2508 			 * and recepient nick (unknown, assume max length) */
2509 			CUTOFF = MSG_LEN - strlen(nick) - 3; /* 3 is for decorative symbols */
2510 			CUTOFF -= (MAX_NAME_LEN+1); /* +1 for ':' symbol in private messages */
2511 /*RLS*/
2512 			if( msglen < CUTOFF ){
2513 				send_msg(pmsgbuf);
2514 			} else{
2515 				int offset,breakpoint,nicklen;
2516 				char * startmsg;
2517 				offset = 0;
2518 
2519 				/* see if this was a privmsg, if so, pull off the nick */
2520 
2521 				startmsg = has_addr(pmsgbuf, nickbuf, 29, &nicklen);
2522 
2523 				/* now deal with what's left */
2524 
2525 				while(msglen>0){
2526 					memset(pmsg,0,MSG_LEN);
2527 
2528 					if(msglen<CUTOFF){
2529 						breakpoint=msglen;
2530 					} else{
2531 						/* try to find a breaking char */
2532 						for(breakpoint=CUTOFF; breakpoint>0; breakpoint--) {
2533 							if( startmsg[offset+breakpoint] == ' ' ) break;
2534 							if( startmsg[offset+breakpoint] == ',' ) break;
2535 							if( startmsg[offset+breakpoint] == '.' ) break;
2536 							if( startmsg[offset+breakpoint] == ';' ) break;
2537 						};
2538 						if(!breakpoint) breakpoint=CUTOFF; /* nope */
2539 					}
2540 
2541 					/* if we pulled off a nick above, prepend it. */
2542 					if(nicklen) strncpy(pmsg,nickbuf,nicklen);
2543 
2544 					/* stash in this part of the msg */
2545 					strncat(pmsg, startmsg+offset, breakpoint);
2546 					msglen -= breakpoint;
2547 					offset += breakpoint;
2548 					send_msg(pmsg);
2549 					//Net_flush();
2550 				}
2551 			}
2552 
2553 			/* Clear the message box */
2554 			pmsgbuf[0] = 0;
2555 			SetWindowText(editmsg, pmsgbuf);
2556 			unset_chat_focus();
2557 			return 0;
2558 		}
2559 	}
2560 
2561 	return CallWindowProc(lpfnOldWndProc, hWnd, Message, wParam, lParam);
2562 }
2563 
2564 
2565 /*
2566  * Hack -- disables new and open from file menu
2567  */
disable_start(void)2568 static void disable_start(void)
2569 {
2570 	HMENU hm = GetMenu(win_data[0].w);
2571 
2572 	EnableMenuItem(hm, IDM_FILE_NEW, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
2573 	EnableMenuItem(hm, IDM_FILE_OPEN, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
2574 }
2575 
2576 
2577 /*
2578  * Prepare the menus
2579  *
2580  * XXX XXX XXX See the updated "main-mac.c" for a much nicer
2581  * system, basically, you explicitly disable any menu option
2582  * which the user should not be allowed to use, and then you
2583  * do not have to do any checking when processing the menu.
2584  */
setup_menus(void)2585 static void setup_menus(void)
2586 {
2587 	int i;
2588 
2589 	HMENU hm = GetMenu(win_data[0].w);
2590 #ifdef MNU_SUPPORT
2591 	/* Save player */
2592 	EnableMenuItem(hm, IDM_FILE_SAVE,
2593 	               MF_BYCOMMAND | MF_ENABLED | MF_GRAYED);
2594 
2595 
2596 	/* Exit with save */
2597 	EnableMenuItem(hm, IDM_FILE_EXIT,
2598 	               MF_BYCOMMAND | MF_ENABLED | MF_GRAYED);
2599 
2600 
2601 	/* Window font options */
2602 	for (i = 1; i < MAX_TERM_DATA; i++)
2603 	{
2604 		/* Window font */
2605 		EnableMenuItem(hm, IDM_TEXT_SCREEN + i,
2606 		               MF_BYCOMMAND | (win_data[i].visible ? MF_ENABLED : MF_DISABLED | MF_GRAYED));
2607 	}
2608 
2609 	/* Window options */
2610 	for (i = 1; i < MAX_TERM_DATA; i++)
2611 	{
2612 		/* Window */
2613 		CheckMenuItem(hm, IDM_WINDOWS_SCREEN + i,
2614 		              MF_BYCOMMAND | (win_data[i].visible ? MF_CHECKED : MF_UNCHECKED));
2615 	}
2616 #endif
2617 #ifdef USE_GRAPHICS
2618 	/* Item "Graphics - Off" */
2619 	CheckMenuItem(hm, IDM_GRAPHICS_OFF,
2620 	              MF_BYCOMMAND | (!next_graphics ? MF_CHECKED : MF_UNCHECKED));
2621 
2622 	/* Item "Graphics - Tileset N" */
2623 	for (i = 0; i < 8; i++)
2624 	{
2625 		/* Replace "Tileset N" string with actual tileset name */
2626 		if ((1 + i) <= get_num_graphics_modes())
2627 		{
2628 			graphics_mode *gm = get_graphics_mode((byte)(1 + i));
2629 			MENUITEMINFO menuitem = { sizeof(MENUITEMINFO) };
2630 			GetMenuItemInfo(hm, IDM_GRAPHICS_TILESET_1 + i, FALSE, &menuitem);
2631 			menuitem.fMask = MIIM_TYPE | MIIM_DATA;
2632 			menuitem.dwTypeData = gm->menuname;
2633 			SetMenuItemInfo(hm, IDM_GRAPHICS_TILESET_1 + i, FALSE, &menuitem);
2634 		}
2635 
2636 		/* Item "Graphics - Tileset N" */
2637 		CheckMenuItem(hm, IDM_GRAPHICS_TILESET_1 + i,
2638 		              MF_BYCOMMAND | (next_graphics == 1 + i ? MF_CHECKED : MF_UNCHECKED));
2639 
2640 		/* XXX Delete unused menu entries */
2641 		if ((1 + i) > get_num_graphics_modes())
2642 		RemoveMenu(hm, IDM_GRAPHICS_TILESET_1 + i, MF_BYCOMMAND);
2643 	}
2644 
2645 	/* Item "Graphics - Respect Tile Size?" */
2646 	CheckMenuItem(hm, IDM_GRAPHICS_BIG_TILE,
2647 	              MF_BYCOMMAND | (big_tile ? MF_CHECKED : MF_UNCHECKED));
2648 #endif
2649 #ifdef USE_SOUND
2650 	/* Item "Sound" */
2651 	CheckMenuItem(hm, IDM_OPTIONS_SOUND,
2652 	              MF_BYCOMMAND | (use_sound ? MF_CHECKED : MF_UNCHECKED));
2653 #endif
2654 
2655 	/* Item "Mouse" */
2656 	CheckMenuItem(hm, IDM_OPTIONS_MOUSE,
2657 	              MF_BYCOMMAND | (use_mouse ? MF_CHECKED : MF_UNCHECKED));
2658 
2659 #ifdef BEN_HACK
2660 	/* Item "Colors 16" */
2661 	EnableMenuItem(hm, IDM_OPTIONS_UNUSED,
2662 	               MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
2663 #endif
2664 
2665 #ifndef ALLOW_SCRSAVER
2666 	/* Item "Run as Screensaver" */
2667 	EnableMenuItem(hm, IDM_OPTIONS_SAVER,
2668 	               MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
2669 #endif
2670 
2671 }
2672 
2673 
2674 /*
2675  * Check for double clicked (or dragged) savefile
2676  *
2677  * Apparently, Windows copies the entire filename into the first
2678  * piece of the "command line string".  Perhaps we should extract
2679  * the "basename" of that filename and append it to the "save" dir.
2680  */
check_for_save_file(LPSTR cmd_line)2681 static void check_for_save_file(LPSTR cmd_line)
2682 {
2683 	char *s, *p;
2684 
2685 	/* First arg */
2686 	s = cmd_line;
2687 
2688 	/* Second arg */
2689 	p = strchr(s, ' ');
2690 
2691 	/* Tokenize, advance */
2692 	if (p) *p++ = '\0';
2693 
2694 	/* No args */
2695 	if (!*s) return;
2696 
2697 /* More stuff moved to server -GP
2698 	// Extract filename
2699 	strcat(savefile, s);
2700 
2701 	// Validate the file
2702 	validate_file(savefile);
2703 */
2704 	/* Game in progress */
2705 	game_in_progress = TRUE;
2706 
2707 	/* No restarting */
2708 	disable_start();
2709 
2710 	/* Play game */
2711 /*	play_game(FALSE);	-changed to network call -GP */
2712 }
2713 
dDialogProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)2714 BOOL CALLBACK dDialogProc(
2715   HWND hwndDlg,  // handle to dialog box
2716   UINT uMsg,     // message
2717   WPARAM wParam, // first message parameter
2718   LPARAM lParam  // second message parameter
2719 )
2720 {
2721 	switch( uMsg ){
2722 		case WM_COMMAND:
2723 			EndDialog(hwndDlg,0);
2724 	}
2725 	return 0;
2726 }
2727 
2728 /*
2729  * Process a menu command
2730  */
process_menus(WORD wCmd)2731 static void process_menus(WORD wCmd)
2732 {
2733 #ifdef	MNU_SUPPORT
2734 	int i;
2735 
2736 	/* Analyze */
2737 	switch (wCmd)
2738 	{
2739 		/* Save and Exit */
2740 		case IDM_FILE_EXIT:
2741 		{
2742 			quit(NULL);
2743 			break;
2744 		}
2745 
2746 
2747 		case IDM_TEXT_SCREEN:
2748 		{
2749 
2750 #ifdef USE_GRAPHICS
2751 			/* XXX XXX XXX */
2752 			//if (use_graphics)
2753 			//{
2754 			//	term_change_bitmap(&win_data[0]);
2755 			//	break;
2756 			//}
2757 #endif
2758 
2759 			term_change_font(&win_data[0]);
2760 			break;
2761 		}
2762 
2763 		/* Window fonts */
2764 		case IDM_TEXT_MIRROR:
2765 		case IDM_TEXT_RECALL:
2766 		case IDM_TEXT_CHOICE:
2767 		case IDM_TEXT_TERM_4:
2768 		case IDM_TEXT_TERM_5:
2769 		case IDM_TEXT_TERM_6:
2770 		case IDM_TEXT_TERM_7:
2771 		{
2772 			i = wCmd - IDM_TEXT_SCREEN;
2773 
2774 			if ((i < 0) || (i >= MAX_TERM_DATA)) break;
2775 
2776 			term_change_font(&win_data[i]);
2777 
2778 			break;
2779 		}
2780 
2781 		/* Window visibility */
2782 		case IDM_WINDOWS_MIRROR:
2783 		case IDM_WINDOWS_RECALL:
2784 		case IDM_WINDOWS_CHOICE:
2785 		case IDM_WINDOWS_TERM_4:
2786 		case IDM_WINDOWS_TERM_5:
2787 		case IDM_WINDOWS_TERM_6:
2788 		case IDM_WINDOWS_TERM_7:
2789 		{
2790 			i = wCmd - IDM_WINDOWS_SCREEN;
2791 
2792 			if ((i < 0) || (i >= MAX_TERM_DATA)) break;
2793 
2794 			if (!win_data[i].visible)
2795 			{
2796 				win_data[i].visible = TRUE;
2797 				ShowWindow(win_data[i].w, SW_SHOW);
2798 				term_data_redraw(&win_data[i]);
2799 			}
2800 			else
2801 			{
2802 				win_data[i].visible = FALSE;
2803 				ShowWindow(win_data[i].w, SW_HIDE);
2804 			}
2805 
2806 			break;
2807 		}
2808 
2809 		/* Hack -- unused */
2810 		case IDM_OPTIONS_UNUSED:
2811 		{
2812 			/* XXX XXX XXX */
2813 			break;
2814 		}
2815 /*	Currently no graphics options available. -GP */
2816 #ifdef USE_GRAPHICS
2817 		case IDM_GRAPHICS_OFF:
2818 		{
2819 			set_graphics_next(0);
2820 			break;
2821 		}
2822 		case IDM_GRAPHICS_TILESET_1:
2823 		case IDM_GRAPHICS_TILESET_2:
2824 		case IDM_GRAPHICS_TILESET_3:
2825 		case IDM_GRAPHICS_TILESET_4:
2826 		case IDM_GRAPHICS_TILESET_5:
2827 		case IDM_GRAPHICS_TILESET_6:
2828 		case IDM_GRAPHICS_TILESET_7:
2829 		case IDM_GRAPHICS_TILESET_8:
2830 		{
2831 			set_graphics_next(wCmd - IDM_GRAPHICS_TILESET_1 + 1);
2832 			break;
2833 			/* no support -GP */
2834 			/* React to changes */
2835 			//Term_xtra_win_react();
2836 
2837 			/* Hack -- Force redraw */
2838 			//Term_key_push(KTRL('R'));
2839 		}
2840 		case IDM_GRAPHICS_BIG_TILE:
2841 		{
2842 			static int old_font_wid, old_font_hgt;
2843 			/*
2844 			if (!big_tile)
2845 			{
2846 				old_font_wid = win_data[0].font_wid;
2847 				old_font_hgt = win_data[0].font_hgt;
2848 				win_data[0].font_wid = infGraph.CellHeight;
2849 				win_data[0].font_hgt = infGraph.CellHeight;
2850 			} else {
2851 				win_data[0].font_wid = old_font_wid;
2852 				win_data[0].font_hgt = old_font_hgt;
2853 			}
2854 			*/
2855 			x_offset = 20;
2856 			big_tile = !big_tile;
2857 
2858 			/* Hack -- Force redraw */
2859 			Term_key_push(KTRL('R'));
2860 			break;
2861 		}
2862 #endif
2863 		case IDM_OPTIONS_SOUND:
2864 		{
2865 			use_sound = !use_sound;
2866 			Term_xtra_win_react();
2867 			break;
2868 		}
2869 
2870 		case IDM_OPTIONS_MOUSE:
2871 		{
2872 			use_mouse = !use_mouse;
2873 			break;
2874 		}
2875 
2876 		case IDM_HELP_GENERAL:
2877 		{
2878 			char buf[1024];
2879 			char tmp[1024];
2880 			path_build(tmp, 1024, ANGBAND_DIR_XTRA_HELP, "angband.hlp");
2881 			sprintf(buf, "winhelp.exe %s", tmp);
2882 			WinExec(buf, SW_NORMAL);
2883 			break;
2884 		}
2885 
2886 		case IDM_HELP_SPOILERS:
2887 		{
2888 			char buf[1024];
2889 			char tmp[1024];
2890 			path_build(tmp, 1024, ANGBAND_DIR_XTRA_HELP, "spoilers.hlp");
2891 			sprintf(buf, "winhelp.exe %s", tmp);
2892 			WinExec(buf, SW_NORMAL);
2893 			break;
2894 		}
2895 		case IDM_HELP_ABOUT:
2896 		{
2897 			/*x_offset += 1;
2898 			Term_redraw();*/
2899 
2900 			DialogBox(hInstance, "ABOUT" ,win_data[0].w, dDialogProc );
2901 
2902 			break;
2903 		}
2904 
2905 	}
2906 #endif	/* MNU_SUPPORT */
2907 }
2908 
2909 #ifdef BEN_HACK
2910 LRESULT FAR PASCAL _export AngbandWndProc(HWND hWnd, UINT uMsg,
2911                                           WPARAM wParam, LPARAM lParam);
2912 #endif
2913 
AngbandWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)2914 LRESULT FAR PASCAL AngbandWndProc(HWND hWnd, UINT uMsg,
2915                                           WPARAM wParam, LPARAM lParam)
2916 {
2917 	PAINTSTRUCT     ps;
2918 	HDC             hdc;
2919 	term_data      *td;
2920 	MINMAXINFO FAR *lpmmi;
2921 	RECT            rc;
2922 	int             i;
2923 
2924 
2925 	/* Acquire proper "term_data" info */
2926 	td = (term_data *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
2927 
2928 	/* Handle message */
2929 	switch (uMsg)
2930 	{
2931 		/* XXX XXX XXX */
2932 		case WM_NCCREATE:
2933 		{
2934 			SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG)(td_ptr));
2935 			break;
2936 		}
2937 
2938 		/* XXX XXX XXX */
2939 		case WM_CREATE:
2940 		{
2941 			return 0;
2942 		}
2943 
2944 		case WM_GETMINMAXINFO:
2945 		{
2946 			lpmmi = (MINMAXINFO FAR *)lParam;
2947 
2948 			if (!td) return 1;  /* this message was sent before WM_NCCREATE */
2949 
2950 			/* Minimum window size is 8x2 */
2951 			rc.left = rc.top = 0;
2952 			rc.right = rc.left + 8 * td->font_wid + td->size_ow1 + td->size_ow2;
2953 			rc.bottom = rc.top + 2 * td->font_hgt + td->size_oh1 + td->size_oh2 + 1;
2954 
2955 			/* Adjust */
2956 			AdjustWindowRectEx(&rc, td->dwStyle, TRUE, td->dwExStyle);
2957 
2958 			/* Save minimum size */
2959 			lpmmi->ptMinTrackSize.x = rc.right - rc.left;
2960 			lpmmi->ptMinTrackSize.y = rc.bottom - rc.top;
2961 
2962 			/* Maximum window size */
2963 			rc.left = rc.top = 0;
2964 			rc.right = rc.left + (MAX_WID+SCREEN_CLIP_X) * td->font_wid + td->size_ow1 + td->size_ow2;
2965 			rc.bottom = rc.top + (MAX_HGT+SCREEN_CLIP_Y) * td->font_hgt + td->size_oh1 + td->size_oh2 + 1;
2966 
2967 			/* Paranoia */
2968 			rc.right  += (td->font_wid - 1);
2969 			rc.bottom += (td->font_hgt - 1);
2970 
2971 			/* Adjust */
2972 			AdjustWindowRectEx(&rc, td->dwStyle, TRUE, td->dwExStyle);
2973 
2974 			/* Save maximum size */
2975 			lpmmi->ptMaxSize.x      = rc.right - rc.left;
2976 			lpmmi->ptMaxSize.y      = rc.bottom - rc.top;
2977 
2978 			/* Save maximum size */
2979 			lpmmi->ptMaxTrackSize.x = rc.right - rc.left;
2980 			lpmmi->ptMaxTrackSize.y = rc.bottom - rc.top;
2981 
2982 			return 0;
2983 		}
2984 
2985 		case WM_PAINT:
2986 		{
2987 			BeginPaint(hWnd, &ps);
2988 			if (td) term_data_redraw(td);
2989 			EndPaint(hWnd, &ps);
2990 			ValidateRect(hWnd, NULL);   /* why needed ?? */
2991 			return 0;
2992 		}
2993 
2994 		case WM_SYSKEYDOWN:
2995 		case WM_KEYDOWN:
2996 		{
2997 			BYTE KeyState = 0x00;
2998 			bool enhanced = FALSE;
2999 			bool mc = FALSE;
3000 			bool ms = FALSE;
3001 			bool ma = FALSE;
3002 
3003 			/* Extract the modifiers */
3004 			if (GetKeyState(VK_CONTROL) & 0x8000) mc = TRUE;
3005 			if (GetKeyState(VK_SHIFT)   & 0x8000) ms = TRUE;
3006 			if (GetKeyState(VK_MENU)    & 0x8000) ma = TRUE;
3007 
3008 			/* Check for non-normal keys */
3009 			if ((wParam >= VK_PRIOR) && (wParam <= VK_DOWN)) enhanced = TRUE;
3010 			if ((wParam >= VK_F1) && (wParam <= VK_F12)) enhanced = TRUE;
3011 			if ((wParam == VK_INSERT) || (wParam == VK_DELETE)) enhanced = TRUE;
3012 
3013 			/* XXX XXX XXX */
3014 			if (enhanced)
3015 			{
3016 				/* Begin the macro trigger */
3017 				Term_keypress(31);
3018 
3019 				/* Send the modifiers */
3020 				if (mc) Term_keypress('C');
3021 				if (ms) Term_keypress('S');
3022 				if (ma) Term_keypress('A');
3023 
3024 				/* Extract "scan code" from bits 16..23 of lParam */
3025 				i = LOBYTE(HIWORD(lParam));
3026 
3027 				/* Introduce the scan code */
3028 				Term_keypress('x');
3029 
3030 				/* Encode the hexidecimal scan code */
3031 				Term_keypress(hexsym[i/16]);
3032 				Term_keypress(hexsym[i%16]);
3033 
3034 				/* End the macro trigger */
3035 				Term_keypress(13);
3036 
3037 				return 0;
3038 			}
3039 
3040 			break;
3041 		}
3042 
3043 		case WM_CHAR:
3044 		{
3045 			Term_keypress(wParam);
3046 			return 0;
3047 		}
3048 
3049 		case WM_LBUTTONDOWN:
3050 		case WM_MBUTTONDOWN:
3051 		case WM_RBUTTONDOWN:
3052 #if defined(WM_XBUTTONDOWN)
3053 		case WM_XBUTTONDOWN:
3054 #endif
3055 		{
3056 			int x = LOWORD(lParam);
3057 			int y = HIWORD(lParam);
3058 			int button = 1;
3059 
3060 			if (!td) return 1;    /* this message was sent before WM_NCCREATE */
3061 			if (!td->w) return 1; /* it was sent from inside CreateWindowEx */
3062 			if (!Term) return 1;  /* no active terminal yet */
3063 
3064 			x = x / td->font_wid;
3065 			y = y / td->font_hgt;
3066 
3067 			/* Which button */
3068 			if (uMsg == WM_LBUTTONDOWN) button = 1;
3069 			if (uMsg == WM_MBUTTONDOWN) button = 2;
3070 			if (uMsg == WM_RBUTTONDOWN) button = 3;
3071 #if defined(WM_XBUTTONDOWN)
3072 			if (uMsg == WM_XBUTTONDOWN) button = 3 + HIWORD(wParam);
3073 #endif
3074 
3075 			/* Extract the modifiers */
3076 			if (GetKeyState(VK_CONTROL) & 0x8000) button |= 16;
3077 			if (GetKeyState(VK_SHIFT)   & 0x8000) button |= 32;
3078 			if (GetKeyState(VK_MENU)    & 0x8000) button |= 64;
3079 
3080 			if (!use_mouse) return 0; /* No in-game mouse */
3081 
3082 			Term_mousepress(x, y, button);
3083 			return 0;
3084 		}
3085 
3086 		case WM_MOUSEMOVE:
3087 		{
3088 			int x = LOWORD(lParam);
3089 			int y = HIWORD(lParam);
3090 
3091 			if (!td) return 1;    /* this message was sent before WM_NCCREATE */
3092 			if (!td->w) return 1; /* it was sent from inside CreateWindowEx */
3093 			if (!Term) return 1;  /* no active terminal yet */
3094 
3095 			x = x / td->font_wid;
3096 			y = y / td->font_hgt;
3097 
3098 			Term_mousepress(x, y, 0);
3099 			return 0;
3100 		}
3101 
3102 		case WM_INITMENU:
3103 		{
3104 			setup_menus();
3105 			return 0;
3106 		}
3107 
3108 		case WM_CLOSE:
3109 		case WM_QUIT:
3110 		{
3111 			quit(NULL);
3112 			return 0;
3113 		}
3114 
3115 		case WM_COMMAND:
3116 		{
3117 			process_menus(LOWORD(wParam));
3118 			return 0;
3119 		}
3120 /*
3121 		case WM_ENTERSIZEMOVE:
3122 		{
3123 			return 0;
3124 		}
3125 */
3126 		case WM_EXITSIZEMOVE:
3127 		{
3128 			term *old = Term;
3129 
3130 			if (!td) return 1;    /* this message was sent before WM_NCCREATE */
3131 			if (!td->w) return 1; /* it was sent from inside CreateWindowEx */
3132 			if (!conn_state) return 1;
3133 
3134 			if (td->t.wid != td->cols || td->t.hgt != td->rows)
3135 			{
3136 				Term_resize(td->cols, td->rows);
3137 				net_term_manage(window_flag, window_flag, FALSE);
3138 			}
3139 
3140 			return 0;
3141 		}
3142 
3143 		case WM_SIZE:
3144 		{
3145 			if (!td) return 1;    /* this message was sent before WM_NCCREATE */
3146 			if (!td->w) return 1; /* it was sent from inside CreateWindowEx */
3147 			if (td->size_hack) return 1; /* was sent from WM_SIZE */
3148 
3149 			switch (wParam)
3150 			{
3151 				case SIZE_MINIMIZED:
3152 				{
3153 					for (i = 1; i < MAX_TERM_DATA; i++)
3154 					{
3155 						if (win_data[i].visible) ShowWindow(win_data[i].w, SW_HIDE);
3156 					}
3157 					return 0;
3158 				}
3159 
3160 				case SIZE_MAXIMIZED:
3161 				{
3162 					/* fall through XXX XXX XXX */
3163 				}
3164 
3165 				case SIZE_RESTORED:
3166 				{
3167 					term *old = Term;
3168 
3169 					td->size_hack = TRUE;
3170 
3171 					td->cols = (LOWORD(lParam) - td->size_ow1 - td->size_ow2) / td->font_wid;
3172 					td->rows = (HIWORD(lParam) - td->size_oh1 - td->size_oh2) / td->font_hgt;
3173 
3174 					term_getsize(td);
3175 
3176 					MoveWindow(hWnd, td->pos_x, td->pos_y, td->size_wid, td->size_hgt, TRUE);
3177 
3178 					td->size_hack = FALSE;
3179 
3180 					/* Windows */
3181 					for (i = 1; i < MAX_TERM_DATA; i++)
3182 					{
3183 						if (win_data[i].visible) ShowWindow(win_data[i].w, SW_SHOWNOACTIVATE);
3184 					}
3185 
3186 					/* Changed size (before loggin in) */
3187 					Term_resize(td->cols, td->rows);
3188 					if (!conn_state)
3189 					{
3190 						net_term_manage(window_flag, window_flag, FALSE);
3191 					}
3192 
3193 					return 0;
3194 				}
3195 			}
3196 			break;
3197 		}
3198 
3199 		case WM_PALETTECHANGED:
3200 		{
3201 			/* ignore if palette change caused by itself */
3202 			if ((HWND)wParam == hWnd) return FALSE;
3203 			/* otherwise, fall through!!! */
3204 		}
3205 
3206 		case WM_QUERYNEWPALETTE:
3207 		{
3208 			if (!paletted) return FALSE;
3209 			hdc = GetDC(hWnd);
3210 			SelectPalette(hdc, hPal, FALSE);
3211 			i = RealizePalette(hdc);
3212 			/* if any palette entries changed, repaint the window. */
3213 			if (i) InvalidateRect(hWnd, NULL, TRUE);
3214 			ReleaseDC(hWnd, hdc);
3215 			return FALSE;
3216 		}
3217 
3218 		case WM_ACTIVATE:
3219 		{
3220 			if (wParam && !HIWORD(lParam))
3221 			{
3222 				for (i = 1; i < MAX_TERM_DATA; i++)
3223 				{
3224 					SetWindowPos(win_data[i].w, hWnd, 0, 0, 0, 0,
3225 					             SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
3226 				}
3227 				SetFocus(hWnd);
3228 				return 0;
3229 			}
3230 			break;
3231 		}
3232 	}
3233 
3234 
3235 	/* Oops */
3236 	return DefWindowProc(hWnd, uMsg, wParam, lParam);
3237 }
3238 
3239 
3240 #ifdef BEN_HACK
3241 LRESULT FAR PASCAL _export AngbandListProc(HWND hWnd, UINT uMsg,
3242                                            WPARAM wParam, LPARAM lParam);
3243 #endif
3244 
AngbandListProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)3245 LRESULT FAR PASCAL AngbandListProc(HWND hWnd, UINT uMsg,
3246                                            WPARAM wParam, LPARAM lParam)
3247 {
3248 	term_data      *td;
3249 	MINMAXINFO FAR *lpmmi;
3250 	RECT            rc;
3251 	PAINTSTRUCT     ps;
3252 	HDC             hdc;
3253 	int             i,j;
3254 	char		pmsg[60];
3255 
3256 
3257 	/* Acquire proper "term_data" info */
3258 	td = (term_data *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
3259 
3260 	/* Process message */
3261 	switch (uMsg)
3262 	{
3263 		/* XXX XXX XXX */
3264 		case WM_NCCREATE:
3265 		{
3266 			SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG)(td_ptr));
3267 			break;
3268 		}
3269 
3270 		/* XXX XXX XXX */
3271 		case WM_CREATE:
3272 		{
3273 			return 0;
3274 		}
3275 
3276 		case 0x133: /* WM_CTLCOLOREDIT */
3277 		{
3278 			SetTextColor((HDC)wParam,0x00ffffff);
3279 			SetBkColor((HDC)wParam, 0);
3280 			return (int)hbrBlack;
3281 		}
3282 
3283                 /* GRK, wasn't trapping this so vis menus got messed up */
3284                 /* We fake a click on the visibilty menu when the close icon is clicked */
3285 
3286                 case WM_CLOSE:
3287                         /* Which term is closing ? */
3288                         j=-1;
3289                         for(i=0; i<MAX_TERM_DATA;i++)
3290                           if(&win_data[i] == td) j = i;
3291                         /* Click its menu entry */
3292                         if(j != -1) process_menus(211+j);
3293                         return 0;
3294 
3295 		case WM_GETMINMAXINFO:
3296 		{
3297 			if (!td) return 1;  /* this message was sent before WM_NCCREATE */
3298 
3299 			lpmmi = (MINMAXINFO FAR *)lParam;
3300 
3301 			/* Minimum size */
3302 			rc.left = rc.top = 0;
3303 			rc.right = rc.left + 8 * td->font_wid + td->size_ow1 + td->size_ow2;
3304 			rc.bottom = rc.top + 2 * td->font_hgt + td->size_oh1 + td->size_oh2;
3305 
3306 			/* Adjust */
3307 			AdjustWindowRectEx(&rc, td->dwStyle, TRUE, td->dwExStyle);
3308 
3309 			/* Save the minimum size */
3310 			lpmmi->ptMinTrackSize.x = rc.right - rc.left;
3311 			lpmmi->ptMinTrackSize.y = rc.bottom - rc.top;
3312 
3313 			/* Maximum window size */
3314 			rc.left = rc.top = 0;
3315 			rc.right = rc.left + 80 * td->font_wid + td->size_ow1 + td->size_ow2;
3316 			rc.bottom = rc.top + 24 * td->font_hgt + td->size_oh1 + td->size_oh2;
3317 
3318 			/* Paranoia */
3319 			rc.right += (td->font_wid - 1);
3320 			rc.bottom += (td->font_hgt - 1);
3321 
3322 			/* Adjust */
3323 			AdjustWindowRectEx(&rc, td->dwStyle, TRUE, td->dwExStyle);
3324 
3325 			/* Save maximum size */
3326 			lpmmi->ptMaxSize.x      = rc.right - rc.left;
3327 			lpmmi->ptMaxSize.y      = rc.bottom - rc.top;
3328 
3329 			/* Save the maximum size */
3330 			lpmmi->ptMaxTrackSize.x = rc.right - rc.left;
3331 			lpmmi->ptMaxTrackSize.y = rc.bottom - rc.top;
3332 
3333 			return 0;
3334 		}
3335 		case WM_EXITSIZEMOVE:
3336 		{
3337 			/* Force redraw to remove artifacts */
3338 			InvalidateRect(hWnd,NULL,TRUE);
3339 			return 0;
3340 		}
3341 		case WM_SIZE:
3342 		{
3343 			term *old = Term;
3344 
3345 			if (!td) return 1;    /* this message was sent before WM_NCCREATE */
3346 			if (!td->w) return 1; /* it was sent from inside CreateWindowEx */
3347 			if (td->size_hack) return 1; /* was sent from inside WM_SIZE */
3348 
3349 			td->size_hack = TRUE;
3350 
3351 			td->cols = (LOWORD(lParam) - td->size_ow1 - td->size_ow2) / td->font_wid;
3352 			td->rows = (HIWORD(lParam) - td->size_oh1 - td->size_oh2) / td->font_hgt;
3353 
3354 			term_getsize(td);
3355 
3356 			term_data_resize(td, FALSE);
3357 			/* Gross hack -- find needed terminal number */
3358 			for (i = 1; i < ANGBAND_TERM_MAX; i++) {
3359 				if ((ang_term[i]) == &(td->t)) {
3360 					p_ptr->window |= window_flag[i];
3361 				}
3362 			}
3363 			window_stuff();
3364 
3365 			MoveWindow(hWnd, td->pos_x, td->pos_y, td->size_wid, td->size_hgt, TRUE);
3366 			if(td == &win_data[4]) stretch_chat_ctrl();
3367 
3368 			td->size_hack = FALSE;
3369 
3370 			return 0;
3371 		}
3372 
3373 		case WM_PAINT:
3374 		{
3375 			BeginPaint(hWnd, &ps);
3376 			if (td) term_data_redraw(td);
3377 			EndPaint(hWnd, &ps);
3378 			return 0;
3379 		}
3380 
3381 		case WM_SYSKEYDOWN:
3382 		case WM_KEYDOWN:
3383 		{
3384 			BYTE KeyState = 0x00;
3385 			bool enhanced = FALSE;
3386 			bool mc = FALSE;
3387 			bool ms = FALSE;
3388 			bool ma = FALSE;
3389 
3390             /* Which term getting the keypress ? */
3391             j=-1;
3392             for(i=0; i<MAX_TERM_DATA;i++)
3393               if(&win_data[i] == td) j = i;
3394               /* If this is term7 we are sending a player message */
3395               if(j == 7){
3396 				/* Is this RETURN ? */
3397 				if( wParam == 13){
3398 					/* Get the controls text and send it */
3399 					GetWindowText(editmsg, pmsg, 59);
3400 					send_msg(pmsg);
3401 				}
3402 				/* If not return, ignore key */
3403 				return 0;
3404 			}
3405 
3406 			/* Extract the modifiers */
3407 			if (GetKeyState(VK_CONTROL) & 0x8000) mc = TRUE;
3408 			if (GetKeyState(VK_SHIFT)   & 0x8000) ms = TRUE;
3409 			if (GetKeyState(VK_MENU)    & 0x8000) ma = TRUE;
3410 
3411 			/* Check for non-normal keys */
3412 			if ((wParam >= VK_PRIOR) && (wParam <= VK_DOWN)) enhanced = TRUE;
3413 			if ((wParam >= VK_F1) && (wParam <= VK_F12)) enhanced = TRUE;
3414 			if ((wParam == VK_INSERT) || (wParam == VK_DELETE)) enhanced = TRUE;
3415 
3416 			/* XXX XXX XXX */
3417 			if (enhanced)
3418 			{
3419 				/* Begin the macro trigger */
3420 				Term_keypress(31);
3421 
3422 				/* Send the modifiers */
3423 				if (mc) Term_keypress('C');
3424 				if (ms) Term_keypress('S');
3425 				if (ma) Term_keypress('A');
3426 
3427 				/* Extract "scan code" from bits 16..23 of lParam */
3428 				i = LOBYTE(HIWORD(lParam));
3429 
3430 				/* Introduce the scan code */
3431 				Term_keypress('x');
3432 
3433 				/* Encode the hexidecimal scan code */
3434 				Term_keypress(hexsym[i/16]);
3435 				Term_keypress(hexsym[i%16]);
3436 
3437 				/* End the macro trigger */
3438 				Term_keypress(13);
3439 
3440 				return 0;
3441 			}
3442 
3443 			break;
3444 		}
3445 
3446 		case WM_CHAR:
3447 		{
3448 			Term_keypress(wParam);
3449 			return 0;
3450 		}
3451 
3452 		case WM_PALETTECHANGED:
3453 		{
3454 			/* ignore if palette change caused by itself */
3455 			if ((HWND)wParam == hWnd) return FALSE;
3456 			/* otherwise, fall through!!! */
3457 		}
3458 
3459 		case WM_QUERYNEWPALETTE:
3460 		{
3461 			if (!paletted) return 0;
3462 			hdc = GetDC(hWnd);
3463 			SelectPalette(hdc, hPal, FALSE);
3464 			i = RealizePalette(hdc);
3465 			/* if any palette entries changed, repaint the window. */
3466 			if (i) InvalidateRect(hWnd, NULL, TRUE);
3467 			ReleaseDC(hWnd, hdc);
3468 			return 0;
3469 		}
3470 
3471 		case WM_NCLBUTTONDOWN:
3472 		{
3473 			if (wParam == HTSYSMENU)
3474 			{
3475 				/* Hide sub-windows */
3476 				if (td != &win_data[0])
3477 				{
3478 					if (td->visible)
3479 					{
3480 						td->visible = FALSE;
3481 						ShowWindow(td->w, SW_HIDE);
3482 					}
3483 				}
3484 				return 0;
3485 			}
3486 			break;
3487 		}
3488 
3489 	}
3490 
3491 	return DefWindowProc(hWnd, uMsg, wParam, lParam);
3492 }
3493 
3494 
3495 #ifdef ALLOW_SCRSAVER
3496 
3497 #define MOUSE_SENS 40
3498 
AngbandSaverProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)3499 LRESULT FAR PASCAL _export AngbandSaverProc(HWND hWnd, UINT uMsg,
3500                                             WPARAM wParam, LPARAM lParam)
3501 {
3502 	static int iMouse = 0;
3503 	static WORD xMouse = 0;
3504 	static WORD yMouse = 0;
3505 
3506 	int dx, dy;
3507 
3508 	term_data *td;
3509 
3510 
3511 	/* Acquire proper "term_data" info */
3512 	td = (term_data *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
3513 
3514 	/* Process */
3515 	switch (uMsg)
3516 	{
3517 		/* XXX XXX XXX */
3518 		case WM_NCCREATE:
3519 		{
3520 			SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG)(td_ptr));
3521 			break;
3522 		}
3523 
3524 		case WM_SETCURSOR:
3525 		{
3526 			SetCursor(NULL);
3527 			return 0;
3528 		}
3529 
3530 #if 0
3531 		case WM_ACTIVATE:
3532 		{
3533 			if (LOWORD(wParam) == WA_INACTIVE) break;
3534 
3535 			/* else fall through */
3536 		}
3537 #endif
3538 
3539 		case WM_LBUTTONDOWN:
3540 		case WM_MBUTTONDOWN:
3541 		case WM_RBUTTONDOWN:
3542 		case WM_KEYDOWN:
3543 		{
3544 			SendMessage(hWnd, WM_CLOSE, 0, 0);
3545 			return 0;
3546 		}
3547 
3548 		case WM_MOUSEMOVE:
3549 		{
3550 			if (iMouse)
3551 			{
3552 				dx = LOWORD(lParam) - xMouse;
3553 				dy = HIWORD(lParam) - yMouse;
3554 
3555 				if (dx < 0) dx = -dx;
3556 				if (dy < 0) dy = -dy;
3557 
3558 				if ((dx > MOUSE_SENS) || (dy > MOUSE_SENS))
3559 				{
3560 					SendMessage(hWnd, WM_CLOSE, 0, 0);
3561 				}
3562 			}
3563 
3564 			iMouse = 1;
3565 			xMouse = LOWORD(lParam);
3566 			yMouse = HIWORD(lParam);
3567 			return 0;
3568 		}
3569 
3570 		case WM_CLOSE:
3571 		{
3572 			DestroyWindow(hWnd);
3573 			return 0;
3574 		}
3575 	}
3576 
3577 	/* Oops */
3578 	return DefWindowProc(hWnd, uMsg, wParam, lParam);
3579 }
3580 
3581 #endif
3582 
3583 
3584 
3585 
3586 
3587 /*** Temporary Hooks ***/
3588 
3589 
3590 /*
3591  * Error message -- See "z-util.c"
3592  */
hack_plog(cptr str)3593 static void hack_plog(cptr str)
3594 {
3595 	/* Give a warning */
3596 /*	if (str) c_msg_print(str); */
3597 	if (str) MessageBox(NULL, str, "Warning", MB_OK);
3598 }
3599 
3600 
3601 /*
3602  * Quit with error message -- See "z-util.c"
3603  */
hack_quit(cptr str)3604 static void hack_quit(cptr str)
3605 {
3606 	int i;
3607 
3608 	/* Force saving of preferences on any quit [grk] */
3609 	save_prefs();
3610 
3611 	/* Give a warning */
3612 	if (str && str[0]) MessageBox(NULL, str, "Error", MB_OK | MB_ICONSTOP);
3613 
3614 	/* Sub-Windows */
3615 	for (i = MAX_TERM_DATA - 1; i >= 1; i--)
3616 	{
3617 		term_force_font(&win_data[i], NULL);
3618 		if (win_data[i].font_want) string_free(win_data[i].font_want);
3619 		if (win_data[i].graf_want) string_free(win_data[i].graf_want);
3620 		if (win_data[i].w) DestroyWindow(win_data[i].w);
3621 		win_data[i].w = 0;
3622 	}
3623 
3624 #ifdef USE_GRAPHICS
3625 	/* Free the bitmap stuff */
3626 	FreeDIB(&infGraph);
3627 	FreeDIB(&infMask);
3628 #endif
3629 	/* Forget grafmodes */
3630 	close_graphics_modes();
3631 
3632 
3633 	term_force_font(&win_data[0], NULL);
3634 	if (win_data[0].font_want) string_free(win_data[0].font_want);
3635 	if (win_data[0].graf_want) string_free(win_data[0].graf_want);
3636 	if (win_data[0].w) DestroyWindow(win_data[0].w);
3637 	win_data[0].w = 0;
3638 
3639 	/* Unregister the classes */
3640 	UnregisterClass(AppName, hInstance);
3641 
3642 	/* Destroy the icon */
3643 	if (hIcon) DestroyIcon(hIcon);
3644 
3645 	/* Cleanup WinSock */
3646 	cleanup_network_client();
3647 
3648 	/* Exit */
3649 	exit (0);
3650 }
3651 
3652 
3653 /*
3654  * Fatal error (see "z-util.c")
3655  */
hack_core(cptr str)3656 static void hack_core(cptr str)
3657 {
3658 	/* Give a warning */
3659 	if (str) MessageBox(NULL, str, "Error", MB_OK | MB_ICONSTOP);
3660 
3661 	/* Quit */
3662 	quit (NULL);
3663 }
3664 
3665 
3666 /*** Various hooks ***/
3667 
3668 
3669 /*
3670  * Error message -- See "z-util.c"
3671  */
hook_plog(cptr str)3672 static void hook_plog(cptr str)
3673 {
3674 	/* Warning */
3675 	if (str) MessageBox(win_data[0].w, str, "Warning", MB_OK);
3676 }
3677 
3678 
3679 /*
3680  * Quit with error message -- See "z-util.c"
3681  *
3682  * A lot of this function should be handled by actually calling
3683  * the "term_nuke()" function hook for each window.  XXX XXX XXX
3684  */
hook_quit(cptr str)3685 static void hook_quit(cptr str)
3686 {
3687 	int i;
3688 
3689 #ifdef USE_SOUND
3690 	int j;
3691 #endif /* USE_SOUND */
3692 
3693 	/* Give a warning */
3694 	if (str) MessageBox(win_data[0].w, str, "Error", MB_OK | MB_ICONSTOP);
3695 
3696 
3697 	/* Save the preferences */
3698 	save_prefs();
3699 
3700 	/* Sub-Windows */
3701 	for (i = MAX_TERM_DATA - 1; i >= 1; i--)
3702 	{
3703 		term_force_font(&win_data[i], NULL);
3704 		if (win_data[i].font_want) string_free(win_data[i].font_want);
3705 		if (win_data[i].graf_want) string_free(win_data[i].graf_want);
3706 		if (win_data[i].w) DestroyWindow(win_data[i].w);
3707 		win_data[i].w = 0;
3708 	}
3709 
3710 #ifdef USE_GRAPHICS
3711 	/* Free the bitmap stuff */
3712 	FreeDIB(&infGraph);
3713 	FreeDIB(&infMask);
3714 #endif
3715 
3716 #ifdef USE_SOUND
3717 	/* Free the sound names */
3718 	for (i = 0; i < MSG_MAX; i++)
3719 	{
3720 		for (j = 0; j < SAMPLE_MAX; j++)
3721 		{
3722 			if (!sound_file[i][j]) break;
3723 
3724 			string_free(sound_file[i][j]);
3725 		}
3726 	}
3727 #endif /* USE_SOUND */
3728 
3729 	term_force_font(&win_data[0], NULL);
3730 	if (win_data[0].font_want) string_free(win_data[0].font_want);
3731 	if (win_data[0].graf_want) string_free(win_data[0].graf_want);
3732 	if (win_data[0].w) DestroyWindow(win_data[0].w);
3733 	win_data[0].w = 0;
3734 
3735 
3736 	/*** Free some other stuff ***/
3737 
3738 	DeleteObject(hbrYellow);
3739 
3740 	if (hPal) DeleteObject(hPal);
3741 
3742 	UnregisterClass(AppName, hInstance);
3743 
3744 	if (hIcon) DestroyIcon(hIcon);
3745 
3746 	//network_done();
3747 
3748 	/* Free strings */
3749 
3750 	exit(0);
3751 }
3752 
3753 
3754 
3755 /*** Initialize ***/
3756 
3757 
3758 /*
3759  * Init some stuff
3760  */
init_stuff_win(void)3761 void static init_stuff_win(void)
3762 {
3763 	int   i;
3764 
3765 	char path[1024];
3766 
3767 #ifdef USE_GRAPHICS
3768 	graphics_mode *gm;
3769 #endif
3770 
3771 	/* XXX XXX XXX */
3772 	strcpy(path, conf_get_string("Windows32", "LibPath", ".\\lib"));
3773 
3774 	/* Analyze the path */
3775 	i = strlen(path);
3776 
3777 	/* Require a path */
3778 	if (!i) quit("LibPath shouldn't be empty in ANGBAND.INI");
3779 
3780 	/* Nuke terminal backslash */
3781 	if (i && (path[i-1] != '\\'))
3782 	{
3783 		path[i++] = '\\';
3784 		path[i] = '\0';
3785 	}
3786 
3787 	/* Validate the path */
3788 	validate_dir(path);
3789 
3790 
3791 	/* Init the file paths */
3792 
3793 	init_file_paths(path);
3794 
3795 	/* Hack -- Validate the paths */
3796 
3797 /*	validate_dir(ANGBAND_DIR_APEX); *//*on server */
3798 /*	validate_dir(ANGBAND_DIR_EDIT); */
3799 /*	validate_dir(ANGBAND_DIR_FILE); */
3800 /*	validate_dir(ANGBAND_DIR_HELP); */
3801 	validate_dir(ANGBAND_DIR_BONE);
3802 	validate_dir(ANGBAND_DIR_PREF);
3803 	validate_dir(ANGBAND_DIR_USER);
3804 	validate_dir(ANGBAND_DIR_XTRA);	  /*sounds & graphics */
3805 
3806 
3807 	// Build the "font" path
3808 	path_build(path, 1024, ANGBAND_DIR_XTRA, "font");
3809 
3810 	// Allocate the path
3811 	ANGBAND_DIR_XTRA_FONT = string_make(path);
3812 
3813 	// Validate the "font" directory
3814 	validate_dir(ANGBAND_DIR_XTRA_FONT);
3815 
3816 	// Build the filename
3817 	path_build(path, 1024, ANGBAND_DIR_XTRA_FONT, "8X13.FON");
3818 
3819 	// Hack -- Validate the basic font
3820 	validate_file(path);
3821 
3822 
3823 #ifdef USE_GRAPHICS
3824 
3825 	/* Validate the "graf" directory */
3826 	validate_dir(ANGBAND_DIR_XTRA_GRAF);
3827 
3828 	/* Pick graphics mode */
3829 	if ((gm = get_graphics_mode((byte)use_graphics)))
3830 	{
3831 		/* Build the filename */
3832 		path_build(path, 1024, ANGBAND_DIR_XTRA_GRAF, gm->file);
3833 
3834 		/* Hack -- Validate the basic graf */
3835 		validate_file(path);
3836 	}
3837 #endif
3838 
3839 
3840 #ifdef USE_SOUND
3841 
3842 	/* Validate the "sound" directory */
3843 	validate_dir(ANGBAND_DIR_XTRA_SOUND);
3844 
3845 #endif
3846 
3847 }
3848 
3849 
3850 
WinMain(HINSTANCE hInst,HINSTANCE hPrevInst,LPSTR lpCmdLine,int nCmdShow)3851 int FAR PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrevInst,
3852                        LPSTR lpCmdLine, int nCmdShow)
3853 {
3854 #ifdef USE_GRAPHICS
3855 	int i;
3856 #endif
3857 
3858 	WNDCLASS wc;
3859 	HDC      hdc;
3860 	MSG      msg;
3861 	//WSADATA wsadata;
3862 
3863 	hInstance = hInst;  /* save in a global var */
3864 
3865 	if (hPrevInst == NULL)
3866 	{
3867 		wc.style         = CS_CLASSDC;
3868 		wc.lpfnWndProc   = AngbandWndProc;
3869 		wc.cbClsExtra    = 0;
3870 		wc.cbWndExtra    = 4; /* one long pointer to term_data */
3871 		wc.hInstance     = hInst;
3872 		wc.hIcon         = hIcon = LoadIcon(hInst, AppName);
3873 		wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
3874 		wc.hbrBackground = GetStockObject(BLACK_BRUSH);
3875 		wc.lpszMenuName  = AppName;
3876 		wc.lpszClassName = AppName;
3877 
3878 		if (!RegisterClass(&wc)) exit(1);
3879 
3880 		wc.lpfnWndProc   = AngbandListProc;
3881 		wc.lpszMenuName  = NULL;
3882 		wc.lpszClassName = AngList;
3883 
3884 		if (!RegisterClass(&wc)) exit(2);
3885 
3886 #ifdef ALLOW_SCRSAVER
3887 
3888 		wc.style          = CS_VREDRAW | CS_HREDRAW | CS_SAVEBITS | CS_DBLCLKS;
3889 		wc.lpfnWndProc    = AngbandSaverProc;
3890 		wc.hCursor        = NULL;
3891 		wc.lpszMenuName   = NULL;
3892 		wc.lpszClassName  = "WindowsScreenSaverClass";
3893 
3894 		if (!RegisterClass(&wc)) exit(3);
3895 
3896 #endif
3897 
3898 	}
3899 
3900 	/* Set hooks */
3901 	quit_aux = hack_quit;
3902 	core_aux = hack_core;
3903 	plog_aux = hack_plog;
3904 
3905 	/* Global client config */
3906 	conf_init(hInstance);
3907 
3908 	/* Prepare the filepaths */
3909 	init_stuff_win();
3910 
3911 	/* Initialize WinSock */
3912 //	WSAStartup(MAKEWORD(1, 1), &wsadata);
3913 
3914 	/* Determine if display is 16/256/true color */
3915 	hdc = GetDC(NULL);
3916 	colors16 = (GetDeviceCaps(hdc, BITSPIXEL) == 4);
3917 	paletted = ((GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) ? TRUE : FALSE);
3918 	ReleaseDC(NULL, hdc);
3919 #ifdef USE_GRAPHICS
3920 	/* Initialize "color_table" */
3921 	for (i = 0; i < 16; i++)
3922 	{
3923 		/* Save the "complex" codes */
3924 		color_table[i][1] = GetRValue(win_clr[i]);
3925 		color_table[i][2] = GetGValue(win_clr[i]);
3926 		color_table[i][3] = GetBValue(win_clr[i]);
3927 
3928 		/* Save the "simple" code */
3929 		color_table[i][0] = win_pal[i];
3930 	}
3931 #endif
3932 
3933 	/* load the possible graphics modes */
3934 	if (!init_graphics_modes("graphics.txt")) {
3935 		plog("Graphics list load failed");
3936 	}
3937 
3938 	/* Prepare the windows */
3939 	init_windows();
3940 
3941 	/* Set the system suffix */
3942 	ANGBAND_SYS = "win";
3943 
3944 	/* We are now initialized */
3945 	initialized = TRUE;
3946 
3947 	/* Do network initialization, etc. */
3948 	client_init();
3949 
3950 	/* Process messages forever */
3951 	while (GetMessage(&msg, NULL, 0, 0))
3952 	{
3953 		TranslateMessage(&msg);
3954 		DispatchMessage(&msg);
3955 	}
3956 
3957 	cleanup_network_client();
3958 
3959 	/* Paranoia */
3960 	quit(NULL);
3961 
3962 	/* Paranoia */
3963 	return (0);
3964 }
3965 
3966 #endif /* _Windows */
3967