From 6aa48afdd57d03314fdf4be6c9da911c32277c84 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 8 Jan 2010 20:28:34 +0100 Subject: Import tome-2.3.5. --- src/main-win.c | 4486 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 4486 insertions(+) create mode 100644 src/main-win.c (limited to 'src/main-win.c') diff --git a/src/main-win.c b/src/main-win.c new file mode 100644 index 00000000..e2e71e95 --- /dev/null +++ b/src/main-win.c @@ -0,0 +1,4486 @@ +/* File: main-win.c */ + +/* + * Copyright (c) 1997 Ben Harrison, Skirmantas Kligys, and others + * + * This software may be copied and distributed for educational, research, + * and not for profit purposes provided that this copyright and statement + * are included in all such copies. + */ + + +/* + * This file helps Angband work with Windows computers. + * + * To use this file, use an appropriate "Makefile" or "Project File", + * make sure that "WINDOWS" and/or "WIN32" are defined somewhere, and + * make sure to obtain various extra files as described below. + * + * The official compilation uses the CodeWarrior Pro compiler, which + * includes a special project file and precompilable header file. + * + * + * See also "main-dos.c" and "main-ibm.c". + * + * + * The "lib/user/pref-win.prf" file contains keymaps, macro definitions, + * and/or color redefinitions. + * + * The "lib/user/font-win.prf" contains attr/char mappings for use with the + * normal "lib/xtra/font/ .fon" font files. + * + * The "lib/user/graf-win.prf" contains attr/char mappings for use with the + * special "lib/xtra/graf/ .bmp" bitmap files, which are activated by a + * menu item. + * + * + * Compiling this file, and using the resulting executable, requires + * several extra files not distributed with the standard Angband code. + * If "USE_GRAPHICS" is defined, then "readdib.h" and "readdib.c" must + * be placed into "src/", and the "8X8.BMP" bitmap file must be placed + * into "lib/xtra/graf". In any case, some "*.fon" files (including + * "8X13.FON" if nothing else) must be placed into "lib/xtra/font/". + * If "USE_SOUND" is defined, then some special library (for example, + * "winmm.lib") may need to be linked in, and desired "*.WAV" sound + * files must be placed into "lib/xtra/sound/". All of these extra + * files can be found in the "ext-win" archive. + * + * + * The "Term_xtra_win_clear()" function should probably do a low-level + * clear of the current window, and redraw the borders and other things, + * if only for efficiency. XXX XXX XXX + * + * A simpler method is needed for selecting the "tile size" for windows. + * XXX XXX XXX + * + * The various "warning" messages assume the existance of the "screen.w" + * window, I think, and only a few calls actually check for its existance, + * this may be okay since "NULL" means "on top of all windows". (?) The + * user must never be allowed to "hide" the main window, or the "menubar" + * will disappear. XXX XXX XXX + * + * Special "Windows Help Files" can be placed into "lib/xtra/help/" for + * use with the "winhelp.exe" program. These files *may* be available + * at the ftp site somewhere, but I have not seen them. XXX XXX XXX + * + * + * Initial framework (and most code) by Ben Harrison (benh@phial.com). + * + * Original code by Skirmantas Kligys (kligys@scf.usc.edu). + * + * Additional code by Ross E Becker (beckerr@cis.ohio-state.edu), + * and Chris R. Martin (crm7479@tam2000.tamu.edu). + */ + + +#include "angband.h" + + +#ifdef WINDOWS + + +/* + * Extract the "WIN32" flag from the compiler + */ +#if defined(__WIN32__) || defined(__WINNT__) || defined(__NT__) +# ifndef WIN32 +# define WIN32 +# endif +#endif + + +/* + * Hack -- allow use of "screen saver" mode + */ +#define USE_SAVER + +/* + * Menu constants -- see "ANGBAND.RC" + */ + +#define IDM_FILE_NEW 100 +#define IDM_FILE_OPEN 101 +#define IDM_FILE_SAVE 110 +#ifdef ALLOW_QUITTING +# define IDM_FILE_ABORT 120 +#else +# define IDM_FILE_SCORE 120 +#endif +#define IDM_FILE_EXIT 121 + +#define IDM_WINDOW_VIS_0 200 +#define IDM_WINDOW_VIS_1 201 +#define IDM_WINDOW_VIS_2 202 +#define IDM_WINDOW_VIS_3 203 +#define IDM_WINDOW_VIS_4 204 +#define IDM_WINDOW_VIS_5 205 +#define IDM_WINDOW_VIS_6 206 +#define IDM_WINDOW_VIS_7 207 + +#define IDM_WINDOW_FONT_0 210 +#define IDM_WINDOW_FONT_1 211 +#define IDM_WINDOW_FONT_2 212 +#define IDM_WINDOW_FONT_3 213 +#define IDM_WINDOW_FONT_4 214 +#define IDM_WINDOW_FONT_5 215 +#define IDM_WINDOW_FONT_6 216 +#define IDM_WINDOW_FONT_7 217 + +#define IDM_WINDOW_BIZ_0 230 +#define IDM_WINDOW_BIZ_1 231 +#define IDM_WINDOW_BIZ_2 232 +#define IDM_WINDOW_BIZ_3 233 +#define IDM_WINDOW_BIZ_4 234 +#define IDM_WINDOW_BIZ_5 235 +#define IDM_WINDOW_BIZ_6 236 +#define IDM_WINDOW_BIZ_7 237 + +#define IDM_WINDOW_I_WID_0 240 +#define IDM_WINDOW_I_WID_1 241 +#define IDM_WINDOW_I_WID_2 242 +#define IDM_WINDOW_I_WID_3 243 +#define IDM_WINDOW_I_WID_4 244 +#define IDM_WINDOW_I_WID_5 245 +#define IDM_WINDOW_I_WID_6 246 +#define IDM_WINDOW_I_WID_7 247 + +#define IDM_WINDOW_D_WID_0 250 +#define IDM_WINDOW_D_WID_1 251 +#define IDM_WINDOW_D_WID_2 252 +#define IDM_WINDOW_D_WID_3 253 +#define IDM_WINDOW_D_WID_4 254 +#define IDM_WINDOW_D_WID_5 255 +#define IDM_WINDOW_D_WID_6 256 +#define IDM_WINDOW_D_WID_7 257 + +#define IDM_WINDOW_I_HGT_0 260 +#define IDM_WINDOW_I_HGT_1 261 +#define IDM_WINDOW_I_HGT_2 262 +#define IDM_WINDOW_I_HGT_3 263 +#define IDM_WINDOW_I_HGT_4 264 +#define IDM_WINDOW_I_HGT_5 265 +#define IDM_WINDOW_I_HGT_6 266 +#define IDM_WINDOW_I_HGT_7 267 + +#define IDM_WINDOW_D_HGT_0 270 +#define IDM_WINDOW_D_HGT_1 271 +#define IDM_WINDOW_D_HGT_2 272 +#define IDM_WINDOW_D_HGT_3 273 +#define IDM_WINDOW_D_HGT_4 274 +#define IDM_WINDOW_D_HGT_5 275 +#define IDM_WINDOW_D_HGT_6 276 +#define IDM_WINDOW_D_HGT_7 277 + +#define IDM_OPTIONS_OLD_GRAPHICS 400 +#define IDM_OPTIONS_NEW_GRAPHICS 401 +#define IDM_OPTIONS_ASCII_GRAPHICS 403 +#define IDM_OPTIONS_SOUND 402 +#define IDM_OPTIONS_BIGTILE 409 +#define IDM_OPTIONS_UNUSED 410 +#define IDM_OPTIONS_SAVER 411 + +#define IDM_HELP_GENERAL 901 +#define IDM_HELP_SPOILERS 902 + + +/* + * This may need to be removed for some compilers XXX XXX XXX + */ +#define STRICT + +/* + * Exclude parts of WINDOWS.H that are not needed + */ +#define NOCOMM /* Comm driver APIs and definitions */ +#define NOLOGERROR /* LogError() and related definitions */ +#define NOPROFILER /* Profiler APIs */ +#define NOLFILEIO /* _l* file I/O routines */ +#define NOOPENFILE /* OpenFile and related definitions */ +#define NORESOURCE /* Resource management */ +#define NOATOM /* Atom management */ +#define NOLANGUAGE /* Character test routines */ +#define NOLSTRING /* lstr* string management routines */ +#define NODBCS /* Double-byte character set routines */ +#define NOKEYBOARDINFO /* Keyboard driver routines */ +#define NOCOLOR /* COLOR_* color values */ +#define NODRAWTEXT /* DrawText() and related definitions */ +#define NOSCALABLEFONT /* Truetype scalable font support */ +#define NOMETAFILE /* Metafile support */ +#define NOSYSTEMPARAMSINFO /* SystemParametersInfo() and SPI_* definitions */ +#define NODEFERWINDOWPOS /* DeferWindowPos and related definitions */ +#define NOKEYSTATES /* MK_* message key state flags */ +#define NOWH /* SetWindowsHook and related WH_* definitions */ +#define NOCLIPBOARD /* Clipboard APIs and definitions */ +#define NOICONS /* IDI_* icon IDs */ +#define NOMDI /* MDI support */ +#define NOHELP /* Help support */ + +/* Not defined since it breaks Borland C++ 5.5 */ +/* #define NOCTLMGR */ /* Control management and controls */ + +/* + * Exclude parts of WINDOWS.H that are not needed (Win32) + */ +#define WIN32_LEAN_AND_MEAN +#define NONLS /* All NLS defines and routines */ +#define NOSERVICE /* All Service Controller routines, SERVICE_ equates, etc. */ +#define NOKANJI /* Kanji support stuff. */ +#define NOMCX /* Modem Configuration Extensions */ + +/* + * Include the "windows" support file + */ +#include + +/* + * For IRC stuff + */ +#ifdef USE_WINSOCK +#define ZSOCK_TIMER_ID 1 +#define ZSOCK_TIMER_RATE 50 +#endif + + +/* + * Exclude parts of MMSYSTEM.H that are not needed + */ +#define MMNODRV /* Installable driver support */ +#define MMNOWAVE /* Waveform support */ +#define MMNOMIDI /* MIDI support */ +#define MMNOAUX /* Auxiliary audio support */ +#define MMNOJOY /* Joystick support */ +#define MMNOMCI /* MCI support */ +#define MMNOMMIO /* Multimedia file I/O support */ +#define MMNOMMSYSTEM /* General MMSYSTEM functions */ + +/* + * Include some more files + */ +#include +#include + +/* + * Include the support for loading bitmaps + */ +#ifdef USE_GRAPHICS +# include "readdib.h" +#endif + +/* + * Hack -- Fake declarations from "dos.h" XXX XXX XXX + */ +#ifdef WIN32 +#define INVALID_FILE_NAME (DWORD)0xFFFFFFFF +#else /* WIN32 */ +#define FA_LABEL 0x08 /* Volume label */ +#define FA_DIREC 0x10 /* Directory */ +unsigned _cdecl _dos_getfileattr(const char *, unsigned *); +#endif /* WIN32 */ + +/* + * Silliness in WIN32 drawing routine + */ +#ifdef WIN32 +# define MoveTo(H, X, Y) MoveToEx(H, X, Y, NULL) +#endif /* WIN32 */ + +/* + * Silliness for Windows 95 + */ +#ifndef WS_EX_TOOLWINDOW +# define WS_EX_TOOLWINDOW 0 +#endif + +/* + * Foreground color bits (hard-coded by DOS) + */ +#define VID_BLACK 0x00 +#define VID_BLUE 0x01 +#define VID_GREEN 0x02 +#define VID_CYAN 0x03 +#define VID_RED 0x04 +#define VID_MAGENTA 0x05 +#define VID_YELLOW 0x06 +#define VID_WHITE 0x07 + +/* + * Bright text (hard-coded by DOS) + */ +#define VID_BRIGHT 0x08 + +/* + * Background color bits (hard-coded by DOS) + */ +#define VUD_BLACK 0x00 +#define VUD_BLUE 0x10 +#define VUD_GREEN 0x20 +#define VUD_CYAN 0x30 +#define VUD_RED 0x40 +#define VUD_MAGENTA 0x50 +#define VUD_YELLOW 0x60 +#define VUD_WHITE 0x70 + +/* + * Blinking text (hard-coded by DOS) + */ +#define VUD_BRIGHT 0x80 + + + +/* + * Forward declare + */ +typedef struct _term_data term_data; + +/* + * Extra "term" data + * + * Note the use of "font_want" for the names of the font file requested by + * the user, and the use of "font_file" for the currently active font file. + * + * The "font_file" is uppercased, and takes the form "8X13.FON", while + * "font_want" can be in almost any form as long as it could be construed + * as attempting to represent the name of a font. + */ +struct _term_data +{ + term t; + + cptr s; + + HWND w; + + DWORD dwStyle; + DWORD dwExStyle; + + uint keys; + + uint rows; + uint cols; + + uint pos_x; + uint pos_y; + uint size_wid; + uint size_hgt; + uint size_ow1; + uint size_oh1; + uint size_ow2; + uint size_oh2; + + bool size_hack; + + bool xtra_hack; + + bool visible; + + bool bizarre; + + cptr font_want; + + cptr font_file; + + HFONT font_id; + + uint font_wid; + uint font_hgt; + + uint tile_wid; + uint tile_hgt; +}; + + +/* + * Maximum number of windows XXX XXX XXX + */ +#define MAX_TERM_DATA 8 + +/* + * An array of term_data's + */ +static term_data data[MAX_TERM_DATA]; + +/* + * Hack -- global "window creation" pointer + */ +static term_data *my_td; + +/* + * game in progress + */ +bool game_in_progress = FALSE; + +/* + * note when "open"/"new" become valid + */ +bool initialized = FALSE; + +/* + * screen paletted, i.e. 256 colors + */ +bool paletted = FALSE; + +/* + * 16 colors screen, don't use RGB() + */ +bool colors16 = FALSE; + +/* + * Saved instance handle + */ +static HINSTANCE hInstance; + +/* + * Yellow brush for the cursor + */ +static HBRUSH hbrYellow; + +/* + * An icon + */ +static HICON hIcon; + +/* + * A palette + */ +static HPALETTE hPal; + + +#ifdef USE_SAVER + +/* + * The screen saver window + */ +static HWND hwndSaver; + +#endif /* USE_SAVER */ + + +#ifdef USE_GRAPHICS + +/* + * Flag set once "graphics" has been initialized + */ +static bool can_use_graphics = FALSE; + +/* + * The global bitmap + */ +static DIBINIT infGraph; + +#ifdef USE_TRANSPARENCY + +/* + * The global bitmap mask + */ +static DIBINIT infMask; + +#endif /* USE_TRANSPARENCY */ + +#endif /* USE_GRAPHICS */ + + +#ifdef USE_SOUND + +/* + * Flag set once "sound" has been initialized + */ +static bool can_use_sound = FALSE; + +/* + * An array of sound file names + */ +static cptr sound_file[SOUND_MAX]; + +#endif /* USE_SOUND */ + + +/* + * Full path to ANGBAND.INI + */ +static cptr ini_file = NULL; + +/* + * Name of application + */ +static cptr AppName = "ANGBAND"; + +/* + * Name of sub-window type + */ +static cptr AngList = "AngList"; + +/* + * Directory names + */ +static cptr ANGBAND_DIR_XTRA_FONT; +static cptr ANGBAND_DIR_XTRA_GRAF; +static cptr ANGBAND_DIR_XTRA_SOUND; +static cptr ANGBAND_DIR_XTRA_HELP; + + +/* + * The "complex" color values + */ +static COLORREF win_clr[256]; + + +/* + * The "simple" color values + * + * See "main-ibm.c" for original table information + * + * The entries below are taken from the "color bits" defined above. + * + * Note that many of the choices below suck, but so do crappy monitors. + */ +static BYTE win_pal[256] = +{ + VID_BLACK, /* Dark */ + VID_WHITE, /* White */ + VID_CYAN, /* Slate XXX */ + VID_RED | VID_BRIGHT, /* Orange XXX */ + VID_RED, /* Red */ + VID_GREEN, /* Green */ + VID_BLUE, /* Blue */ + VID_YELLOW, /* Umber XXX */ + VID_BLACK | VID_BRIGHT, /* Light Dark */ + VID_CYAN | VID_BRIGHT, /* Light Slate XXX */ + VID_MAGENTA, /* Violet XXX */ + VID_YELLOW | VID_BRIGHT, /* Yellow */ + VID_MAGENTA | VID_BRIGHT, /* Light Red XXX */ + VID_GREEN | VID_BRIGHT, /* Light Green */ + VID_BLUE | VID_BRIGHT, /* Light Blue */ + VID_YELLOW /* Light Umber XXX */ +}; + + +/* + * Hack -- define which keys are "special" + */ +static bool special_key[256]; +static bool ignore_key[256]; + +#if 1 +/* + * Hack -- initialization list for "special_key" + */ +static byte special_key_list[] = { + VK_CLEAR, VK_PAUSE, VK_CAPITAL, VK_KANA, +#ifdef JP + VK_JUNJA, VK_FINAL, VK_KANJI, VK_CONVERT, VK_NONCONVERT, VK_ACCEPT, VK_MODECHANGE, +#endif + VK_PRIOR, VK_NEXT, VK_END, VK_HOME, VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN, + VK_SELECT, VK_PRINT, VK_EXECUTE, VK_SNAPSHOT, VK_INSERT, VK_DELETE, + VK_HELP, VK_APPS, + VK_F1, VK_F2, VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, + VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16, VK_F17, VK_F18, VK_F19, VK_F20, + VK_F21, VK_F22, VK_F23, VK_F24, VK_NUMLOCK, VK_SCROLL, + VK_ATTN, VK_CRSEL, VK_EXSEL, VK_EREOF, VK_PLAY, VK_ZOOM, VK_NONAME, + VK_PA1, 0 +}; + +static byte ignore_key_list[] = { + VK_ESCAPE, VK_TAB, VK_SPACE, + 'F', 'W', 'O', 'H', /* these are menu characters.*/ + VK_SHIFT, VK_CONTROL, VK_MENU, VK_LWIN, VK_RWIN, + VK_LSHIFT, VK_RSHIFT, VK_LCONTROL, VK_RCONTROL, VK_LMENU, VK_RMENU, 0 +}; + +#else +/* +* Hack -- initialization list for "special_key" +* +* We ignore the modifier keys (shift, control, alt, num lock, scroll lock), +* and the normal keys (escape, tab, return, letters, numbers, etc), but we +* catch the keypad keys (with and without numlock set, including keypad 5), +* the function keys (including the "menu" key which maps to F10), and the +* "pause" key (between scroll lock and numlock). We also catch a few odd +* keys which I do not recognize, but which are listed among keys which we +* do catch, so they should be harmless to catch. +*/ +static byte special_key_list[] = +{ + VK_CLEAR, /* 0x0C (KP<5>) */ + + VK_PAUSE, /* 0x13 (pause) */ + + VK_PRIOR, /* 0x21 (KP<9>) */ + VK_NEXT, /* 0x22 (KP<3>) */ + VK_END, /* 0x23 (KP<1>) */ + VK_HOME, /* 0x24 (KP<7>) */ + VK_LEFT, /* 0x25 (KP<4>) */ + VK_UP, /* 0x26 (KP<8>) */ + VK_RIGHT, /* 0x27 (KP<6>) */ + VK_DOWN, /* 0x28 (KP<2>) */ + VK_SELECT, /* 0x29 (?????) */ + VK_PRINT, /* 0x2A (?????) */ + VK_EXECUTE, /* 0x2B (?????) */ + VK_SNAPSHOT, /* 0x2C (?????) */ + VK_INSERT, /* 0x2D (KP<0>) */ + VK_DELETE, /* 0x2E (KP<.>) */ + VK_HELP, /* 0x2F (?????) */ + +#if 0 + VK_NUMPAD0, /* 0x60 (KP<0>) */ + VK_NUMPAD1, /* 0x61 (KP<1>) */ + VK_NUMPAD2, /* 0x62 (KP<2>) */ + VK_NUMPAD3, /* 0x63 (KP<3>) */ + VK_NUMPAD4, /* 0x64 (KP<4>) */ + VK_NUMPAD5, /* 0x65 (KP<5>) */ + VK_NUMPAD6, /* 0x66 (KP<6>) */ + VK_NUMPAD7, /* 0x67 (KP<7>) */ + VK_NUMPAD8, /* 0x68 (KP<8>) */ + VK_NUMPAD9, /* 0x69 (KP<9>) */ + VK_MULTIPLY, /* 0x6A (KP<*>) */ + VK_ADD, /* 0x6B (KP<+>) */ + VK_SEPARATOR, /* 0x6C (?????) */ + VK_SUBTRACT, /* 0x6D (KP<->) */ + VK_DECIMAL, /* 0x6E (KP<.>) */ + VK_DIVIDE, /* 0x6F (KP) */ +#endif + + VK_F1, /* 0x70 */ + VK_F2, /* 0x71 */ + VK_F3, /* 0x72 */ + VK_F4, /* 0x73 */ + VK_F5, /* 0x74 */ + VK_F6, /* 0x75 */ + VK_F7, /* 0x76 */ + VK_F8, /* 0x77 */ + VK_F9, /* 0x78 */ + VK_F10, /* 0x79 */ + VK_F11, /* 0x7A */ + VK_F12, /* 0x7B */ + VK_F13, /* 0x7C */ + VK_F14, /* 0x7D */ + VK_F15, /* 0x7E */ + VK_F16, /* 0x7F */ + VK_F17, /* 0x80 */ + VK_F18, /* 0x81 */ + VK_F19, /* 0x82 */ + VK_F20, /* 0x83 */ + VK_F21, /* 0x84 */ + VK_F22, /* 0x85 */ + VK_F23, /* 0x86 */ + VK_F24, /* 0x87 */ + + 0 +}; +#endif + + +/* + * Hack -- given a pathname, point at the filename + */ +static cptr extract_file_name(cptr s) +{ + cptr p; + + /* Start at the end */ + p = s + strlen(s) - 1; + + /* Back up to divider */ + while ((p >= s) && (*p != ':') && (*p != '\\')) p--; + + /* Return file name */ + return (p + 1); +} + + +/* + * Hack -- given a simple filename, extract the "font size" info + * + * Return a pointer to a static buffer holding the capitalized base name. + */ +static char *analyze_font(char *path, int *wp, int *hp) +{ + int wid, hgt; + + char *s, *p; + + /* Start at the end */ + p = path + strlen(path) - 1; + + /* Back up to divider */ + while ((p >= path) && (*p != ':') && (*p != '\\')) --p; + + /* Advance to file name */ + ++p; + + /* Capitalize */ + for (s = p; *s; ++s) + { + /* Capitalize (be paranoid) */ + if (islower(*s)) *s = toupper(*s); + } + + /* Find first 'X' */ + s = strchr(p, 'X'); + + /* Extract font width */ + wid = atoi(p); + + /* Extract height */ + hgt = s ? atoi(s + 1) : 0; + + /* Save results */ + (*wp) = wid; + (*hp) = hgt; + + /* Result */ + return (p); +} + + +/* + * Check for existance of a file + */ +static bool check_file(cptr s) +{ + char path[1024]; + +#ifdef WIN32 + + DWORD attrib; + +#else /* WIN32 */ + + unsigned int attrib; + +#endif /* WIN32 */ + + /* Copy it */ + strcpy(path, s); + +#ifdef WIN32 + + /* Examine */ + attrib = GetFileAttributes(path); + + /* Require valid filename */ + if (attrib == INVALID_FILE_NAME) return (FALSE); + + /* Prohibit directory */ + if (attrib & FILE_ATTRIBUTE_DIRECTORY) return (FALSE); + +#else /* WIN32 */ + + /* Examine and verify */ + if (_dos_getfileattr(path, &attrib)) return (FALSE); + + /* Prohibit something */ + if (attrib & FA_LABEL) return (FALSE); + + /* Prohibit directory */ + if (attrib & FA_DIREC) return (FALSE); + +#endif /* WIN32 */ + + /* Success */ + return (TRUE); +} + + +/* + * Check for existance of a directory + */ +static bool check_dir(cptr s) +{ + int i; + + char path[1024]; + +#ifdef WIN32 + + DWORD attrib; + +#else /* WIN32 */ + + unsigned int attrib; + +#endif /* WIN32 */ + + /* Copy it */ + strcpy(path, s); + + /* Check length */ + i = strlen(path); + + /* Remove trailing backslash */ + if (i && (path[i - 1] == '\\')) path[--i] = '\0'; + +#ifdef WIN32 + + /* Examine */ + attrib = GetFileAttributes(path); + + /* Require valid filename */ + if (attrib == INVALID_FILE_NAME) return (FALSE); + + /* Require directory */ + if (!(attrib & FILE_ATTRIBUTE_DIRECTORY)) return (FALSE); + +#else /* WIN32 */ + + /* Examine and verify */ + if (_dos_getfileattr(path, &attrib)) return (FALSE); + + /* Prohibit something */ + if (attrib & FA_LABEL) return (FALSE); + + /* Require directory */ + if (!(attrib & FA_DIREC)) return (FALSE); + +#endif /* WIN32 */ + + /* Success */ + return (TRUE); +} + + +/* + * Validate a file + */ +static void validate_file(cptr s) +{ + /* Verify or fail */ + if (!check_file(s)) + { + quit_fmt("Cannot find required file:\n%s", s); + } +} + + +/* + * Validate a directory + */ +static void validate_dir(cptr s) +{ + /* Verify or fail */ + if (!check_dir(s)) + { + quit_fmt("Cannot find required directory:\n%s", s); + } +} + + +/* + * Get the "size" for a window + */ +static void term_getsize(term_data *td) +{ + RECT rc; + + int wid, hgt; + + /* + * The Angband window is always at least 80x24. I'm not sure if + * small windows work... -- pelpel + */ + if (td == &data[0]) + { + if (td->cols < 80) td->cols = 80; + if (td->rows < 24) td->rows = 24; + } + + /* The other windows can be smaller */ + else + { + /* Paranoia */ + if (td->cols < 1) td->cols = 1; + if (td->rows < 1) td->rows = 1; + } + + /* Paranoia */ + if (td->cols > 255) td->cols = 255; + if (td->rows > 255) td->rows = 255; + + /* Window sizes */ + wid = td->cols * td->tile_wid + td->size_ow1 + td->size_ow2; + hgt = td->rows * td->tile_hgt + td->size_oh1 + td->size_oh2; + + /* Fake window size */ + rc.left = 0; + rc.right = rc.left + wid; + rc.top = 0; + rc.bottom = rc.top + hgt; + + /* XXX XXX XXX */ + /* rc.right += 1; */ + /* rc.bottom += 1; */ + + /* Adjust */ + AdjustWindowRectEx(&rc, td->dwStyle, TRUE, td->dwExStyle); + + /* Total size */ + td->size_wid = rc.right - rc.left; + td->size_hgt = rc.bottom - rc.top; + + /* See CreateWindowEx */ + if (!td->w) return; + + /* Extract actual location */ + GetWindowRect(td->w, &rc); + + /* Save the location */ + td->pos_x = rc.left; + td->pos_y = rc.top; +} + + +/* + * Write the "prefs" for a single term + */ +static void save_prefs_aux(term_data *td, cptr sec_name) +{ + char buf[1024]; + + RECT rc; + + /* Paranoia */ + if (!td->w) return; + + /* Visible */ + strcpy(buf, td->visible ? "1" : "0"); + WritePrivateProfileString(sec_name, "Visible", buf, ini_file); + + /* Font */ + strcpy(buf, td->font_file ? td->font_file : "8X13.FON"); + WritePrivateProfileString(sec_name, "Font", buf, ini_file); + + /* Bizarre */ + strcpy(buf, td->bizarre ? "1" : "0"); + WritePrivateProfileString(sec_name, "Bizarre", buf, ini_file); + + /* Tile size (x) */ + wsprintf(buf, "%d", td->tile_wid); + WritePrivateProfileString(sec_name, "TileWid", buf, ini_file); + + /* Tile size (y) */ + wsprintf(buf, "%d", td->tile_hgt); + WritePrivateProfileString(sec_name, "TileHgt", buf, ini_file); + + /* Window size (x) */ + wsprintf(buf, "%d", td->cols); + WritePrivateProfileString(sec_name, "NumCols", buf, ini_file); + + /* Window size (y) */ + wsprintf(buf, "%d", td->rows); + WritePrivateProfileString(sec_name, "NumRows", buf, ini_file); + + /* Acquire position */ + GetWindowRect(td->w, &rc); + + /* Window position (x) */ + wsprintf(buf, "%d", rc.left); + WritePrivateProfileString(sec_name, "PositionX", buf, ini_file); + + /* Window position (y) */ + wsprintf(buf, "%d", rc.top); + WritePrivateProfileString(sec_name, "PositionY", buf, ini_file); +} + + +/* + * Write the "prefs" + * + * We assume that the windows have all been initialized + */ +static void save_prefs(void) +{ + int i; + + char buf[128]; + + /* Save the "arg_graphics" flag */ + sprintf(buf, "%d", arg_graphics); + WritePrivateProfileString("Angband", "Graphics", buf, ini_file); + + /* Save the "arg_bigtile" flag */ + strcpy(buf, arg_bigtile ? "1" : "0"); + WritePrivateProfileString("Angband", "Bigtile", buf, ini_file); + + /* Save the "arg_sound" flag */ + strcpy(buf, arg_sound ? "1" : "0"); + WritePrivateProfileString("Angband", "Sound", buf, ini_file); + +#ifdef SUPPORT_GAMMA + /* Save the "gamma_val" */ + sprintf(buf, "%d", gamma_val); + WritePrivateProfileString("Angband", "GammaVal", buf, ini_file); +#endif /* SUPPORT_GAMMA */ + + /* Save window prefs */ + for (i = 0; i < MAX_TERM_DATA; ++i) + { + term_data *td = &data[i]; + + sprintf(buf, "Term-%d", i); + + save_prefs_aux(td, buf); + } +} + + +/* + * Load the "prefs" for a single term + */ +static void load_prefs_aux(term_data *td, cptr sec_name) +{ + char tmp[1024]; + + int wid, hgt; + + /* Visible */ + td->visible = (GetPrivateProfileInt(sec_name, "Visible", td->visible, ini_file) != 0); + + /* Desired font, with default */ + GetPrivateProfileString(sec_name, "Font", "8X13.FON", tmp, 127, ini_file); + + /* Bizarre */ + td->bizarre = (GetPrivateProfileInt(sec_name, "Bizarre", td->bizarre, ini_file) != 0); + + /* Analyze font, save desired font name */ + td->font_want = string_make(analyze_font(tmp, &wid, &hgt)); + + /* Tile size */ + td->tile_wid = GetPrivateProfileInt(sec_name, "TileWid", wid, ini_file); + td->tile_hgt = GetPrivateProfileInt(sec_name, "TileHgt", hgt, ini_file); + + /* Window size */ + td->cols = GetPrivateProfileInt(sec_name, "NumCols", td->cols, ini_file); + td->rows = GetPrivateProfileInt(sec_name, "NumRows", td->rows, ini_file); + + /* Window position */ + td->pos_x = GetPrivateProfileInt(sec_name, "PositionX", td->pos_x, ini_file); + td->pos_y = GetPrivateProfileInt(sec_name, "PositionY", td->pos_y, ini_file); +} + + +/* + * Load the "prefs" + */ +static void load_prefs(void) +{ + int i; + + char buf[1024]; + + /* Extract the "arg_graphics" flag */ + arg_graphics = GetPrivateProfileInt("Angband", "Graphics", 0, ini_file); + + /* Extract the "arg_bigtile" flag */ + arg_bigtile = GetPrivateProfileInt("Angband", "Bigtile", FALSE, ini_file); + use_bigtile = arg_bigtile; + + /* Extract the "arg_sound" flag */ + arg_sound = (GetPrivateProfileInt("Angband", "Sound", 0, ini_file) != 0); + +#ifdef SUPPORT_GAMMA + /* Extract the "gamma_val" */ + gamma_val = GetPrivateProfileInt("Angband", "GammaVal", 0, ini_file); +#endif /* SUPPORT_GAMMA */ + + /* Load window prefs */ + for (i = 0; i < MAX_TERM_DATA; ++i) + { + term_data *td = &data[i]; + + sprintf(buf, "Term-%d", i); + + load_prefs_aux(td, buf); + } +} + + +/* + * Create the new global palette based on the bitmap palette + * (if any), and the standard 16 entry palette derived from + * "win_clr[]" which is used for the basic 16 Angband colors. + * + * This function is never called before all windows are ready. + * + * This function returns FALSE if the new palette could not be + * prepared, which should normally be a fatal error. XXX XXX + * + * Note that only some machines actually use a "palette". + */ +static int new_palette(void) +{ + HPALETTE hBmPal; + HPALETTE hNewPal; + HDC hdc; + int i, nEntries; + int pLogPalSize; + int lppeSize; + LPLOGPALETTE pLogPal; + LPPALETTEENTRY lppe; + + term_data *td; + + + /* This makes no sense */ + if (!paletted) return (TRUE); + + + /* No palette */ + hBmPal = NULL; + + /* No bitmap */ + lppeSize = 0; + lppe = NULL; + nEntries = 0; + +#ifdef USE_GRAPHICS + + /* Check the bitmap palette */ + hBmPal = infGraph.hPalette; + + /* Use the bitmap */ + if (hBmPal) + { + lppeSize = 256 * sizeof(PALETTEENTRY); + lppe = (LPPALETTEENTRY)ralloc(lppeSize); + nEntries = GetPaletteEntries(hBmPal, 0, 255, lppe); + if ((nEntries == 0) || (nEntries > 220)) + { + /* Warn the user */ + plog_fmt("Unusable bitmap palette (%d entries)", nEntries); + + /* Cleanup */ + rnfree(lppe, lppeSize); + + /* Fail */ + return (FALSE); + } + } + +#endif + + /* Size of palette */ + pLogPalSize = sizeof(LOGPALETTE) + (nEntries + 16) * sizeof(PALETTEENTRY); + + /* Allocate palette */ + pLogPal = (LPLOGPALETTE)ralloc(pLogPalSize); + + /* Version */ + pLogPal->palVersion = 0x300; + + /* Make room for bitmap and normal data */ + pLogPal->palNumEntries = nEntries + 16; + + /* Save the bitmap data */ + for (i = 0; i < nEntries; i++) + { + pLogPal->palPalEntry[i] = lppe[i]; + } + + /* Save the normal data */ + for (i = 0; i < 16; i++) + { + LPPALETTEENTRY p; + + /* Access the entry */ + p = &(pLogPal->palPalEntry[i + nEntries]); + + /* Save the colors */ + p->peRed = GetRValue(win_clr[i]); + p->peGreen = GetGValue(win_clr[i]); + p->peBlue = GetBValue(win_clr[i]); + + /* Save the flags */ + p->peFlags = PC_NOCOLLAPSE; + } + + /* Free something */ + if (lppe) rnfree(lppe, lppeSize); + + /* Create a new palette, or fail */ + hNewPal = CreatePalette(pLogPal); + if (!hNewPal) quit("Cannot create palette!"); + + /* Free the palette */ + rnfree(pLogPal, pLogPalSize); + + /* Main window */ + td = &data[0]; + + /* Realize the palette */ + hdc = GetDC(td->w); + SelectPalette(hdc, hNewPal, 0); + i = RealizePalette(hdc); + ReleaseDC(td->w, hdc); + if (i == 0) quit("Cannot realize palette!"); + + /* Sub-windows */ + for (i = 1; i < MAX_TERM_DATA; i++) + { + td = &data[i]; + + hdc = GetDC(td->w); + SelectPalette(hdc, hNewPal, 0); + ReleaseDC(td->w, hdc); + } + + /* Delete old palette */ + if (hPal) DeleteObject(hPal); + + /* Save new palette */ + hPal = hNewPal; + + /* Success */ + return (TRUE); +} + + +/* + * Initialize graphics + */ +static bool init_graphics() +{ + /* Initialize once */ + /*if (can_use_graphics != arg_graphics) */ + { + char buf[1024]; + int wid, hgt; + cptr name; + +#ifdef USE_TRANSPARENCY + + /* Unused */ + PALETTEENTRY entry = + { + 0, 0, 0, 0 + }; + (void)entry; + +#endif /* USE_TRANSPARENCY */ + + if (arg_graphics == 2) + { + wid = 16; + hgt = 16; + + name = "16X16.BMP"; + + ANGBAND_GRAF = "new"; + } + else + { + wid = 8; + hgt = 8; + + name = "8X8.BMP"; + ANGBAND_GRAF = "old"; + } + + /* Access the bitmap file */ + path_build(buf, 1024, ANGBAND_DIR_XTRA_GRAF, name); + + /* Load the bitmap or quit */ + if (!ReadDIB(data[0].w, buf, &infGraph)) + { + plog_fmt("Cannot read bitmap file '%s'", name); + return (FALSE); + } + + /* Save the new sizes */ + infGraph.CellWidth = wid; + infGraph.CellHeight = hgt; + + +#ifdef USE_TRANSPARENCY + + path_build(buf, 1024, ANGBAND_DIR_XTRA_GRAF, "mask.bmp"); + /* Load the bitmap or quit */ + if (!ReadDIB(data[0].w, buf, &infMask)) + { + plog_fmt("Cannot read bitmap file '%s'", name); + return (FALSE); + } + +#endif /* USE_TRANSPARENCY */ + + /* Activate a palette */ + if (!new_palette()) + { + /* Free bitmap XXX XXX XXX */ + + /* Oops */ + plog("Cannot activate palette!"); + return (FALSE); + } + + /* Graphics available */ + can_use_graphics = arg_graphics; + } + + /* Result */ + return (can_use_graphics); +} + + +/* + * Initialize sound + */ +static bool init_sound() +{ + /* Initialize once */ + if (!can_use_sound) + { + int i; + + char wav[128]; + char buf[1024]; + + /* Prepare the sounds */ + for (i = 1; i < SOUND_MAX; i++) + { + /* Extract name of sound file */ + sprintf(wav, "%s.wav", angband_sound_name[i]); + + /* Access the sound */ + path_build(buf, 1024, ANGBAND_DIR_XTRA_SOUND, wav); + + /* Save the sound filename, if it exists */ + if (check_file(buf)) sound_file[i] = string_make(buf); + } + + /* Sound available */ + can_use_sound = TRUE; + } + + /* Result */ + return (can_use_sound); +} + + + +/* + * Resize a window + */ +static void term_window_resize(term_data *td) +{ + /* Require window */ + if (!td->w) return; + + /* Resize the window */ + SetWindowPos(td->w, 0, 0, 0, + td->size_wid, td->size_hgt, + SWP_NOMOVE | SWP_NOZORDER); + + /* Redraw later */ + InvalidateRect(td->w, NULL, TRUE); +} + + + +/* + * Force the use of a new "font file" for a term_data + * + * This function may be called before the "window" is ready + * + * This function returns zero only if everything succeeds. + * + * Note that the "font name" must be capitalized!!! + */ +static errr term_force_font(term_data *td, cptr path) +{ + int i; + + int wid, hgt; + + char *base; + + char buf[1024]; + + + /* Forget the old font (if needed) */ + if (td->font_id) DeleteObject(td->font_id); + + /* Forget old font */ + if (td->font_file) + { + bool used = FALSE; + + /* Scan windows */ + for (i = 0; i < MAX_TERM_DATA; i++) + { + /* Check "screen" */ + if ((td != &data[i]) && + (data[i].font_file) && + (streq(data[i].font_file, td->font_file))) + { + used = TRUE; + } + } + + /* Remove unused font resources */ + if (!used) RemoveFontResource(td->font_file); + + /* Free the old name */ + string_free(td->font_file); + + /* Forget it */ + td->font_file = NULL; + } + + + /* No path given */ + if (!path) return (1); + + + /* Local copy */ + strcpy(buf, path); + + /* Analyze font path */ + base = analyze_font(buf, &wid, &hgt); + + /* Verify suffix */ + if (!suffix(base, ".FON")) return (1); + + /* Verify file */ + if (!check_file(buf)) return (1); + + /* Load the new font */ + if (!AddFontResource(buf)) return (1); + + /* Save new font name */ + td->font_file = string_make(base); + + /* Remove the "suffix" */ + base[strlen(base) - 4] = '\0'; + + /* Create the font (using the 'base' of the font file name!) */ + td->font_id = CreateFont(hgt, wid, 0, 0, FW_DONTCARE, 0, 0, 0, + ANSI_CHARSET, OUT_DEFAULT_PRECIS, + CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, + FIXED_PITCH | FF_DONTCARE, base); + + /* Hack -- Unknown size */ + if (!wid || !hgt) + { + HDC hdcDesktop; + HFONT hfOld; + TEXTMETRIC tm; + + /* all this trouble to get the cell size */ + hdcDesktop = GetDC(HWND_DESKTOP); + hfOld = SelectObject(hdcDesktop, td->font_id); + GetTextMetrics(hdcDesktop, &tm); + SelectObject(hdcDesktop, hfOld); + ReleaseDC(HWND_DESKTOP, hdcDesktop); + + /* Font size info */ + wid = tm.tmAveCharWidth; + hgt = tm.tmHeight; + } + + /* Save the size info */ + td->font_wid = wid; + td->font_hgt = hgt; + + /* Success */ + return (0); +} + + + +/* + * Allow the user to change the font for this window. + */ +static void term_change_font(term_data *td) +{ + OPENFILENAME ofn; + + char tmp[1024] = ""; + + /* Extract a default if possible */ + if (td->font_file) strcpy(tmp, td->font_file); + + /* Ask for a choice */ + memset(&ofn, 0, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = data[0].w; + ofn.lpstrFilter = "Angband Font Files (*.fon)\0*.fon\0"; + ofn.nFilterIndex = 1; + ofn.lpstrFile = tmp; + ofn.nMaxFile = 128; + ofn.lpstrInitialDir = ANGBAND_DIR_XTRA_FONT; + ofn.Flags = OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR; + ofn.lpstrDefExt = "fon"; + + /* Force choice if legal */ + if (GetOpenFileName(&ofn)) + { + /* Force the font */ + if (term_force_font(td, tmp)) + { + /* Access the standard font file */ + path_build(tmp, 1024, ANGBAND_DIR_XTRA_FONT, "8X13.FON"); + + /* Force the use of that font */ + (void)term_force_font(td, tmp); + } + + /* Assume not bizarre */ + td->bizarre = FALSE; + + /* Reset the tile info */ + td->tile_wid = td->font_wid; + td->tile_hgt = td->font_hgt; + + /* Analyze the font */ + term_getsize(td); + + /* Resize the window */ + term_window_resize(td); + } +} + + + +/* + * Hack -- redraw a term_data + */ +static void term_data_redraw(term_data *td) +{ + /* Activate the term */ + Term_activate(&td->t); + + /* Redraw the contents */ + Term_redraw(); + + /* Restore the term */ + Term_activate(term_screen); +} + + + + + +/*** Function hooks needed by "Term" ***/ + + +#if 0 + +/* + * Initialize a new Term + */ +static void Term_init_win(term *t) +{ + /* XXX Unused */ +} + + +/* + * Nuke an old Term + */ +static void Term_nuke_win(term *t) +{ + /* XXX Unused */ +} + +#endif + + +/* + * Interact with the User + */ +static errr Term_user_win(int n) +{ + /* Success */ + return (0); +} + + +#ifdef SUPPORT_GAMMA + +/* + * When set to TRUE, indicates that we can use gamma_table + */ +static bool gamma_table_ready = FALSE; + +#endif /* SUPPORT_GAMMA */ + + +/* + * React to global changes + */ +static errr Term_xtra_win_react(void) +{ + int i; + + + /* Simple color */ + if (colors16) + { + /* Save the default colors */ + for (i = 0; i < 256; i++) + { + /* Simply accept the desired colors */ + win_pal[i] = angband_color_table[i][0]; + } + } + + /* Complex color */ + else + { + COLORREF code; + + byte rv, gv, bv; + + bool change = FALSE; + +#ifdef SUPPORT_GAMMA + + static u16b old_gamma_val = 0; + + + /* React to change in the gamma value */ + if (gamma_val != old_gamma_val) + { + /* Temporarily inactivate the gamma table */ + gamma_table_ready = FALSE; + + /* Only need to build the table if gamma exists */ + if (gamma_val) + { + /* Rebuild the table */ + build_gamma_table(gamma_val); + + /* Activate the table */ + gamma_table_ready = TRUE; + } + + /* Remember the gamma value used */ + old_gamma_val = gamma_val; + } + +#endif /* SUPPORT_GAMMA */ + + /* Save the default colors */ + for (i = 0; i < 256; i++) + { + /* Extract desired values */ + rv = angband_color_table[i][1]; + gv = angband_color_table[i][2]; + bv = angband_color_table[i][3]; + +#ifdef SUPPORT_GAMMA + + /* Hack - Gamma correction */ + if (gamma_table_ready) + { + rv = gamma_table[rv]; + gv = gamma_table[gv]; + bv = gamma_table[bv]; + } + +#endif /* SUPPORT_GAMMA */ + + /* Extract a full color code */ + code = PALETTERGB(rv, gv, bv); + + /* Activate changes */ + if (win_clr[i] != code) + { + /* Note the change */ + change = TRUE; + + /* Apply the desired color */ + win_clr[i] = code; + } + } + + /* Activate the palette if needed */ + if (change) (void)new_palette(); + } + + +#ifdef USE_SOUND + + /* Handle "arg_sound" */ + if (use_sound != arg_sound) + { + /* Initialize (if needed) */ + if (arg_sound && !init_sound()) + { + /* Warning */ + plog("Cannot initialize sound!"); + + /* Cannot enable */ + arg_sound = FALSE; + } + + /* Change setting */ + use_sound = arg_sound; + } + +#endif + + +#ifdef USE_GRAPHICS + + /* Handle "arg_graphics" */ + if (use_graphics != arg_graphics) + { + /* Initialize (if needed) */ + if (arg_graphics && !init_graphics()) + { + /* Warning */ + plog("Cannot initialize graphics!"); + + /* Cannot enable */ + arg_graphics = FALSE; + } + + /* Change setting */ + use_graphics = arg_graphics; + + /* Reset visuals */ + reset_visuals(); + } + +#endif /* USE_GRAPHICS */ + + + /* Clean up windows */ + for (i = 0; i < MAX_TERM_DATA; i++) + { + term *old = Term; + + term_data *td = &data[i]; + + /* Update resized windows */ + if ((td->cols != td->t.wid) || (td->rows != td->t.hgt)) + { + /* Activate */ + Term_activate(&td->t); + + /* Hack -- Resize the term */ + Term_resize(td->cols, td->rows); + + /* Redraw the contents */ + Term_redraw(); + + /* Restore */ + Term_activate(old); + } + } + + + /* Success */ + return (0); +} + + +/* + * Process at least one event + */ +static errr Term_xtra_win_event(int v) +{ + MSG msg; + + /* Wait for an event */ + if (v) + { + /* Block */ + if (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + /* Check for an event */ + else + { + irc_poll(); + + /* Check */ + if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + /* Success */ + return 0; +} + + +/* + * Process all pending events + */ +static errr Term_xtra_win_flush(void) +{ + MSG msg; + + /* Process all pending events */ + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + /* Success */ + return (0); +} + + +/* + * Hack -- clear the screen + * + * Make this more efficient XXX XXX XXX + */ +static errr Term_xtra_win_clear(void) +{ + term_data *td = (term_data*)(Term->data); + + HDC hdc; + RECT rc; + + /* Rectangle to erase */ + rc.left = td->size_ow1; + rc.right = rc.left + td->cols * td->tile_wid; + rc.top = td->size_oh1; + rc.bottom = rc.top + td->rows * td->tile_hgt; + + /* Erase it */ + hdc = GetDC(td->w); + SetBkColor(hdc, RGB(0, 0, 0)); + SelectObject(hdc, td->font_id); + ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL); + ReleaseDC(td->w, hdc); + + /* Success */ + return 0; +} + + +/* + * Hack -- make a noise + */ +static errr Term_xtra_win_noise(void) +{ + MessageBeep(MB_ICONASTERISK); + return (0); +} + + +/* + * Hack -- make a sound + */ +static errr Term_xtra_win_sound(int v) +{ + /* Sound disabled */ + if (!use_sound) return (1); + + /* Illegal sound */ + if ((v < 0) || (v >= SOUND_MAX)) return (1); + + /* Unknown sound */ + if (!sound_file[v]) return (1); + +#ifdef USE_SOUND + +#ifdef WIN32 + + /* Play the sound, catch errors */ + return (PlaySound(sound_file[v], 0, SND_FILENAME | SND_ASYNC)); + +#else /* WIN32 */ + +/* Play the sound, catch errors */ + return (sndPlaySound(sound_file[v], SND_ASYNC)); + +#endif /* WIN32 */ + +#endif /* USE_SOUND */ + + /* Oops */ + return (1); +} + + +/* + * Delay for "x" milliseconds + */ +static int Term_xtra_win_delay(int v) +{ + +#ifdef WIN32 + + /* Sleep */ + Sleep(v); + +#else /* WIN32 */ + + DWORD t; + MSG msg; + + /* Final count */ + t = GetTickCount() + v; + + /* Wait for it */ + while (GetTickCount() < t) + { + /* Handle messages */ + if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + +#endif /* WIN32 */ + + /* Success */ + return (0); +} + +/* + * Return the HWND of the main window + */ +HWND get_main_hwnd() +{ + return data[0].w; +} + +/* + * Do a "special thing" + */ +static errr Term_xtra_win(int n, int v) +{ + /* Handle a subset of the legal requests */ + switch (n) + { + /* Make a bell sound */ + case TERM_XTRA_NOISE: + { + return (Term_xtra_win_noise()); + } + + /* Make a special sound */ + case TERM_XTRA_SOUND: + { + return (Term_xtra_win_sound(v)); + } + + /* Process random events */ + case TERM_XTRA_BORED: + { + return (Term_xtra_win_event(0)); + } + + /* Process an event */ + case TERM_XTRA_EVENT: + { + return (Term_xtra_win_event(v)); + } + + /* Flush all events */ + case TERM_XTRA_FLUSH: + { + return (Term_xtra_win_flush()); + } + + /* Clear the screen */ + case TERM_XTRA_CLEAR: + { + return (Term_xtra_win_clear()); + } + + /* React to global changes */ + case TERM_XTRA_REACT: + { + return (Term_xtra_win_react()); + } + + /* Delay for some milliseconds */ + case TERM_XTRA_DELAY: + { + irc_poll(); + + return (Term_xtra_win_delay(v)); + } + + /* Get the current time in milliseconds */ + case TERM_XTRA_GET_DELAY: + { + DWORD t; + + t = GetTickCount(); + Term_xtra_long = t; + return 0; + } + + /* + * Scans for subdirectories in a directory "scansubdir_dir" + * and place teh result in "scansubdir_result/scansubdir_max" + */ + case TERM_XTRA_SCANSUBDIR: + { + BOOL ok; + HANDLE h; + WIN32_FIND_DATA fd; + for (h = FindFirstFile(format("%s\\*", scansubdir_dir), &fd), ok = 1; + h != INVALID_HANDLE_VALUE && ok; + ok = FindNextFile(h, &fd)) + { + if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && (strcmp(fd.cFileName, ".")) && (strcmp(fd.cFileName, ".."))) + { + string_free(scansubdir_result[scansubdir_max]); + scansubdir_result[scansubdir_max] = string_make(fd.cFileName); + scansubdir_max++; + } + } + + return 0; + } + + /* Rename main window */ + case TERM_XTRA_RENAME_MAIN_WIN: + SetWindowText(get_main_hwnd(), angband_term_name[0]); return (0); + } + + /* Oops */ + return 1; +} + + + +/* + * Low level graphics (Assumes valid input). + * + * Draw a "cursor" at (x,y), using a "yellow box". + */ +static errr Term_curs_win(int x, int y) +{ + term_data *td = (term_data*)(Term->data); + + RECT rc; + HDC hdc; + + /* Frame the grid */ + rc.left = x * td->tile_wid + td->size_ow1; + rc.right = rc.left + td->tile_wid; + rc.top = y * td->tile_hgt + td->size_oh1; + rc.bottom = rc.top + td->tile_hgt; + + if (use_bigtile && x + 1 < Term->wid && Term->old->a[y][x + 1] == 255) + rc.right += td->tile_wid; + + /* Cursor is done as a yellow "box" */ + hdc = GetDC(data[0].w); + FrameRect(hdc, &rc, hbrYellow); + ReleaseDC(data[0].w, hdc); + + /* Success */ + return 0; +} + + +/* + * Low level graphics (Assumes valid input). + * + * Erase a "block" of "n" characters starting at (x,y). + */ +static errr Term_wipe_win(int x, int y, int n) +{ + term_data *td = (term_data*)(Term->data); + + HDC hdc; + RECT rc; + + /* Rectangle to erase in client coords */ + rc.left = x * td->tile_wid + td->size_ow1; + rc.right = rc.left + n * td->tile_wid; + rc.top = y * td->tile_hgt + td->size_oh1; + rc.bottom = rc.top + td->tile_hgt; + + hdc = GetDC(td->w); + SetBkColor(hdc, RGB(0, 0, 0)); + SelectObject(hdc, td->font_id); + ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL); + ReleaseDC(td->w, hdc); + + /* Success */ + return 0; +} + +/* + * Low level graphics. Assumes valid input. + * + * Draw several ("n") chars, with an attr, at a given location. + * + * All "graphic" data is handled by "Term_pict_win()", below. + * + * One would think there is a more efficient method for telling a window + * what color it should be using to draw with, but perhaps simply changing + * it every time is not too inefficient. XXX XXX XXX + */ +static errr Term_text_win(int x, int y, int n, byte a, const char *s) +{ + term_data *td = (term_data*)(Term->data); + RECT rc; + HDC hdc; + + + /* Total rectangle */ + rc.left = x * td->tile_wid + td->size_ow1; + rc.right = rc.left + n * td->tile_wid; + rc.top = y * td->tile_hgt + td->size_oh1; + rc.bottom = rc.top + td->tile_hgt; + + /* Acquire DC */ + hdc = GetDC(td->w); + + /* Background color */ + SetBkColor(hdc, RGB(0, 0, 0)); + + /* Foreground color */ + if (colors16) + { + SetTextColor(hdc, PALETTEINDEX(win_pal[a])); + } + else if (paletted) + { + SetTextColor(hdc, win_clr[a&0x0F]); + } + else + { + SetTextColor(hdc, win_clr[a]); + } + + /* Use the font */ + SelectObject(hdc, td->font_id); + + /* Bizarre size */ + if (td->bizarre || + (td->tile_hgt != td->font_hgt) || + (td->tile_wid != td->font_wid)) + { + int i; + + /* Erase complete rectangle */ + ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL); + + /* New rectangle */ + rc.left += ((td->tile_wid - td->font_wid) / 2); + rc.right = rc.left + td->font_wid; + rc.top += ((td->tile_hgt - td->font_hgt) / 2); + rc.bottom = rc.top + td->font_hgt; + + /* Dump each character */ + for (i = 0; i < n; i++) + { + /* Dump the text */ + ExtTextOut(hdc, rc.left, rc.top, 0, &rc, + s + i, 1, NULL); + + /* Advance */ + rc.left += td->tile_wid; + rc.right += td->tile_wid; + } + } + + /* Normal size */ + else + { + /* Dump the text */ + ExtTextOut(hdc, rc.left, rc.top, ETO_OPAQUE | ETO_CLIPPED, &rc, + s, n, NULL); + } + + /* Release DC */ + ReleaseDC(td->w, hdc); + + /* Success */ + return 0; +} + + +/* + * Low level graphics. Assumes valid input. + * + * Draw an array of "special" attr/char pairs at the given location. + * + * We use the "Term_pict_win()" function for "graphic" data, which are + * encoded by setting the "high-bits" of both the "attr" and the "char" + * data. We use the "attr" to represent the "row" of the main bitmap, + * and the "char" to represent the "col" of the main bitmap. The use + * of this function is induced by the "higher_pict" flag. + * + * If "graphics" is not available, we simply "wipe" the given grids. + */ +# ifdef USE_TRANSPARENCY +# ifdef USE_EGO_GRAPHICS +static errr Term_pict_win(int x, int y, int n, const byte *ap, const char *cp, const byte *tap, const char *tcp, const byte *eap, const char *ecp) +# else /* USE_EGO_GRAPHICS */ +static errr Term_pict_win(int x, int y, int n, const byte *ap, const char *cp, const byte *tap, const char *tcp) +# endif /* USE_EGO_GRAPHICS */ +# else /* USE_TRANSPARENCY */ +static errr Term_pict_win(int x, int y, int n, const byte *ap, const char *cp) +# endif /* USE_TRANSPARENCY */ +{ + term_data *td = (term_data*)(Term->data); + +#ifdef USE_GRAPHICS + + int i; + int x1, y1, w1, h1; + int x2, y2, w2, h2, tw2; + +# ifdef USE_TRANSPARENCY + + int x3, y3; + + HDC hdcMask = NULL; + +#ifdef USE_EGO_GRAPHICS + + int x4, y4; + +#endif + +# endif /* USE_TRANSPARENCY */ + + HDC hdc; + HDC hdcSrc; + HBITMAP hbmSrcOld; + + /* Paranoia */ + if (!use_graphics) + { + /* Erase the grids */ + return (Term_wipe_win(x, y, n)); + } + + /* Size of bitmap cell */ + w1 = infGraph.CellWidth; + h1 = infGraph.CellHeight; + + /* Size of window cell */ + w2 = td->tile_wid; + h2 = td->tile_hgt; + tw2 = w2; + + /* big tile mode */ + if (use_bigtile) tw2 *= 2; + + /* Location of window cell */ + x2 = x * w2 + td->size_ow1; + y2 = y * h2 + td->size_oh1; + + /* Info */ + hdc = GetDC(td->w); + + /* More info */ + hdcSrc = CreateCompatibleDC(hdc); + hbmSrcOld = SelectObject(hdcSrc, infGraph.hBitmap); + +# ifdef USE_TRANSPARENCY + + if (arg_graphics == 2) + { + hdcMask = CreateCompatibleDC(hdc); + SelectObject(hdcMask, infMask.hBitmap); + } + +# endif /* USE_TRANSPARENCY */ + + /* Draw attr/char pairs */ + for (i = 0; i < n; i++, x2 += w2) + { + byte a = ap[i]; + char c = cp[i]; + + /* Extract picture */ + int row = (a & 0x7F); + int col = (c & 0x7F); + + /* Location of bitmap cell */ + x1 = col * w1; + y1 = row * h1; + +# ifdef USE_TRANSPARENCY + + if (arg_graphics == 2) + { + x3 = (tcp[i] & 0x7F) * w1; + y3 = (tap[i] & 0x7F) * h1; + + /* Perfect size */ + if ((w1 == tw2) && (h1 == h2)) + { + /* Copy the terrain picture from the bitmap to the window */ + BitBlt(hdc, x2, y2, tw2, h2, hdcSrc, x3, y3, SRCCOPY); + + /* Mask out the tile */ + BitBlt(hdc, x2, y2, tw2, h2, hdcMask, x1, y1, SRCAND); + + /* Draw the tile */ + BitBlt(hdc, x2, y2, tw2, h2, hdcSrc, x1, y1, SRCPAINT); + +#ifdef USE_EGO_GRAPHICS + if (ecp[i] != 0 && eap[i] != 0) + { + x4 = (ecp[i] & 0x7F) * w1; + y4 = (eap[i] & 0x7F) * h1; + + /* Mask out the tile */ + BitBlt(hdc, x2, y2, tw2, h2, hdcMask, x4, y4, SRCAND); + + /* Draw the tile */ + BitBlt(hdc, x2, y2, tw2, h2, hdcSrc, x4, y4, SRCPAINT); + } +#endif + } + + /* Need to stretch */ + else + { + /* Set the correct mode for stretching the tiles */ + SetStretchBltMode(hdc, COLORONCOLOR); + + /* Copy the terrain picture from the bitmap to the window */ + StretchBlt(hdc, x2, y2, tw2, h2, hdcSrc, x3, y3, w1, h1, SRCCOPY); + + /* Only draw if terrain and overlay are different */ + if ((x1 != x3) || (y1 != y3)) + { + /* Mask out the tile */ + StretchBlt(hdc, x2, y2, tw2, h2, hdcMask, x1, y1, w1, h1, SRCAND); + + /* Draw the tile */ + StretchBlt(hdc, x2, y2, tw2, h2, hdcSrc, x1, y1, w1, h1, SRCPAINT); + } + +#ifdef USE_EGO_GRAPHICS + if (ecp[i] != 0 && eap[i] != 0) + { + x4 = (ecp[i] & 0x7F) * w1; + y4 = (eap[i] & 0x7F) * h1; + + /* Mask out the tile */ + StretchBlt(hdc, x2, y2, tw2, h2, hdcMask, x4, y4, w1, h1, SRCAND); + + /* Draw the tile */ + StretchBlt(hdc, x2, y2, tw2, h2, hdcSrc, x4, y4, w1, h1, SRCPAINT); + } +#endif + } + } + else + +# endif /* USE_TRANSPARENCY */ + + { + /* Perfect size */ + if ((w1 == tw2) && (h1 == h2)) + { + /* Copy the picture from the bitmap to the window */ + BitBlt(hdc, x2, y2, tw2, h2, hdcSrc, x1, y1, SRCCOPY); + } + + /* Need to stretch */ + else + { + /* Set the correct mode for stretching the tiles */ + SetStretchBltMode(hdc, COLORONCOLOR); + + /* Copy the picture from the bitmap to the window */ + StretchBlt(hdc, x2, y2, tw2, h2, hdcSrc, x1, y1, w1, h1, SRCCOPY); + } + } + } + + /* Release */ + SelectObject(hdcSrc, hbmSrcOld); + DeleteDC(hdcSrc); + +# ifdef USE_TRANSPARENCY + + if (arg_graphics == 2) + { + /* Release */ + SelectObject(hdcMask, hbmSrcOld); + DeleteDC(hdcMask); + } + +# endif /* USE_TRANSPARENCY */ + + /* Release */ + ReleaseDC(td->w, hdc); + +#else /* USE_GRAPHICS */ + + /* Just erase this grid */ + return (Term_wipe_win(x, y, n)); + +#endif /* USE_GRAPHICS */ + + /* Success */ + return 0; +} + + +/*** Other routines ***/ + + +/* + * Create and initialize a "term_data" given a title + */ +static void term_data_link(term_data *td) +{ + term *t = &td->t; + + /* Initialize the term */ + term_init(t, td->cols, td->rows, td->keys); + + /* Use a "software" cursor */ + t->soft_cursor = TRUE; + + /* Use "Term_pict" for "graphic" data */ + t->higher_pict = TRUE; + + /* Erase with "white space" */ + t->attr_blank = TERM_WHITE; + t->char_blank = ' '; + +#if 0 + /* Prepare the init/nuke hooks */ + t->init_hook = Term_init_win; + t->nuke_hook = Term_nuke_win; +#endif + + /* Prepare the template hooks */ + t->user_hook = Term_user_win; + t->xtra_hook = Term_xtra_win; + t->curs_hook = Term_curs_win; + t->wipe_hook = Term_wipe_win; + t->text_hook = Term_text_win; + t->pict_hook = Term_pict_win; + + /* Remember where we came from */ + t->data = (vptr)(td); +} + + +/* + * Create the windows + * + * First, instantiate the "default" values, then read the "ini_file" + * to over-ride selected values, then create the windows, and fonts. + * + * Must use SW_SHOW not SW_SHOWNA, since on 256 color display + * must make active to realize the palette. XXX XXX XXX + */ +static void init_windows(void) +{ + int i; + + term_data *td; + + char buf[1024]; + + + /* Main window */ + td = &data[0]; + WIPE(td, term_data); + td->s = angband_term_name[0]; + td->keys = 1024; + td->rows = 24; + td->cols = 80; + td->visible = TRUE; + td->size_ow1 = 2; + td->size_ow2 = 2; + td->size_oh1 = 2; + td->size_oh2 = 2; + td->pos_x = 7 * 30; + td->pos_y = 7 * 20; + + /* Sub windows */ + for (i = 1; i < MAX_TERM_DATA; i++) + { + td = &data[i]; + WIPE(td, term_data); + td->s = angband_term_name[i]; + td->keys = 16; + td->rows = 24; + td->cols = 80; + td->visible = FALSE; + td->size_ow1 = 1; + td->size_ow2 = 1; + td->size_oh1 = 1; + td->size_oh2 = 1; + td->pos_x = (7 - i) * 30; + td->pos_y = (7 - i) * 20; + } + + + /* Load prefs */ + load_prefs(); + + + /* Main window (need these before term_getsize gets called) */ + td = &data[0]; + td->dwStyle = (WS_OVERLAPPED | WS_THICKFRAME | WS_SYSMENU | + WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CAPTION | + WS_VISIBLE); + td->dwExStyle = 0; + td->visible = TRUE; + + /* Sub windows (need these before term_getsize gets called) */ + for (i = 1; i < MAX_TERM_DATA; i++) + { + td = &data[i]; + td->dwStyle = (WS_OVERLAPPED | WS_THICKFRAME | WS_SYSMENU); + td->dwExStyle = (WS_EX_TOOLWINDOW); + } + + + /* All windows */ + for (i = 0; i < MAX_TERM_DATA; i++) + { + td = &data[i]; + + /* Access the standard font file */ + path_build(buf, 1024, ANGBAND_DIR_XTRA_FONT, td->font_want); + + /* Activate the chosen font */ + if (term_force_font(td, buf)) + { + /* Access the standard font file */ + path_build(buf, 1024, ANGBAND_DIR_XTRA_FONT, "8X13.FON"); + + /* Force the use of that font */ + (void)term_force_font(td, buf); + + /* Oops */ + td->tile_wid = 8; + td->tile_hgt = 13; + + /* Assume not bizarre */ + td->bizarre = FALSE; + } + + /* Analyze the font */ + term_getsize(td); + + /* Resize the window */ + term_window_resize(td); + } + + + /* Sub windows (reverse order) */ + for (i = MAX_TERM_DATA - 1; i >= 1; --i) + { + td = &data[i]; + + my_td = td; + td->w = CreateWindowEx(td->dwExStyle, AngList, + td->s, td->dwStyle, + td->pos_x, td->pos_y, + td->size_wid, td->size_hgt, + HWND_DESKTOP, NULL, hInstance, NULL); + my_td = NULL; + if (!td->w) quit("Failed to create sub-window"); + + if (td->visible) + { + td->size_hack = TRUE; + ShowWindow(td->w, SW_SHOW); + td->size_hack = FALSE; + } + + term_data_link(td); + angband_term[i] = &td->t; + + if (td->visible) + { + /* Activate the window */ + SetActiveWindow(td->w); + + /* Bring window to top */ + SetWindowPos(td->w, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + } + } + + + /* Main window */ + td = &data[0]; + + /* Main window */ + my_td = td; + td->w = CreateWindowEx(td->dwExStyle, AppName, + td->s, td->dwStyle, + td->pos_x, td->pos_y, + td->size_wid, td->size_hgt, + HWND_DESKTOP, NULL, hInstance, NULL); + my_td = NULL; + if (!td->w) quit("Failed to create Angband window"); + + term_data_link(td); + angband_term[0] = &td->t; + + /* Activate the main window */ + SetActiveWindow(td->w); + + /* Bring main window back to top */ + SetWindowPos(td->w, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + + + /* New palette XXX XXX XXX */ + (void)new_palette(); + + + /* Create a "brush" for drawing the "cursor" */ + hbrYellow = CreateSolidBrush(win_clr[TERM_YELLOW]); + + + /* Process pending messages */ + (void)Term_xtra_win_flush(); +} + + + +/* + * Prepare the menus + */ +static void setup_menus(void) +{ + int i; + + HMENU hm = GetMenu(data[0].w); + + + /* Menu "File", Disable all */ + EnableMenuItem(hm, IDM_FILE_NEW, + MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); + EnableMenuItem(hm, IDM_FILE_OPEN, + MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); + EnableMenuItem(hm, IDM_FILE_SAVE, + MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); +#ifdef ALLOW_QUITTING + EnableMenuItem(hm, IDM_FILE_ABORT, + MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); +#else + EnableMenuItem(hm, IDM_FILE_SCORE, + MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); +#endif /* ALLOW_QUITTING */ + EnableMenuItem(hm, IDM_FILE_EXIT, + MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); + + /* No character available */ + if (!character_generated) + { + /* Menu "File", Item "New" */ + EnableMenuItem(hm, IDM_FILE_NEW, + MF_BYCOMMAND | MF_ENABLED); + + /* Menu "File", Item "Open" */ + EnableMenuItem(hm, IDM_FILE_OPEN, + MF_BYCOMMAND | MF_ENABLED); + } + + /* A character available */ + if (character_generated) + { + /* Menu "File", Item "Save" */ + EnableMenuItem(hm, IDM_FILE_SAVE, + MF_BYCOMMAND | MF_ENABLED); + } + +#ifdef ALLOW_QUITTING + + /* Menu "File", Item "Abort" */ + EnableMenuItem(hm, IDM_FILE_ABORT, + MF_BYCOMMAND | MF_ENABLED); + +#else + + /* Menu "File", Item "Score" */ + if (initialized && character_generated && !character_icky) + { + EnableMenuItem(hm, IDM_FILE_SCORE, + MF_BYCOMMAND | MF_ENABLED); + } + +#endif + + /* Menu "File", Item "Exit" */ + EnableMenuItem(hm, IDM_FILE_EXIT, + MF_BYCOMMAND | MF_ENABLED); + + + /* Menu "Window::Visibility" */ + for (i = 0; i < MAX_TERM_DATA; i++) + { + EnableMenuItem(hm, IDM_WINDOW_VIS_0 + i, + MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); + + CheckMenuItem(hm, IDM_WINDOW_VIS_0 + i, + (data[i].visible ? MF_CHECKED : MF_UNCHECKED)); + + EnableMenuItem(hm, IDM_WINDOW_VIS_0 + i, + MF_BYCOMMAND | MF_ENABLED); + } + + /* Menu "Window::Font" */ + for (i = 0; i < MAX_TERM_DATA; i++) + { + EnableMenuItem(hm, IDM_WINDOW_FONT_0 + i, + MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); + + if (data[i].visible) + { + EnableMenuItem(hm, IDM_WINDOW_FONT_0 + i, + MF_BYCOMMAND | MF_ENABLED); + } + } + + /* Menu "Window::Bizarre Display" */ + for (i = 0; i < MAX_TERM_DATA; i++) + { + EnableMenuItem(hm, IDM_WINDOW_BIZ_0 + i, + MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); + + CheckMenuItem(hm, IDM_WINDOW_BIZ_0 + i, + (data[i].bizarre ? MF_CHECKED : MF_UNCHECKED)); + + if (data[i].visible) + { + EnableMenuItem(hm, IDM_WINDOW_BIZ_0 + i, + MF_BYCOMMAND | MF_ENABLED); + + } + } + + /* Menu "Window::Increase Tile Width" */ + for (i = 0; i < MAX_TERM_DATA; i++) + { + EnableMenuItem(hm, IDM_WINDOW_I_WID_0 + i, + MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); + + if (data[i].visible) + { + EnableMenuItem(hm, IDM_WINDOW_I_WID_0 + i, + MF_BYCOMMAND | MF_ENABLED); + + } + } + + /* Menu "Window::Decrease Tile Width" */ + for (i = 0; i < MAX_TERM_DATA; i++) + { + EnableMenuItem(hm, IDM_WINDOW_D_WID_0 + i, + MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); + + if (data[i].visible) + { + EnableMenuItem(hm, IDM_WINDOW_D_WID_0 + i, + MF_BYCOMMAND | MF_ENABLED); + + } + } + + /* Menu "Window::Increase Tile Height" */ + for (i = 0; i < MAX_TERM_DATA; i++) + { + EnableMenuItem(hm, IDM_WINDOW_I_HGT_0 + i, + MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); + + if (data[i].visible) + { + EnableMenuItem(hm, IDM_WINDOW_I_HGT_0 + i, + MF_BYCOMMAND | MF_ENABLED); + + } + } + + /* Menu "Window::Decrease Tile Height" */ + for (i = 0; i < MAX_TERM_DATA; i++) + { + EnableMenuItem(hm, IDM_WINDOW_D_HGT_0 + i, + MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); + + if (data[i].visible) + { + EnableMenuItem(hm, IDM_WINDOW_D_HGT_0 + i, + MF_BYCOMMAND | MF_ENABLED); + + } + } + + /* Menu "Options", disable all */ + EnableMenuItem(hm, IDM_OPTIONS_OLD_GRAPHICS, + MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); + EnableMenuItem(hm, IDM_OPTIONS_NEW_GRAPHICS, + MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); + EnableMenuItem(hm, IDM_OPTIONS_ASCII_GRAPHICS, + MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); + EnableMenuItem(hm, IDM_OPTIONS_BIGTILE, + MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); + EnableMenuItem(hm, IDM_OPTIONS_SOUND, + MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); + EnableMenuItem(hm, IDM_OPTIONS_UNUSED, + MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); + EnableMenuItem(hm, IDM_OPTIONS_SAVER, + MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); + + /* Menu "Options", update all */ + CheckMenuItem(hm, IDM_OPTIONS_OLD_GRAPHICS, + (arg_graphics == 1 ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(hm, IDM_OPTIONS_NEW_GRAPHICS, + (arg_graphics == 2 ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(hm, IDM_OPTIONS_ASCII_GRAPHICS, + (arg_graphics == 0 ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(hm, IDM_OPTIONS_BIGTILE, + (arg_bigtile ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(hm, IDM_OPTIONS_SOUND, + (arg_sound ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(hm, IDM_OPTIONS_UNUSED, + (0 ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(hm, IDM_OPTIONS_SAVER, + (hwndSaver ? MF_CHECKED : MF_UNCHECKED)); + +#ifdef USE_GRAPHICS + /* Menu "Options", Item "Graphics" */ + EnableMenuItem(hm, IDM_OPTIONS_OLD_GRAPHICS, MF_ENABLED); + /* Menu "Options", Item "Graphics" */ + EnableMenuItem(hm, IDM_OPTIONS_NEW_GRAPHICS, MF_ENABLED); + /* Menu "Options", Item "Graphics" */ + EnableMenuItem(hm, IDM_OPTIONS_ASCII_GRAPHICS, MF_ENABLED); + /* Menu "Options", Item "Graphics" */ + EnableMenuItem(hm, IDM_OPTIONS_BIGTILE, MF_ENABLED); +#endif + +#ifdef USE_SOUND + /* Menu "Options", Item "Sound" */ + EnableMenuItem(hm, IDM_OPTIONS_SOUND, MF_ENABLED); +#endif + +#ifdef USE_SAVER + /* Menu "Options", Item "ScreenSaver" */ + EnableMenuItem(hm, IDM_OPTIONS_SAVER, + MF_BYCOMMAND | MF_ENABLED); +#endif + +} + + +/* + * Check for double clicked (or dragged) savefile + * + * Apparently, Windows copies the entire filename into the first + * piece of the "command line string". Perhaps we should extract + * the "basename" of that filename and append it to the "save" dir. + */ +static void check_for_save_file(LPSTR cmd_line) +{ + char *s, *p; + + /* First arg */ + s = cmd_line; + + /* Second arg */ + p = strchr(s, ' '); + + /* Tokenize, advance */ + if (p) *p++ = '\0'; + + /* No args */ + if (!*s) return; + + /* Extract filename */ + strcat(savefile, s); + + /* Validate the file */ + validate_file(savefile); + + /* Game in progress */ + game_in_progress = TRUE; + + /* Play game */ + play_game(FALSE); +} + + +/* + * Process a menu command + */ +static void process_menus(WORD wCmd) +{ + int i; + + term_data *td; + + OPENFILENAME ofn; + + /* Analyze */ + switch (wCmd) + { + /* New game */ + case IDM_FILE_NEW: + { + if (!initialized) + { + plog("You cannot do that yet..."); + } + else if (game_in_progress) + { + plog("You can't start a new game while you're still playing!"); + } + else + { + game_in_progress = TRUE; + Term_flush(); + play_game(TRUE); + quit(NULL); + } + break; + } + + /* Open game */ + case IDM_FILE_OPEN: + { + if (!initialized) + { + plog("You cannot do that yet..."); + } + else if (game_in_progress) + { + plog("You can't open a new game while you're still playing!"); + } + else + { + memset(&ofn, 0, sizeof(ofn)); +#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0500) + ofn.lStructSize = sizeof(OPENFILENAME) - (sizeof(void*) + 2 * sizeof(DWORD)); +#else // old headers +ofn.lStructSize = sizeof(OPENFILENAME); +#endif + ofn.hwndOwner = data[0].w; + ofn.lpstrFilter = "Save Files (*.)\0*\0"; + ofn.nFilterIndex = 1; + ofn.lpstrFile = savefile; + ofn.nMaxFile = 1024; + ofn.lpstrInitialDir = ANGBAND_DIR_SAVE; + ofn.Flags = OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR; + + if (GetOpenFileName(&ofn)) + { + /* Load 'savefile' */ + validate_file(savefile); + game_in_progress = TRUE; + Term_flush(); + play_game(FALSE); + quit(NULL); + } + } + break; + } + + /* Save game */ + case IDM_FILE_SAVE: + { + if (game_in_progress && character_generated) + { + /* Paranoia */ + if (!inkey_flag) + { + plog("You may not do that right now."); + break; + } + + /* Hack -- Forget messages */ + msg_flag = FALSE; + + /* Save the game */ + do_cmd_save_game(); + } + else + { + plog("You may not do that right now."); + } + break; + } + + /* Exit */ + case IDM_FILE_EXIT: + { + if (game_in_progress && character_generated) + { + /* Paranoia */ + if (!inkey_flag) + { + plog("You may not do that right now."); + break; + } + + /* Hack -- Forget messages */ + msg_flag = FALSE; + + /* Save the game */ + do_cmd_save_game(); + } + quit(NULL); + break; + } + +#ifdef ALLOW_QUITTING + + /* Abort */ + case IDM_FILE_ABORT: + { + if (game_in_progress && character_generated) + { + /* XXX XXX XXX */ + if (MessageBox(data[0].w, + "Your character will be not saved!", "Warning", + MB_ICONEXCLAMATION | MB_OKCANCEL) == IDCANCEL) + { + break; + } + } + quit(NULL); + break; + } + +#else + + /* Score */ + case IDM_FILE_SCORE: + { + char buf[1024]; + + /* Paranoia */ + if (!initialized || character_icky || + !game_in_progress || !character_generated) + { + /* Can't happen but just in case */ + plog("You may not do that right now."); + + break; + } + + /* Build the pathname of the score file */ + path_build(buf, sizeof(buf), ANGBAND_DIR_APEX, "scores.raw"); + + /* Hack - open the score file for reading */ + highscore_fd = fd_open(buf, O_RDONLY); + + /* Paranoia - No score file */ + if (highscore_fd < 0) + { + msg_print("Score file is not available."); + + break; + } + + /* Mega-Hack - prevent various functions XXX XXX XXX */ + initialized = FALSE; + + /* Save screen */ + screen_save(); + + /* Clear screen */ + Term_clear(); + + /* Prepare scores */ + if (game_in_progress && character_generated) + { + predict_score(); + } + +#if 0 /* I don't like this - pelpel */ + + /* Mega-Hack - No current player XXX XXX XXX XXX */ + else + { + display_scores_aux(0, MAX_HISCORES, -1, NULL); + } + +#endif + + /* Close the high score file */ + (void)fd_close(highscore_fd); + + /* Forget the fd */ + highscore_fd = -1; + + /* Restore screen */ + screen_load(); + + /* Hack - Flush it */ + Term_fresh(); + + /* Mega-Hack - We are ready again */ + initialized = TRUE; + + /* Done */ + break; + } + +#endif + + case IDM_WINDOW_VIS_0: + { + plog("You are not allowed to do that!"); + + break; + } + + /* Window visibility */ + case IDM_WINDOW_VIS_1: + case IDM_WINDOW_VIS_2: + case IDM_WINDOW_VIS_3: + case IDM_WINDOW_VIS_4: + case IDM_WINDOW_VIS_5: + case IDM_WINDOW_VIS_6: + case IDM_WINDOW_VIS_7: + { + i = wCmd - IDM_WINDOW_VIS_0; + + if ((i < 0) || (i >= MAX_TERM_DATA)) break; + + td = &data[i]; + + if (!td->visible) + { + td->visible = TRUE; + ShowWindow(td->w, SW_SHOW); + term_data_redraw(td); + } + else + { + td->visible = FALSE; + ShowWindow(td->w, SW_HIDE); + } + + break; + } + + /* Window fonts */ + case IDM_WINDOW_FONT_0: + case IDM_WINDOW_FONT_1: + case IDM_WINDOW_FONT_2: + case IDM_WINDOW_FONT_3: + case IDM_WINDOW_FONT_4: + case IDM_WINDOW_FONT_5: + case IDM_WINDOW_FONT_6: + case IDM_WINDOW_FONT_7: + { + i = wCmd - IDM_WINDOW_FONT_0; + + if ((i < 0) || (i >= MAX_TERM_DATA)) break; + + td = &data[i]; + + term_change_font(td); + + break; + } + + /* Bizarre Display */ + case IDM_WINDOW_BIZ_0: + case IDM_WINDOW_BIZ_1: + case IDM_WINDOW_BIZ_2: + case IDM_WINDOW_BIZ_3: + case IDM_WINDOW_BIZ_4: + case IDM_WINDOW_BIZ_5: + case IDM_WINDOW_BIZ_6: + case IDM_WINDOW_BIZ_7: + { + i = wCmd - IDM_WINDOW_BIZ_0; + + if ((i < 0) || (i >= MAX_TERM_DATA)) break; + + td = &data[i]; + + td->bizarre = !td->bizarre; + + term_getsize(td); + + term_window_resize(td); + + break; + } + + /* Increase Tile Width */ + case IDM_WINDOW_I_WID_0: + case IDM_WINDOW_I_WID_1: + case IDM_WINDOW_I_WID_2: + case IDM_WINDOW_I_WID_3: + case IDM_WINDOW_I_WID_4: + case IDM_WINDOW_I_WID_5: + case IDM_WINDOW_I_WID_6: + case IDM_WINDOW_I_WID_7: + { + i = wCmd - IDM_WINDOW_I_WID_0; + + if ((i < 0) || (i >= MAX_TERM_DATA)) break; + + td = &data[i]; + + td->tile_wid += 1; + + term_getsize(td); + + term_window_resize(td); + + break; + } + + /* Decrease Tile Height */ + case IDM_WINDOW_D_WID_0: + case IDM_WINDOW_D_WID_1: + case IDM_WINDOW_D_WID_2: + case IDM_WINDOW_D_WID_3: + case IDM_WINDOW_D_WID_4: + case IDM_WINDOW_D_WID_5: + case IDM_WINDOW_D_WID_6: + case IDM_WINDOW_D_WID_7: + { + i = wCmd - IDM_WINDOW_D_WID_0; + + if ((i < 0) || (i >= MAX_TERM_DATA)) break; + + td = &data[i]; + + td->tile_wid -= 1; + + term_getsize(td); + + term_window_resize(td); + + break; + } + + /* Increase Tile Height */ + case IDM_WINDOW_I_HGT_0: + case IDM_WINDOW_I_HGT_1: + case IDM_WINDOW_I_HGT_2: + case IDM_WINDOW_I_HGT_3: + case IDM_WINDOW_I_HGT_4: + case IDM_WINDOW_I_HGT_5: + case IDM_WINDOW_I_HGT_6: + case IDM_WINDOW_I_HGT_7: + { + i = wCmd - IDM_WINDOW_I_HGT_0; + + if ((i < 0) || (i >= MAX_TERM_DATA)) break; + + td = &data[i]; + + td->tile_hgt += 1; + + term_getsize(td); + + term_window_resize(td); + + break; + } + + /* Decrease Tile Height */ + case IDM_WINDOW_D_HGT_0: + case IDM_WINDOW_D_HGT_1: + case IDM_WINDOW_D_HGT_2: + case IDM_WINDOW_D_HGT_3: + case IDM_WINDOW_D_HGT_4: + case IDM_WINDOW_D_HGT_5: + case IDM_WINDOW_D_HGT_6: + case IDM_WINDOW_D_HGT_7: + { + i = wCmd - IDM_WINDOW_D_HGT_0; + + if ((i < 0) || (i >= MAX_TERM_DATA)) break; + + td = &data[i]; + + td->tile_hgt -= 1; + + term_getsize(td); + + term_window_resize(td); + + break; + } + + case IDM_OPTIONS_OLD_GRAPHICS: + { + /* Paranoia */ + if (!inkey_flag) + { + plog("You may not do that right now."); + break; + } + + /* Set "arg_graphics" */ + arg_graphics = 1; + + /* React to changes */ + Term_xtra_win_react(); + + /* Hack -- Force redraw */ + Term_key_push(KTRL('R')); + + break; + } + + case IDM_OPTIONS_NEW_GRAPHICS: + { + /* Paranoia */ + if (!inkey_flag) + { + plog("You may not do that right now."); + break; + } + + /* Set "arg_graphics" */ + arg_graphics = 2; + + /* React to changes */ + Term_xtra_win_react(); + + /* Hack -- Force redraw */ + Term_key_push(KTRL('R')); + + break; + } + case IDM_OPTIONS_ASCII_GRAPHICS: + { + /* Paranoia */ + if (!inkey_flag) + { + plog("You may not do that right now."); + break; + } + + /* Set "ASCII Graphics" */ + arg_graphics = 0; + /* React to Changes */ + Term_xtra_win_react(); + + /* Hack -- Force redraw */ + Term_key_push(KTRL('R')); + + break; + } + + case IDM_OPTIONS_BIGTILE: + { + term_data *td = &data[0]; + + /* Paranoia */ + if (!inkey_flag) + { + plog("You may not do that right now."); + break; + } + + /* Toggle "arg_sound" */ + arg_bigtile = !arg_bigtile; + + /* Activate */ + Term_activate(&td->t); + + /* Resize the term */ + Term_resize(td->cols, td->rows); + + /* Redraw later */ + InvalidateRect(td->w, NULL, TRUE); + + break; + } + + case IDM_OPTIONS_SOUND: + { + /* Paranoia */ + if (!inkey_flag) + { + plog("You may not do that right now."); + break; + } + + /* Toggle "arg_sound" */ + arg_sound = !arg_sound; + + /* React to changes */ + Term_xtra_win_react(); + + /* Hack -- Force redraw */ + Term_key_push(KTRL('R')); + + break; + } + + case IDM_OPTIONS_UNUSED: + { + /* Unused for now XXX XXX XXX */ + + break; + } + +#ifdef USE_SAVER + + case IDM_OPTIONS_SAVER: + { + if (hwndSaver) + { + DestroyWindow(hwndSaver); + hwndSaver = NULL; + } + else + { + /* Create a screen scaver window */ + hwndSaver = CreateWindowEx(WS_EX_TOPMOST, "WindowsScreenSaverClass", + "Angband Screensaver", + WS_POPUP | WS_MAXIMIZE | WS_VISIBLE, + 0, 0, GetSystemMetrics(SM_CXSCREEN), + GetSystemMetrics(SM_CYSCREEN), + NULL, NULL, hInstance, NULL); + + if (hwndSaver) + { + /* Push the window to the bottom XXX XXX XXX */ + SetWindowPos(hwndSaver, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + } + else + { + plog("Failed to create saver window"); + } + } + break; + } + +#endif + + case IDM_HELP_GENERAL: + { + char buf[1024]; + char tmp[1024]; + path_build(tmp, 1024, ANGBAND_DIR_XTRA_HELP, "angband.hlp"); + if (check_file(tmp)) + { + sprintf(buf, "winhelp.exe %s", tmp); + WinExec(buf, SW_NORMAL); + } + else + { + plog_fmt("Cannot find help file: %s", tmp); + plog("Use the online help files instead."); + } + break; + } + + case IDM_HELP_SPOILERS: + { + char buf[1024]; + char tmp[1024]; + path_build(tmp, 1024, ANGBAND_DIR_XTRA_HELP, "spoilers.hlp"); + if (check_file(tmp)) + { + sprintf(buf, "winhelp.exe %s", tmp); + WinExec(buf, SW_NORMAL); + } + else + { + plog_fmt("Cannot find help file: %s", tmp); + plog("Use the online help files instead."); + } + break; + } + } +} + + + +#ifdef __MWERKS__ +LRESULT FAR PASCAL AngbandWndProc(HWND hWnd, UINT uMsg, + WPARAM wParam, LPARAM lParam); +LRESULT FAR PASCAL AngbandWndProc(HWND hWnd, UINT uMsg, + WPARAM wParam, LPARAM lParam) +#else /* __MWERKS__ */ +LRESULT FAR PASCAL AngbandWndProc(HWND hWnd, UINT uMsg, + WPARAM wParam, LPARAM lParam) +#endif /* __MWERKS__ */ +{ + PAINTSTRUCT ps; + HDC hdc; + term_data *td; + MINMAXINFO FAR *lpmmi; + RECT rc; + int i; + + + /* Acquire proper "term_data" info */ + td = (term_data *)GetWindowLong(hWnd, 0); + + /* Handle message */ + switch (uMsg) + { + /* XXX XXX XXX */ + case WM_NCCREATE: + { + SetWindowLong(hWnd, 0, (LONG)(my_td)); + break; + } + + /* XXX XXX XXX */ + case WM_CREATE: + { + return 0; + } + + case WM_GETMINMAXINFO: + { + lpmmi = (MINMAXINFO FAR *)lParam; + + /* this message was sent before WM_NCCREATE */ + if (!td) return 1; + + /* Minimum window size is 8x2 */ + rc.left = rc.top = 0; + rc.right = rc.left + 8 * td->tile_wid + td->size_ow1 + td->size_ow2; + rc.bottom = rc.top + 2 * td->tile_hgt + td->size_oh1 + td->size_oh2 + 1; + + /* Adjust */ + AdjustWindowRectEx(&rc, td->dwStyle, TRUE, td->dwExStyle); + + /* Save minimum size */ + lpmmi->ptMinTrackSize.x = rc.right - rc.left; + lpmmi->ptMinTrackSize.y = rc.bottom - rc.top; + + /* Maximum window size */ + rc.left = rc.top = 0; + rc.right = rc.left + 255 * td->tile_wid + td->size_ow1 + td->size_ow2; + rc.bottom = rc.top + 255 * td->tile_hgt + td->size_oh1 + td->size_oh2; + + /* Paranoia */ + rc.right += (td->tile_wid - 1); + rc.bottom += (td->tile_hgt - 1); + + /* Adjust */ + AdjustWindowRectEx(&rc, td->dwStyle, TRUE, td->dwExStyle); + + /* Save maximum size */ + lpmmi->ptMaxSize.x = rc.right - rc.left; + lpmmi->ptMaxSize.y = rc.bottom - rc.top; + + /* Save maximum size */ + lpmmi->ptMaxTrackSize.x = rc.right - rc.left; + lpmmi->ptMaxTrackSize.y = rc.bottom - rc.top; + + return 0; + } + + case WM_PAINT: + { + BeginPaint(hWnd, &ps); + if (td) term_data_redraw(td); + EndPaint(hWnd, &ps); + ValidateRect(hWnd, NULL); + return 0; + } + + case WM_SYSKEYDOWN: + case WM_KEYDOWN: + { + /* Unused */ + /* BYTE KeyState = 0x00; */ + + bool mc = FALSE; + bool ms = FALSE; + bool ma = FALSE; + + /* Extract the modifiers */ + if (GetKeyState(VK_CONTROL) & 0x8000) mc = TRUE; + if (GetKeyState(VK_SHIFT) & 0x8000) ms = TRUE; + if (GetKeyState(VK_MENU) & 0x8000) ma = TRUE; + + /* Handle "special" keys */ + if (special_key[(byte)(wParam)] || (ma && !ignore_key[(byte)(wParam)]) ) + { + /* Begin the macro trigger */ + Term_keypress(31); + + /* Send the modifiers */ + if (mc) Term_keypress('C'); + if (ms) Term_keypress('S'); + if (ma) Term_keypress('A'); + + /* Extract "scan code" */ + i = LOBYTE(HIWORD(lParam)); + + /* Introduce the scan code */ + Term_keypress('x'); + + /* Encode the hexidecimal scan code */ + Term_keypress(hexsym[i / 16]); + Term_keypress(hexsym[i % 16]); + + /* End the macro trigger */ + Term_keypress(13); + + return 0; + } + + break; + } + + case WM_CHAR: + { + Term_keypress(wParam); + return 0; + } + + case WM_INITMENU: + { + setup_menus(); + return 0; + } + + case WM_CLOSE: + { + if (game_in_progress && character_generated) + { + /* Hack -- Forget messages */ + msg_flag = FALSE; + + /* Save the game */ + do_cmd_save_game(); + } + quit(NULL); + return 0; + } + + case WM_QUIT: + { + quit(NULL); + return 0; + } + + case WM_COMMAND: + { + process_menus(LOWORD(wParam)); + return 0; + } + + case WM_SIZE: + { + /* this message was sent before WM_NCCREATE */ + if (!td) return 1; + + /* it was sent from inside CreateWindowEx */ + if (!td->w) return 1; + + /* was sent from WM_SIZE */ + if (td->size_hack) return 1; + + switch (wParam) + { + case SIZE_MINIMIZED: + { + /* Hide sub-windows */ + for (i = 1; i < MAX_TERM_DATA; i++) + { + if (data[i].visible) ShowWindow(data[i].w, SW_HIDE); + } + return 0; + } + + case SIZE_MAXIMIZED: + { + /* fall through XXX XXX XXX */ + } + + case SIZE_RESTORED: + { + uint cols = (LOWORD(lParam) - td->size_ow1 - td->size_ow2) / td->tile_wid; + uint rows = (HIWORD(lParam) - td->size_oh1 - td->size_oh2) / td->tile_hgt; + + /* New size */ + if ((td->cols != cols) || (td->rows != rows)) + { + /* save the new size */ + td->cols = cols; + td->rows = rows; + + /* Activate */ + Term_activate(&td->t); + + /* Resize the term */ + Term_resize(td->cols, td->rows); + + /* Redraw later */ + InvalidateRect(td->w, NULL, TRUE); + } + + td->size_hack = TRUE; + + /* Restore sub-windows */ + for (i = 1; i < MAX_TERM_DATA; i++) + { + if (data[i].visible) ShowWindow(data[i].w, SW_SHOWNOACTIVATE); + } + + td->size_hack = FALSE; + + return 0; + } + } + break; + } + + case WM_PALETTECHANGED: + { + /* Ignore if palette change caused by itself */ + if ((HWND)wParam == hWnd) return 0; + + /* Fall through... */ + } + + case WM_QUERYNEWPALETTE: + { + if (!paletted) return 0; + + hdc = GetDC(hWnd); + + SelectPalette(hdc, hPal, FALSE); + + i = RealizePalette(hdc); + + /* if any palette entries changed, repaint the window. */ + if (i) InvalidateRect(hWnd, NULL, TRUE); + + ReleaseDC(hWnd, hdc); + + return 0; + } + + case WM_ACTIVATE: + { + if (wParam && !HIWORD(lParam)) + { + /* Do something to sub-windows */ + for (i = 1; i < MAX_TERM_DATA; i++) + { + SetWindowPos(data[i].w, hWnd, 0, 0, 0, 0, + SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); + } + + /* Focus on main window */ + SetFocus(hWnd); + + return 0; + } + + break; + } + } + + return DefWindowProc(hWnd, uMsg, wParam, lParam); +} + + +#ifdef __MWERKS__ +LRESULT FAR PASCAL AngbandListProc(HWND hWnd, UINT uMsg, + WPARAM wParam, LPARAM lParam); +LRESULT FAR PASCAL AngbandListProc(HWND hWnd, UINT uMsg, + WPARAM wParam, LPARAM lParam) +#else /* __MWERKS__ */ +LRESULT FAR PASCAL AngbandListProc(HWND hWnd, UINT uMsg, + WPARAM wParam, LPARAM lParam) +#endif /* __MWERKS__ */ +{ + term_data *td; + MINMAXINFO FAR *lpmmi; + RECT rc; + PAINTSTRUCT ps; + HDC hdc; + int i; + + + /* Acquire proper "term_data" info */ + td = (term_data *)GetWindowLong(hWnd, 0); + + /* Process message */ + switch (uMsg) + { + /* XXX XXX XXX */ + case WM_NCCREATE: + { + SetWindowLong(hWnd, 0, (LONG)(my_td)); + break; + } + + /* XXX XXX XXX */ + case WM_CREATE: + { + return 0; + } + + case WM_GETMINMAXINFO: + { + /* this message was sent before WM_NCCREATE */ + if (!td) return 1; + + lpmmi = (MINMAXINFO FAR *)lParam; + + /* Minimum size */ + rc.left = rc.top = 0; + rc.right = rc.left + 8 * td->tile_wid + td->size_ow1 + td->size_ow2; + rc.bottom = rc.top + 2 * td->tile_hgt + td->size_oh1 + td->size_oh2; + + /* Adjust */ + AdjustWindowRectEx(&rc, td->dwStyle, TRUE, td->dwExStyle); + + /* Save the minimum size */ + lpmmi->ptMinTrackSize.x = rc.right - rc.left; + lpmmi->ptMinTrackSize.y = rc.bottom - rc.top; + + /* Maximum window size */ + rc.left = rc.top = 0; + rc.right = rc.left + 80 * td->tile_wid + td->size_ow1 + td->size_ow2; + rc.bottom = rc.top + 24 * td->tile_hgt + td->size_oh1 + td->size_oh2; + + /* Paranoia */ + rc.right += (td->tile_wid - 1); + rc.bottom += (td->tile_hgt - 1); + + /* Adjust */ + AdjustWindowRectEx(&rc, td->dwStyle, TRUE, td->dwExStyle); + + /* Save maximum size */ + lpmmi->ptMaxSize.x = rc.right - rc.left; + lpmmi->ptMaxSize.y = rc.bottom - rc.top; + + /* Save the maximum size */ + lpmmi->ptMaxTrackSize.x = rc.right - rc.left; + lpmmi->ptMaxTrackSize.y = rc.bottom - rc.top; + + return 0; + } + + case WM_SIZE: + { + /* this message was sent before WM_NCCREATE */ + if (!td) return 1; + + /* it was sent from inside CreateWindowEx */ + if (!td->w) return 1; + + /* was sent from inside WM_SIZE */ + if (td->size_hack) return 1; + + td->size_hack = TRUE; + + td->cols = (LOWORD(lParam) - td->size_ow1 - td->size_ow2) / td->tile_wid; + td->rows = (HIWORD(lParam) - td->size_oh1 - td->size_oh2) / td->tile_hgt; + + term_getsize(td); + + MoveWindow(hWnd, td->pos_x, td->pos_y, td->size_wid, td->size_hgt, TRUE); + + td->size_hack = FALSE; + + return 0; + } + + case WM_PAINT: + { + BeginPaint(hWnd, &ps); + if (td) term_data_redraw(td); + EndPaint(hWnd, &ps); + return 0; + } + + case WM_SYSKEYDOWN: + case WM_KEYDOWN: + { + /* Unused */ + /* BYTE KeyState = 0x00; */ + + bool mc = FALSE; + bool ms = FALSE; + bool ma = FALSE; + + /* Extract the modifiers */ + if (GetKeyState(VK_CONTROL) & 0x8000) mc = TRUE; + if (GetKeyState(VK_SHIFT) & 0x8000) ms = TRUE; + if (GetKeyState(VK_MENU) & 0x8000) ma = TRUE; + + /* Handle "special" keys */ + if (special_key[(byte)(wParam)] || (ma && !ignore_key[(byte)(wParam)]) ) + { + /* Begin the macro trigger */ + Term_keypress(31); + + /* Send the modifiers */ + if (mc) Term_keypress('C'); + if (ms) Term_keypress('S'); + if (ma) Term_keypress('A'); + + /* Extract "scan code" */ + i = LOBYTE(HIWORD(lParam)); + + /* Introduce the scan code */ + Term_keypress('x'); + + /* Encode the hexidecimal scan code */ + Term_keypress(hexsym[i / 16]); + Term_keypress(hexsym[i % 16]); + + /* End the macro trigger */ + Term_keypress(13); + + return 0; + } + + break; + } + + case WM_CHAR: + { + Term_keypress(wParam); + return 0; + } + + case WM_PALETTECHANGED: + { + /* ignore if palette change caused by itself */ + if ((HWND)wParam == hWnd) return FALSE; + /* otherwise, fall through!!! */ + } + + case WM_QUERYNEWPALETTE: + { + if (!paletted) return 0; + hdc = GetDC(hWnd); + SelectPalette(hdc, hPal, FALSE); + i = RealizePalette(hdc); + /* if any palette entries changed, repaint the window. */ + if (i) InvalidateRect(hWnd, NULL, TRUE); + ReleaseDC(hWnd, hdc); + return 0; + } + + case WM_NCLBUTTONDOWN: + { + +#ifdef HTCLOSE + if (wParam == HTCLOSE) wParam = HTSYSMENU; +#endif /* HTCLOSE */ + + if (wParam == HTSYSMENU) + { + if (td->visible) + { + td->visible = FALSE; + ShowWindow(td->w, SW_HIDE); + } + + return 0; + } + + break; + } + } + + return DefWindowProc(hWnd, uMsg, wParam, lParam); +} + + +#ifdef USE_SAVER + +#define MOUSE_SENS 40 + +#ifdef __MWERKS__ +LRESULT FAR PASCAL AngbandSaverProc(HWND hWnd, UINT uMsg, + WPARAM wParam, LPARAM lParam); +LRESULT FAR PASCAL AngbandSaverProc(HWND hWnd, UINT uMsg, + WPARAM wParam, LPARAM lParam) +#else /* __MWERKS__ */ +LRESULT FAR PASCAL AngbandSaverProc(HWND hWnd, UINT uMsg, +WPARAM wParam, LPARAM lParam) +#endif /* __MWERKS__ */ +{ + static int iMouse = 0; + static WORD xMouse = 0; + static WORD yMouse = 0; + + int dx, dy; + + + /* Process */ + switch (uMsg) + { + /* XXX XXX XXX */ + case WM_NCCREATE: + { + break; + } + + case WM_SETCURSOR: + { + SetCursor(NULL); + return 0; + } + +#if 0 + case WM_ACTIVATE: + { + if (LOWORD(wParam) == WA_INACTIVE) break; + + /* else fall through */ + } +#endif + + case WM_LBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_RBUTTONDOWN: + case WM_KEYDOWN: + { + SendMessage(hWnd, WM_CLOSE, 0, 0); + return 0; + } + + case WM_MOUSEMOVE: + { + if (iMouse) + { + dx = LOWORD(lParam) - xMouse; + dy = HIWORD(lParam) - yMouse; + + if (dx < 0) dx = -dx; + if (dy < 0) dy = -dy; + + if ((dx > MOUSE_SENS) || (dy > MOUSE_SENS)) + { + SendMessage(hWnd, WM_CLOSE, 0, 0); + } + } + + /* Save last location */ + iMouse = 1; + xMouse = LOWORD(lParam); + yMouse = HIWORD(lParam); + + return 0; + } + + case WM_CLOSE: + { + DestroyWindow(hwndSaver); + hwndSaver = NULL; + return 0; + } + } + + /* Oops */ + return DefWindowProc(hWnd, uMsg, wParam, lParam); +} + +#endif /* USE_SAVER */ + + + + + +/*** Temporary Hooks ***/ + + +/* + * Display warning message (see "z-util.c") + */ +static void hack_plog(cptr str) +{ + /* Give a warning */ + if (str) + { + MessageBox(NULL, str, "Warning", + MB_ICONEXCLAMATION | MB_OK); + } +} + + +/* + * Display error message and quit (see "z-util.c") + */ +static void hack_quit(cptr str) +{ + /* Give a warning */ + if (str) + { + MessageBox(NULL, str, "Error", + MB_ICONEXCLAMATION | MB_OK | MB_ICONSTOP); + } + + /* Unregister the classes */ + UnregisterClass(AppName, hInstance); + + /* Destroy the icon */ + if (hIcon) DestroyIcon(hIcon); + + /* Exit */ + exit(0); +} + + + +/*** Various hooks ***/ + + +/* + * Display warning message (see "z-util.c") + */ +static void hook_plog(cptr str) +{ + /* Warning */ + if (str) + { + MessageBox(data[0].w, str, "Warning", + MB_ICONEXCLAMATION | MB_OK); + } +} + + +/* + * Display error message and quit (see "z-util.c") + */ +static void hook_quit(cptr str) +{ + int i; + + + /* Give a warning */ + if (str) + { + MessageBox(data[0].w, str, "Error", + MB_ICONEXCLAMATION | MB_OK | MB_ICONSTOP); + } + + + /* Save the preferences */ + save_prefs(); + + + /*** Could use 'Term_nuke_win()' XXX XXX XXX */ + + /* Destroy all windows */ + for (i = MAX_TERM_DATA - 1; i >= 0; --i) + { + term_force_font(&data[i], NULL); + if (data[i].font_want) string_free(data[i].font_want); + if (data[i].w) DestroyWindow(data[i].w); + data[i].w = 0; + } + + + /*** Free some other stuff ***/ + + DeleteObject(hbrYellow); + + if (hPal) DeleteObject(hPal); + + UnregisterClass(AppName, hInstance); + + if (hIcon) DestroyIcon(hIcon); + + exit(0); +} + +/*** Initialize ***/ + + +/* + * Init some stuff + */ +static void init_stuff(void) +{ + int i; + + char path[1024]; + + + /* Get program name with full path */ + GetModuleFileName(hInstance, path, 512); + + /* Get the name of the "*.ini" file */ + strcpy(path + strlen(path) - 4, ".INI"); + + /* Save the the name of the ini-file */ + ini_file = string_make(path); + + /* Validate the ini-file */ + validate_file(ini_file); + + /* Analyze the path */ + i = strlen(path); + + /* Get the path */ + for (; i > 0; i--) + { + if (path[i] == '\\') + { + /* End of path */ + break; + } + } + + /* Add "lib" to the path */ + strcpy(path + i + 1, "lib\\"); + + /* Validate the path */ + validate_dir(path); + + /*** Initialise the file paths ***/ + + /* Start with standard ones */ + init_file_paths(path); + + /* Build the "font" path */ + path_build(path, 1024, ANGBAND_DIR_XTRA, "font"); + + /* Allocate the path */ + ANGBAND_DIR_XTRA_FONT = string_make(path); + + + /*** Validate the paths to ensure we have a working install ***/ + + validate_dir(ANGBAND_DIR_APEX); + validate_dir(ANGBAND_DIR_BONE); + validate_dir(ANGBAND_DIR_DATA); + validate_dir(ANGBAND_DIR_EDIT); + validate_dir(ANGBAND_DIR_FILE); + validate_dir(ANGBAND_DIR_HELP); + validate_dir(ANGBAND_DIR_INFO); + validate_dir(ANGBAND_DIR_NOTE); + validate_dir(ANGBAND_DIR_SAVE); + validate_dir(ANGBAND_DIR_PREF); + validate_dir(ANGBAND_DIR_USER); + validate_dir(ANGBAND_DIR_XTRA); + validate_dir(ANGBAND_DIR_CMOV); + validate_dir(ANGBAND_DIR_XTRA_FONT); + + /* Build the filename */ + path_build(path, 1024, ANGBAND_DIR_XTRA_FONT, "8X13.FON"); + + /* Hack -- Validate the basic font */ + validate_file(path); + + +#ifdef USE_GRAPHICS + + /* Build the "graf" path */ + path_build(path, 1024, ANGBAND_DIR_XTRA, "graf"); + + /* Allocate the path */ + ANGBAND_DIR_XTRA_GRAF = string_make(path); + + /* Validate the "graf" directory */ + validate_dir(ANGBAND_DIR_XTRA_GRAF); + + /* Build the filename */ + path_build(path, 1024, ANGBAND_DIR_XTRA_GRAF, "8X8.BMP"); + + /* Hack -- Validate the basic graf */ + validate_file(path); + +#endif + + +#ifdef USE_SOUND + + /* Build the "sound" path */ + path_build(path, 1024, ANGBAND_DIR_XTRA, "sound"); + + /* Allocate the path */ + ANGBAND_DIR_XTRA_SOUND = string_make(path); + + /* Validate the "sound" directory */ + validate_dir(ANGBAND_DIR_XTRA_SOUND); + +#endif + + + /* Build the "help" path */ + path_build(path, 1024, ANGBAND_DIR_XTRA, "help"); + + /* Allocate the path */ + ANGBAND_DIR_XTRA_HELP = string_make(path); + + /* Validate the "help" directory */ + /* validate_dir(ANGBAND_DIR_XTRA_HELP); */ +} + +int FAR PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, + LPSTR lpCmdLine, int nCmdShow) +{ + int i; + + WNDCLASS wc; + HDC hdc; + MSG msg; + + /* Save globally */ + hInstance = hInst; + + /* Initialize */ + if (hPrevInst == NULL) + { + wc.style = CS_CLASSDC; + wc.lpfnWndProc = AngbandWndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 4; /* one long pointer to term_data */ + wc.hInstance = hInst; + wc.hIcon = hIcon = LoadIcon(hInst, AppName); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = GetStockObject(BLACK_BRUSH); + wc.lpszMenuName = AppName; + wc.lpszClassName = AppName; + + if (!RegisterClass(&wc)) exit(1); + + wc.lpfnWndProc = AngbandListProc; + wc.lpszMenuName = NULL; + wc.lpszClassName = AngList; + + if (!RegisterClass(&wc)) exit(2); + +#ifdef USE_SAVER + + wc.style = CS_VREDRAW | CS_HREDRAW | CS_SAVEBITS | CS_DBLCLKS; + wc.lpfnWndProc = AngbandSaverProc; + wc.hCursor = NULL; + wc.lpszMenuName = NULL; + wc.lpszClassName = "WindowsScreenSaverClass"; + + if (!RegisterClass(&wc)) exit(3); + +#endif + + } + + /* Temporary hooks */ + plog_aux = hack_plog; + quit_aux = hack_quit; + core_aux = hack_quit; + + /* Prepare the filepaths */ + init_stuff(); + + /* Initialize the keypress analyzer */ + for (i = 0; special_key_list[i]; ++i) + { + special_key[special_key_list[i]] = TRUE; + } + + /* Determine if display is 16/256/true color */ + hdc = GetDC(NULL); + colors16 = (GetDeviceCaps(hdc, BITSPIXEL) == 4); + paletted = ((GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) ? TRUE : FALSE); + ReleaseDC(NULL, hdc); + + /* Initialize the colors */ + for (i = 0; i < 256; i++) + { + byte rv, gv, bv; + + /* Extract desired values */ + rv = angband_color_table[i][1]; + gv = angband_color_table[i][2]; + bv = angband_color_table[i][3]; + + /* Extract the "complex" code */ + win_clr[i] = PALETTERGB(rv, gv, bv); + + /* Save the "simple" code */ + angband_color_table[i][0] = win_pal[i]; + } + + /* Prepare the windows */ + init_windows(); + + /* Activate hooks */ + plog_aux = hook_plog; + quit_aux = hook_quit; + core_aux = hook_quit; + + /* Set the system suffix */ + ANGBAND_SYS = "win"; + + + /* Set the keyboard suffix */ + if (7 != GetKeyboardType(0)) + ANGBAND_KEYBOARD = "0"; + else + { + /* Japanese keyboard */ + switch (GetKeyboardType(1)) + { + case 0x0D01: + case 0x0D02: + case 0x0D03: + case 0x0D04: + case 0x0D05: + case 0x0D06: + /* NEC PC-98x1 */ + ANGBAND_KEYBOARD = "NEC98"; + break; + default: + /* PC/AT */ + ANGBAND_KEYBOARD = "JAPAN"; + } + } + + /* Initialize */ + init_angband(); + + /* Prompt the user */ + prt("", 23, 0); + prt("[Press any key to proceed]", 23, 27); + Term_fresh(); + + inkey(); + + /* We are now initialized */ + initialized = TRUE; + + /* Did the user double click on a save file? */ + check_for_save_file(lpCmdLine); + + game_in_progress = TRUE; + play_game(FALSE); + + /* Prompt the user */ + Term_fresh(); + + /* Process messages forever */ + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + /* Initialize the keypress analyzer */ + for (i = 0; ignore_key_list[i]; ++i) + { + ignore_key[ignore_key_list[i]] = TRUE; + } + + /* Paranoia */ + quit(NULL); + + /* Paranoia */ + return (0); +} + + +#endif /* WINDOWS */ + + -- cgit v1.2.3