OSDN Git Service

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