OSDN Git Service

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