OSDN Git Service

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