OSDN Git Service

[Refactor] #38997 reset_visuals() にplayer_type * 引数を追加 / Added player_type * argument...
[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(void);
1890
1891 /*
1892  * Hack -- redraw a term_data
1893  */
1894 static void term_data_redraw(term_data *td)
1895 {
1896         if (td->map_active)
1897         {
1898                 /* Redraw the map */
1899                 windows_map();
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(void)
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(p_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(p_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  * Do a "special thing"
2390  */
2391 static errr Term_xtra_win(int n, int v)
2392 {
2393         /* Handle a subset of the legal requests */
2394         switch (n)
2395         {
2396                 /* Make a bell sound */
2397         case TERM_XTRA_NOISE:
2398         {
2399                 return (Term_xtra_win_noise());
2400         }
2401
2402         /* Play a music */
2403         case TERM_XTRA_MUSIC_BASIC:
2404         case TERM_XTRA_MUSIC_DUNGEON:
2405         case TERM_XTRA_MUSIC_QUEST:
2406         case TERM_XTRA_MUSIC_TOWN:
2407         {
2408                 return (Term_xtra_win_music(n, v));
2409         }
2410
2411         /* Make a special sound */
2412         case TERM_XTRA_SOUND:
2413         {
2414                 return (Term_xtra_win_sound(v));
2415         }
2416
2417         /* Process random events */
2418         case TERM_XTRA_BORED:
2419         {
2420                 return (Term_xtra_win_event(0));
2421         }
2422
2423         /* Process an event */
2424         case TERM_XTRA_EVENT:
2425         {
2426                 return (Term_xtra_win_event(v));
2427         }
2428
2429         /* Flush all events */
2430         case TERM_XTRA_FLUSH:
2431         {
2432                 return (Term_xtra_win_flush());
2433         }
2434
2435         /* Clear the screen */
2436         case TERM_XTRA_CLEAR:
2437         {
2438                 return (Term_xtra_win_clear());
2439         }
2440
2441         /* React to global changes */
2442         case TERM_XTRA_REACT:
2443         {
2444                 return (Term_xtra_win_react());
2445         }
2446
2447         /* Delay for some milliseconds */
2448         case TERM_XTRA_DELAY:
2449         {
2450                 return (Term_xtra_win_delay(v));
2451         }
2452         }
2453
2454         return 1;
2455 }
2456
2457
2458
2459 /*
2460  * Low level graphics (Assumes valid input).
2461  *
2462  * Draw a "cursor" at (x,y), using a "yellow box".
2463  */
2464 static errr Term_curs_win(int x, int y)
2465 {
2466         term_data *td = (term_data*)(Term->data);
2467
2468         RECT rc;
2469         HDC hdc;
2470
2471         int tile_wid, tile_hgt;
2472
2473         if (td->map_active)
2474         {
2475                 tile_wid = td->map_tile_wid;
2476                 tile_hgt = td->map_tile_hgt;
2477         }
2478         else
2479         {
2480                 tile_wid = td->tile_wid;
2481                 tile_hgt = td->tile_hgt;
2482         }
2483
2484         /* Frame the grid */
2485         rc.left = x * tile_wid + td->size_ow1;
2486         rc.right = rc.left + tile_wid;
2487         rc.top = y * tile_hgt + td->size_oh1;
2488         rc.bottom = rc.top + tile_hgt;
2489
2490         /* Cursor is done as a yellow "box" */
2491         hdc = GetDC(td->w);
2492         FrameRect(hdc, &rc, hbrYellow);
2493         ReleaseDC(td->w, hdc);
2494
2495         /* Success */
2496         return 0;
2497 }
2498
2499
2500 /*
2501  * Low level graphics (Assumes valid input).
2502  *
2503  * Draw a "big cursor" at (x,y), using a "yellow box".
2504  */
2505 static errr Term_bigcurs_win(int x, int y)
2506 {
2507         term_data *td = (term_data*)(Term->data);
2508
2509         RECT rc;
2510         HDC hdc;
2511
2512         int tile_wid, tile_hgt;
2513
2514         if (td->map_active)
2515         {
2516                 /* Normal cursor in map window */
2517                 Term_curs_win(x, y);
2518                 return 0;
2519         }
2520         else
2521         {
2522                 tile_wid = td->tile_wid;
2523                 tile_hgt = td->tile_hgt;
2524         }
2525
2526         /* Frame the grid */
2527         rc.left = x * tile_wid + td->size_ow1;
2528         rc.right = rc.left + 2 * tile_wid;
2529         rc.top = y * tile_hgt + td->size_oh1;
2530         rc.bottom = rc.top + tile_hgt;
2531
2532         /* Cursor is done as a yellow "box" */
2533         hdc = GetDC(td->w);
2534         FrameRect(hdc, &rc, hbrYellow);
2535         ReleaseDC(td->w, hdc);
2536
2537         /* Success */
2538         return 0;
2539 }
2540
2541
2542 /*
2543  * Low level graphics (Assumes valid input).
2544  *
2545  * Erase a "block" of "n" characters starting at (x,y).
2546  */
2547 static errr Term_wipe_win(int x, int y, int n)
2548 {
2549         term_data *td = (term_data*)(Term->data);
2550
2551         HDC hdc;
2552         RECT rc;
2553
2554         /* Rectangle to erase in client coords */
2555         rc.left = x * td->tile_wid + td->size_ow1;
2556         rc.right = rc.left + n * td->tile_wid;
2557         rc.top = y * td->tile_hgt + td->size_oh1;
2558         rc.bottom = rc.top + td->tile_hgt;
2559
2560         hdc = GetDC(td->w);
2561         SetBkColor(hdc, RGB(0, 0, 0));
2562         SelectObject(hdc, td->font_id);
2563         /* bg */
2564         if (use_bg)
2565                 DrawBG(hdc, &rc);
2566         else
2567                 ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
2568         ReleaseDC(td->w, hdc);
2569
2570         /* Success */
2571         return 0;
2572 }
2573
2574
2575 /*
2576  * Low level graphics.  Assumes valid input.
2577  *
2578  * Draw several ("n") chars, with an attr, at a given location.
2579  *
2580  * All "graphic" data is handled by "Term_pict_win()", below.
2581  *
2582  * One would think there is a more efficient method for telling a window
2583  * what color it should be using to draw with, but perhaps simply changing
2584  * it every time is not too inefficient.
2585  */
2586 static errr Term_text_win(int x, int y, int n, TERM_COLOR a, concptr s)
2587 {
2588         term_data *td = (term_data*)(Term->data);
2589         RECT rc;
2590         HDC hdc;
2591
2592         static HBITMAP  WALL;
2593         static HBRUSH   myBrush, oldBrush;
2594         static HPEN     oldPen;
2595         static bool init_done = FALSE;
2596
2597         if (!init_done) {
2598                 WALL = LoadBitmap(hInstance, AppName);
2599                 myBrush = CreatePatternBrush(WALL);
2600                 init_done = TRUE;
2601         }
2602
2603         /* Total rectangle */
2604         rc.left = x * td->tile_wid + td->size_ow1;
2605         rc.right = rc.left + n * td->tile_wid;
2606         rc.top = y * td->tile_hgt + td->size_oh1;
2607         rc.bottom = rc.top + td->tile_hgt;
2608
2609         /* Acquire DC */
2610         hdc = GetDC(td->w);
2611
2612         /* Background color */
2613         SetBkColor(hdc, RGB(0, 0, 0));
2614
2615         /* Foreground color */
2616         if (colors16)
2617         {
2618                 SetTextColor(hdc, PALETTEINDEX(win_pal[a]));
2619         }
2620         else if (paletted)
2621         {
2622                 SetTextColor(hdc, win_clr[a & 0x0F]);
2623         }
2624         else
2625         {
2626                 SetTextColor(hdc, win_clr[a]);
2627         }
2628
2629         /* Use the font */
2630         SelectObject(hdc, td->font_id);
2631
2632         /* bg */
2633         if (use_bg) SetBkMode(hdc, TRANSPARENT);
2634
2635         /* Bizarre size */
2636         if (td->bizarre ||
2637                 (td->tile_hgt != td->font_hgt) ||
2638                 (td->tile_wid != td->font_wid))
2639         {
2640                 int i;
2641
2642                 /* Erase complete rectangle */
2643                 ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
2644
2645                 /* bg */
2646                 if (use_bg) DrawBG(hdc, &rc);
2647
2648                 /* New rectangle */
2649                 rc.left += ((td->tile_wid - td->font_wid) / 2);
2650                 rc.right = rc.left + td->font_wid;
2651                 rc.top += ((td->tile_hgt - td->font_hgt) / 2);
2652                 rc.bottom = rc.top + td->font_hgt;
2653
2654                 /* Dump each character */
2655                 for (i = 0; i < n; i++)
2656                 {
2657 #ifdef JP
2658                         if (use_bigtile && *(s + i) == "■"[0] && *(s + i + 1) == "■"[1])
2659                         {
2660                                 rc.right += td->font_wid;
2661
2662                                 oldBrush = SelectObject(hdc, myBrush);
2663                                 oldPen = SelectObject(hdc, GetStockObject(NULL_PEN));
2664
2665                                 /* Dump the wall */
2666                                 Rectangle(hdc, rc.left, rc.top, rc.right + 1, rc.bottom + 1);
2667
2668                                 SelectObject(hdc, oldBrush);
2669                                 SelectObject(hdc, oldPen);
2670                                 rc.right -= td->font_wid;
2671
2672                                 /* Advance */
2673                                 i++;
2674                                 rc.left += 2 * td->tile_wid;
2675                                 rc.right += 2 * td->tile_wid;
2676                         }
2677                         else if (iskanji(*(s + i)))  /*  2バイト文字  */
2678                         {
2679                                 rc.right += td->font_wid;
2680                                 /* Dump the text */
2681                                 ExtTextOut(hdc, rc.left, rc.top, ETO_CLIPPED, &rc,
2682                                         s + i, 2, NULL);
2683                                 rc.right -= td->font_wid;
2684
2685                                 /* Advance */
2686                                 i++;
2687                                 rc.left += 2 * td->tile_wid;
2688                                 rc.right += 2 * td->tile_wid;
2689                         }
2690                         else if (*(s + i) == 127) {
2691                                 oldBrush = SelectObject(hdc, myBrush);
2692                                 oldPen = SelectObject(hdc, GetStockObject(NULL_PEN));
2693
2694                                 /* Dump the wall */
2695                                 Rectangle(hdc, rc.left, rc.top, rc.right + 1, rc.bottom + 1);
2696
2697                                 SelectObject(hdc, oldBrush);
2698                                 SelectObject(hdc, oldPen);
2699
2700                                 /* Advance */
2701                                 rc.left += td->tile_wid;
2702                                 rc.right += td->tile_wid;
2703                         }
2704                         else {
2705                                 /* Dump the text */
2706                                 ExtTextOut(hdc, rc.left, rc.top, ETO_CLIPPED, &rc, s + i, 1, NULL);
2707
2708                                 /* Advance */
2709                                 rc.left += td->tile_wid;
2710                                 rc.right += td->tile_wid;
2711                         }
2712 #else
2713                         if (*(s + i) == 127) {
2714                                 oldBrush = SelectObject(hdc, myBrush);
2715                                 oldPen = SelectObject(hdc, GetStockObject(NULL_PEN));
2716
2717                                 /* Dump the wall */
2718                                 Rectangle(hdc, rc.left, rc.top, rc.right + 1, rc.bottom + 1);
2719
2720                                 SelectObject(hdc, oldBrush);
2721                                 SelectObject(hdc, oldPen);
2722
2723                                 /* Advance */
2724                                 rc.left += td->tile_wid;
2725                                 rc.right += td->tile_wid;
2726                         }
2727                         else {
2728                                 /* Dump the text */
2729                                 ExtTextOut(hdc, rc.left, rc.top, ETO_CLIPPED, &rc,
2730                                         s + i, 1, NULL);
2731
2732                                 /* Advance */
2733                                 rc.left += td->tile_wid;
2734                                 rc.right += td->tile_wid;
2735                         }
2736 #endif
2737
2738                 }
2739         }
2740
2741         /* Normal size */
2742         else
2743         {
2744                 /* Dump the text */
2745                 ExtTextOut(hdc, rc.left, rc.top, ETO_OPAQUE | ETO_CLIPPED, &rc,
2746                         s, n, NULL);
2747         }
2748
2749         /* Release DC */
2750         ReleaseDC(td->w, hdc);
2751
2752         /* Success */
2753         return 0;
2754 }
2755
2756
2757 /*
2758  * Low level graphics.  Assumes valid input.
2759  *
2760  * Draw an array of "special" attr/char pairs at the given location.
2761  *
2762  * We use the "Term_pict_win()" function for "graphic" data, which are
2763  * encoded by setting the "high-bits" of both the "attr" and the "char"
2764  * data.  We use the "attr" to represent the "row" of the main bitmap,
2765  * and the "char" to represent the "col" of the main bitmap.  The use
2766  * of this function is induced by the "higher_pict" flag.
2767  *
2768  * If "graphics" is not available, we simply "wipe" the given grids.
2769  */
2770 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)
2771 {
2772         term_data *td = (term_data*)(Term->data);
2773
2774 #ifdef USE_GRAPHICS
2775
2776         int i;
2777         TERM_LEN x1, y1, w1, h1, tw1, th1;
2778         TERM_LEN x2, y2, w2, h2, tw2 = 0;
2779         TERM_LEN x3, y3;
2780
2781         HDC hdcMask = NULL;
2782
2783         HDC hdc;
2784         HDC hdcSrc;
2785         HBITMAP hbmSrcOld;
2786         if (!use_graphics)
2787         {
2788                 /* Erase the grids */
2789                 return (Term_wipe_win(x, y, n));
2790         }
2791
2792         /* Size of bitmap cell */
2793         w1 = infGraph.CellWidth;
2794         h1 = infGraph.CellHeight;
2795         tw1 = infGraph.TileWidth;
2796         th1 = infGraph.TileHeight;
2797
2798         /* Size of window cell */
2799         if (td->map_active)
2800         {
2801                 w2 = td->map_tile_wid;
2802                 h2 = td->map_tile_hgt;
2803         }
2804         else
2805         {
2806                 w2 = td->tile_wid;
2807                 h2 = td->tile_hgt;
2808                 tw2 = w2;
2809
2810                 /* big tile mode */
2811                 if (use_bigtile) tw2 *= 2;
2812         }
2813
2814         /* Location of window cell */
2815         x2 = x * w2 + td->size_ow1 + infGraph.OffsetX;
2816         y2 = y * h2 + td->size_oh1 + infGraph.OffsetY;
2817
2818         /* Info */
2819         hdc = GetDC(td->w);
2820
2821         /* More info */
2822         hdcSrc = CreateCompatibleDC(hdc);
2823         hbmSrcOld = SelectObject(hdcSrc, infGraph.hBitmap);
2824
2825         if (arg_graphics == GRAPHICS_ADAM_BOLT || arg_graphics == GRAPHICS_HENGBAND)
2826         {
2827                 hdcMask = CreateCompatibleDC(hdc);
2828                 SelectObject(hdcMask, infMask.hBitmap);
2829         }
2830
2831         /* Draw attr/char pairs */
2832         for (i = 0; i < n; i++, x2 += w2)
2833         {
2834                 TERM_COLOR a = ap[i];
2835                 char c = cp[i];
2836
2837
2838                 /* Extract picture */
2839                 int row = (a & 0x7F);
2840                 int col = (c & 0x7F);
2841
2842                 /* Location of bitmap cell */
2843                 x1 = col * w1;
2844                 y1 = row * h1;
2845
2846                 if (arg_graphics == GRAPHICS_ADAM_BOLT || arg_graphics == GRAPHICS_HENGBAND)
2847                 {
2848                         x3 = (tcp[i] & 0x7F) * w1;
2849                         y3 = (tap[i] & 0x7F) * h1;
2850                         tw2 = tw2 * w1 / tw1;
2851                         h2 = h2 * h1 / th1;
2852
2853                         /* Perfect size */
2854                         if ((tw1 == tw2) && (th1 == h2))
2855                         {
2856                                 /* Copy the terrain picture from the bitmap to the window */
2857                                 BitBlt(hdc, x2, y2, tw2, h2, hdcSrc, x3, y3, SRCCOPY);
2858
2859                                 /* Mask out the tile */
2860                                 BitBlt(hdc, x2, y2, tw2, h2, hdcMask, x1, y1, SRCAND);
2861
2862                                 /* Draw the tile */
2863                                 BitBlt(hdc, x2, y2, tw2, h2, hdcSrc, x1, y1, SRCPAINT);
2864                         }
2865
2866                         /* Need to stretch */
2867                         else
2868                         {
2869                                 /* Set the correct mode for stretching the tiles */
2870                                 SetStretchBltMode(hdc, COLORONCOLOR);
2871
2872                                 /* Copy the terrain picture from the bitmap to the window */
2873                                 StretchBlt(hdc, x2, y2, tw2, h2, hdcMask, x3, y3, w1, h1, SRCAND);
2874
2875                                 StretchBlt(hdc, x2, y2, tw2, h2, hdcSrc, x3, y3, w1, h1, SRCPAINT);
2876
2877                                 /* Only draw if terrain and overlay are different */
2878                                 if ((x1 != x3) || (y1 != y3))
2879                                 {
2880                                         /* Mask out the tile */
2881                                         StretchBlt(hdc, x2, y2, tw2, h2, hdcMask, x1, y1, w1, h1, SRCAND);
2882
2883                                         /* Draw the tile */
2884                                         StretchBlt(hdc, x2, y2, tw2, h2, hdcSrc, x1, y1, w1, h1, SRCPAINT);
2885                                 }
2886                         }
2887                 }
2888                 else
2889                 {
2890                         /* Perfect size */
2891                         if ((w1 == tw2) && (h1 == h2))
2892                         {
2893                                 /* Copy the picture from the bitmap to the window */
2894                                 BitBlt(hdc, x2, y2, tw2, h2, hdcSrc, x1, y1, SRCCOPY);
2895                         }
2896
2897                         /* Need to stretch */
2898                         else
2899                         {
2900                                 /* Set the correct mode for stretching the tiles */
2901                                 SetStretchBltMode(hdc, COLORONCOLOR);
2902
2903                                 /* Copy the picture from the bitmap to the window */
2904                                 StretchBlt(hdc, x2, y2, tw2, h2, hdcSrc, x1, y1, w1, h1, SRCCOPY);
2905                         }
2906                 }
2907         }
2908
2909         /* Release */
2910         SelectObject(hdcSrc, hbmSrcOld);
2911         DeleteDC(hdcSrc);
2912
2913         if (arg_graphics == GRAPHICS_ADAM_BOLT || arg_graphics == GRAPHICS_HENGBAND)
2914         {
2915                 /* Release */
2916                 SelectObject(hdcMask, hbmSrcOld);
2917                 DeleteDC(hdcMask);
2918         }
2919
2920         /* Release */
2921         ReleaseDC(td->w, hdc);
2922
2923 #else /* USE_GRAPHICS */
2924
2925         /* Just erase this grid */
2926         return (Term_wipe_win(x, y, n));
2927
2928 #endif /* USE_GRAPHICS */
2929
2930         /* Success */
2931         return 0;
2932 }
2933
2934
2935 static void windows_map(void)
2936 {
2937         term_data *td = &data[0];
2938         TERM_COLOR a;
2939         char c;
2940         TERM_LEN x, min_x, max_x;
2941         TERM_LEN y, min_y, max_y;
2942
2943         TERM_COLOR ta;
2944         char tc;
2945
2946         /* Only in graphics mode */
2947         if (!use_graphics) return;
2948         Term_xtra_win_clear();
2949
2950         td->map_tile_wid = (td->tile_wid * td->cols) / MAX_WID;
2951         td->map_tile_hgt = (td->tile_hgt * td->rows) / MAX_HGT;
2952         td->map_active = TRUE;
2953
2954         {
2955                 min_x = 0;
2956                 min_y = 0;
2957                 max_x = p_ptr->current_floor_ptr->width;
2958                 max_y = p_ptr->current_floor_ptr->height;
2959         }
2960
2961         /* Draw the map */
2962         for (x = min_x; x < max_x; x++)
2963         {
2964                 for (y = min_y; y < max_y; y++)
2965                 {
2966                         map_info(y, x, &a, (char*)&c, &ta, (char*)&tc);
2967
2968                         /* Ignore non-graphics */
2969                         if ((a & 0x80) && (c & 0x80))
2970                         {
2971                                 Term_pict_win(x - min_x, y - min_y, 1, &a, &c, &ta, &tc);
2972                         }
2973                 }
2974         }
2975
2976         /* Hilite the player */
2977         Term_curs_win(p_ptr->x - min_x, p_ptr->y - min_y);
2978
2979         /* Wait for a keypress, flush key buffer */
2980         Term_inkey(&c, TRUE, TRUE);
2981         Term_flush();
2982
2983         /* Switch off the map display */
2984         td->map_active = FALSE;
2985
2986         /* Restore screen */
2987         Term_xtra_win_clear();
2988         Term_redraw();
2989 }
2990
2991
2992 /*** Other routines ***/
2993
2994
2995 /*
2996  * Create and initialize a "term_data" given a title
2997  */
2998 static void term_data_link(term_data *td)
2999 {
3000         term *t = &td->t;
3001
3002         /* Initialize the term */
3003         term_init(t, td->cols, td->rows, td->keys);
3004
3005         /* Use a "software" cursor */
3006         t->soft_cursor = TRUE;
3007
3008         /* Use "Term_pict" for "graphic" data */
3009         t->higher_pict = TRUE;
3010
3011         /* Erase with "white space" */
3012         t->attr_blank = TERM_WHITE;
3013         t->char_blank = ' ';
3014
3015         /* Prepare the template hooks */
3016         t->user_hook = Term_user_win;
3017         t->xtra_hook = Term_xtra_win;
3018         t->curs_hook = Term_curs_win;
3019         t->bigcurs_hook = Term_bigcurs_win;
3020         t->wipe_hook = Term_wipe_win;
3021         t->text_hook = Term_text_win;
3022         t->pict_hook = Term_pict_win;
3023
3024         /* Remember where we came from */
3025         t->data = (vptr)(td);
3026 }
3027
3028
3029 /*
3030  * Create the windows
3031  *
3032  * First, instantiate the "default" values, then read the "ini_file"
3033  * to over-ride selected values, then create the windows, and fonts.
3034  *
3035  * Must use SW_SHOW not SW_SHOWNA, since on 256 color display
3036  * must make active to realize the palette.
3037  */
3038 static void init_windows(void)
3039 {
3040         int i;
3041
3042         term_data *td;
3043
3044         /* Main window */
3045         td = &data[0];
3046         WIPE(td, term_data);
3047 #ifdef JP
3048         td->s = "変愚蛮怒";
3049 #else
3050         td->s = angband_term_name[0];
3051 #endif
3052
3053         td->keys = 1024;
3054         td->rows = 24;
3055         td->cols = 80;
3056         td->visible = TRUE;
3057         td->size_ow1 = 2;
3058         td->size_ow2 = 2;
3059         td->size_oh1 = 2;
3060         td->size_oh2 = 2;
3061         td->pos_x = 7 * 30;
3062         td->pos_y = 7 * 20;
3063         td->posfix = FALSE;
3064         td->bizarre = TRUE;
3065         /* Sub windows */
3066         for (i = 1; i < MAX_TERM_DATA; i++)
3067         {
3068                 td = &data[i];
3069                 WIPE(td, term_data);
3070                 td->s = angband_term_name[i];
3071                 td->keys = 16;
3072                 td->rows = 24;
3073                 td->cols = 80;
3074                 td->visible = FALSE;
3075                 td->size_ow1 = 1;
3076                 td->size_ow2 = 1;
3077                 td->size_oh1 = 1;
3078                 td->size_oh2 = 1;
3079                 td->pos_x = (7 - i) * 30;
3080                 td->pos_y = (7 - i) * 20;
3081                 td->posfix = FALSE;
3082                 td->bizarre = TRUE;
3083         }
3084
3085         /* Load prefs */
3086         load_prefs();
3087
3088         /* Main window (need these before term_getsize gets called) */
3089         td = &data[0];
3090         td->dwStyle = (WS_OVERLAPPED | WS_THICKFRAME | WS_SYSMENU |
3091                 WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CAPTION |
3092                 WS_VISIBLE);
3093         td->dwExStyle = 0;
3094         td->visible = TRUE;
3095
3096         /* Sub windows (need these before term_getsize gets called) */
3097         for (i = 1; i < MAX_TERM_DATA; i++)
3098         {
3099                 td = &data[i];
3100                 td->dwStyle = (WS_OVERLAPPED | WS_THICKFRAME | WS_SYSMENU);
3101                 td->dwExStyle = (WS_EX_TOOLWINDOW);
3102         }
3103
3104
3105         /* All windows */
3106         for (i = 0; i < MAX_TERM_DATA; i++)
3107         {
3108                 td = &data[i];
3109
3110                 strncpy(td->lf.lfFaceName, td->font_want, LF_FACESIZE);
3111                 td->lf.lfCharSet = DEFAULT_CHARSET;
3112                 td->lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
3113                 /* Activate the chosen font */
3114                 term_force_font(td, NULL);
3115                 if (!td->tile_wid) td->tile_wid = td->font_wid;
3116                 if (!td->tile_hgt) td->tile_hgt = td->font_hgt;
3117
3118                 /* Analyze the font */
3119                 term_getsize(td);
3120
3121                 /* Resize the window */
3122                 term_window_resize(td);
3123         }
3124
3125
3126         /* Sub windows (reverse order) */
3127         for (i = MAX_TERM_DATA - 1; i >= 1; --i)
3128         {
3129                 td = &data[i];
3130
3131                 my_td = td;
3132                 td->w = CreateWindowEx(td->dwExStyle, AngList,
3133                         td->s, td->dwStyle,
3134                         td->pos_x, td->pos_y,
3135                         td->size_wid, td->size_hgt,
3136                         HWND_DESKTOP, NULL, hInstance, NULL);
3137                 my_td = NULL;
3138                 if (!td->w) quit(_("サブウィンドウに作成に失敗しました", "Failed to create sub-window"));
3139
3140                 if (td->visible)
3141                 {
3142                         td->size_hack = TRUE;
3143                         ShowWindow(td->w, SW_SHOW);
3144                         td->size_hack = FALSE;
3145                 }
3146
3147                 term_data_link(td);
3148                 angband_term[i] = &td->t;
3149
3150                 if (td->visible)
3151                 {
3152                         /* Activate the window */
3153                         SetActiveWindow(td->w);
3154                 }
3155
3156                 if (data[i].posfix)
3157                 {
3158                         term_window_pos(&data[i], HWND_TOPMOST);
3159                 }
3160                 else
3161                 {
3162                         term_window_pos(&data[i], td->w);
3163                 }
3164         }
3165
3166
3167         /* Main window */
3168         td = &data[0];
3169
3170         /* Main window */
3171         my_td = td;
3172         td->w = CreateWindowEx(td->dwExStyle, AppName,
3173                 td->s, td->dwStyle,
3174                 td->pos_x, td->pos_y,
3175                 td->size_wid, td->size_hgt,
3176                 HWND_DESKTOP, NULL, hInstance, NULL);
3177         my_td = NULL;
3178         if (!td->w) quit(_("メインウィンドウの作成に失敗しました", "Failed to create Angband window"));
3179
3180         term_data_link(td);
3181         angband_term[0] = &td->t;
3182         normsize.x = td->cols;
3183         normsize.y = td->rows;
3184
3185         /* Activate the main window */
3186         if (win_maximized) ShowWindow(td->w, SW_SHOWMAXIMIZED);
3187         else ShowWindow(td->w, SW_SHOW);
3188
3189         /* Bring main window back to top */
3190         SetWindowPos(td->w, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
3191
3192
3193         /* New palette */
3194         (void)new_palette();
3195
3196
3197         /* Create a "brush" for drawing the "cursor" */
3198         hbrYellow = CreateSolidBrush(win_clr[TERM_YELLOW]);
3199
3200
3201         /* Process pending messages */
3202         (void)Term_xtra_win_flush();
3203 }
3204
3205
3206
3207 /*
3208  * Prepare the menus
3209  */
3210 static void setup_menus(void)
3211 {
3212         int i;
3213
3214         HMENU hm = GetMenu(data[0].w);
3215
3216
3217         /* Menu "File", Disable all */
3218         EnableMenuItem(hm, IDM_FILE_NEW,
3219                 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
3220         EnableMenuItem(hm, IDM_FILE_OPEN,
3221                 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
3222         EnableMenuItem(hm, IDM_FILE_SAVE,
3223                 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
3224         EnableMenuItem(hm, IDM_FILE_EXIT,
3225                 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
3226         EnableMenuItem(hm, IDM_FILE_SCORE,
3227                 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
3228
3229
3230         /* No character available */
3231         if (!current_world_ptr->character_generated)
3232         {
3233                 /* Menu "File", Item "New" */
3234                 EnableMenuItem(hm, IDM_FILE_NEW, MF_BYCOMMAND | MF_ENABLED);
3235
3236                 /* Menu "File", Item "Open" */
3237                 EnableMenuItem(hm, IDM_FILE_OPEN, MF_BYCOMMAND | MF_ENABLED);
3238         }
3239
3240         /* A character available */
3241         if (current_world_ptr->character_generated)
3242         {
3243                 /* Menu "File", Item "Save" */
3244                 EnableMenuItem(hm, IDM_FILE_SAVE,
3245                         MF_BYCOMMAND | MF_ENABLED);
3246         }
3247
3248         /* Menu "File", Item "Exit" */
3249         EnableMenuItem(hm, IDM_FILE_EXIT,
3250                 MF_BYCOMMAND | MF_ENABLED);
3251
3252         EnableMenuItem(hm, IDM_FILE_SCORE,
3253                 MF_BYCOMMAND | MF_ENABLED);
3254
3255
3256         /* Menu "Window::Visibility" */
3257         for (i = 0; i < MAX_TERM_DATA; i++)
3258         {
3259                 EnableMenuItem(hm, IDM_WINDOW_VIS_0 + i,
3260                         MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
3261
3262                 CheckMenuItem(hm, IDM_WINDOW_VIS_0 + i,
3263                         (data[i].visible ? MF_CHECKED : MF_UNCHECKED));
3264
3265                 EnableMenuItem(hm, IDM_WINDOW_VIS_0 + i,
3266                         MF_BYCOMMAND | MF_ENABLED);
3267         }
3268
3269         /* Menu "Window::Font" */
3270         for (i = 0; i < MAX_TERM_DATA; i++)
3271         {
3272                 EnableMenuItem(hm, IDM_WINDOW_FONT_0 + i,
3273                         MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
3274
3275                 if (data[i].visible)
3276                 {
3277                         EnableMenuItem(hm, IDM_WINDOW_FONT_0 + i,
3278                                 MF_BYCOMMAND | MF_ENABLED);
3279                 }
3280         }
3281
3282         /* Menu "Window::Window Position Fix" */
3283         for (i = 0; i < MAX_TERM_DATA; i++)
3284         {
3285                 EnableMenuItem(hm, IDM_WINDOW_POS_0 + i,
3286                         MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
3287
3288                 CheckMenuItem(hm, IDM_WINDOW_POS_0 + i,
3289                         (data[i].posfix ? MF_CHECKED : MF_UNCHECKED));
3290
3291                 if (data[i].visible)
3292                 {
3293                         EnableMenuItem(hm, IDM_WINDOW_POS_0 + i,
3294                                 MF_BYCOMMAND | MF_ENABLED);
3295                 }
3296         }
3297
3298         /* Menu "Window::Bizarre Display" */
3299         for (i = 0; i < MAX_TERM_DATA; i++)
3300         {
3301                 EnableMenuItem(hm, IDM_WINDOW_BIZ_0 + i,
3302                         MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
3303
3304                 CheckMenuItem(hm, IDM_WINDOW_BIZ_0 + i,
3305                         (data[i].bizarre ? MF_CHECKED : MF_UNCHECKED));
3306
3307                 if (data[i].visible)
3308                 {
3309                         EnableMenuItem(hm, IDM_WINDOW_BIZ_0 + i,
3310                                 MF_BYCOMMAND | MF_ENABLED);
3311
3312                 }
3313         }
3314
3315         /* Menu "Window::Increase Tile Width" */
3316         for (i = 0; i < MAX_TERM_DATA; i++)
3317         {
3318                 EnableMenuItem(hm, IDM_WINDOW_I_WID_0 + i,
3319                         MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
3320
3321                 if (data[i].visible)
3322                 {
3323                         EnableMenuItem(hm, IDM_WINDOW_I_WID_0 + i,
3324                                 MF_BYCOMMAND | MF_ENABLED);
3325
3326                 }
3327         }
3328
3329         /* Menu "Window::Decrease Tile Width" */
3330         for (i = 0; i < MAX_TERM_DATA; i++)
3331         {
3332                 EnableMenuItem(hm, IDM_WINDOW_D_WID_0 + i,
3333                         MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
3334
3335                 if (data[i].visible)
3336                 {
3337                         EnableMenuItem(hm, IDM_WINDOW_D_WID_0 + i,
3338                                 MF_BYCOMMAND | MF_ENABLED);
3339
3340                 }
3341         }
3342
3343         /* Menu "Window::Increase Tile Height" */
3344         for (i = 0; i < MAX_TERM_DATA; i++)
3345         {
3346                 EnableMenuItem(hm, IDM_WINDOW_I_HGT_0 + i,
3347                         MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
3348
3349                 if (data[i].visible)
3350                 {
3351                         EnableMenuItem(hm, IDM_WINDOW_I_HGT_0 + i,
3352                                 MF_BYCOMMAND | MF_ENABLED);
3353
3354                 }
3355         }
3356
3357         /* Menu "Window::Decrease Tile Height" */
3358         for (i = 0; i < MAX_TERM_DATA; i++)
3359         {
3360                 EnableMenuItem(hm, IDM_WINDOW_D_HGT_0 + i,
3361                         MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
3362
3363                 if (data[i].visible)
3364                 {
3365                         EnableMenuItem(hm, IDM_WINDOW_D_HGT_0 + i,
3366                                 MF_BYCOMMAND | MF_ENABLED);
3367
3368                 }
3369         }
3370
3371         /* Menu "Options", disable all */
3372         EnableMenuItem(hm, IDM_OPTIONS_NO_GRAPHICS,
3373                 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
3374         EnableMenuItem(hm, IDM_OPTIONS_OLD_GRAPHICS,
3375                 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
3376         EnableMenuItem(hm, IDM_OPTIONS_NEW_GRAPHICS,
3377                 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
3378         EnableMenuItem(hm, IDM_OPTIONS_BIGTILE,
3379                 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
3380         EnableMenuItem(hm, IDM_OPTIONS_SOUND,
3381                 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
3382 #ifdef JP
3383 #else
3384
3385         EnableMenuItem(hm, IDM_OPTIONS_SAVER,
3386                 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
3387 #endif
3388
3389         /* Menu "Options", Item "Map" */
3390         if (use_graphics != GRAPHICS_NONE)
3391                 EnableMenuItem(GetMenu(data[0].w), IDM_OPTIONS_MAP, MF_BYCOMMAND | MF_ENABLED);
3392         else
3393                 EnableMenuItem(GetMenu(data[0].w), IDM_OPTIONS_MAP,
3394                         MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
3395
3396         /* Menu "Options", update all */
3397         CheckMenuItem(hm, IDM_OPTIONS_NO_GRAPHICS,
3398                 (arg_graphics == GRAPHICS_NONE ? MF_CHECKED : MF_UNCHECKED));
3399         CheckMenuItem(hm, IDM_OPTIONS_OLD_GRAPHICS,
3400                 (arg_graphics == GRAPHICS_ORIGINAL ? MF_CHECKED : MF_UNCHECKED));
3401         CheckMenuItem(hm, IDM_OPTIONS_NEW_GRAPHICS,
3402                 (arg_graphics == GRAPHICS_ADAM_BOLT ? MF_CHECKED : MF_UNCHECKED));
3403         CheckMenuItem(hm, IDM_OPTIONS_NEW2_GRAPHICS,
3404                 (arg_graphics == GRAPHICS_HENGBAND ? MF_CHECKED : MF_UNCHECKED));
3405         CheckMenuItem(hm, IDM_OPTIONS_BIGTILE,
3406                 (arg_bigtile ? MF_CHECKED : MF_UNCHECKED));
3407         CheckMenuItem(hm, IDM_OPTIONS_MUSIC,
3408                 (arg_music ? MF_CHECKED : MF_UNCHECKED));
3409         CheckMenuItem(hm, IDM_OPTIONS_SOUND,
3410                 (arg_sound ? MF_CHECKED : MF_UNCHECKED));
3411         CheckMenuItem(hm, IDM_OPTIONS_BG,
3412                 (use_bg ? MF_CHECKED : MF_UNCHECKED));
3413 #ifdef JP
3414 #else
3415
3416         CheckMenuItem(hm, IDM_OPTIONS_SAVER,
3417                 (hwndSaver ? MF_CHECKED : MF_UNCHECKED));
3418 #endif
3419
3420 #ifdef USE_GRAPHICS
3421         /* Menu "Options", Item "Graphics" */
3422         EnableMenuItem(hm, IDM_OPTIONS_NO_GRAPHICS, MF_ENABLED);
3423         /* Menu "Options", Item "Graphics" */
3424         EnableMenuItem(hm, IDM_OPTIONS_OLD_GRAPHICS, MF_ENABLED);
3425         /* Menu "Options", Item "Graphics" */
3426         EnableMenuItem(hm, IDM_OPTIONS_NEW_GRAPHICS, MF_ENABLED);
3427         /* Menu "Options", Item "Graphics" */
3428         EnableMenuItem(hm, IDM_OPTIONS_BIGTILE, MF_ENABLED);
3429 #endif /* USE_GRAPHICS */
3430
3431 #ifdef USE_SOUND
3432         /* Menu "Options", Item "Sound" */
3433         EnableMenuItem(hm, IDM_OPTIONS_SOUND, MF_ENABLED);
3434 #endif /* USE_SOUND */
3435
3436 #ifdef USE_SAVER
3437         /* Menu "Options", Item "ScreenSaver" */
3438         EnableMenuItem(hm, IDM_OPTIONS_SAVER,
3439                 MF_BYCOMMAND | MF_ENABLED);
3440 #endif /* USE_SAVER */
3441 }
3442
3443
3444 /*
3445  * Check for double clicked (or dragged) savefile
3446  *
3447  * Apparently, Windows copies the entire filename into the first
3448  * piece of the "command line string".  Perhaps we should extract
3449  * the "basename" of that filename and append it to the "save" dir.
3450  */
3451 static void check_for_save_file(LPSTR cmd_line)
3452 {
3453         char *s;
3454
3455         /* First arg */
3456         s = cmd_line;
3457
3458         /* No args */
3459         if (!*s) return;
3460
3461         /* Extract filename */
3462         strcat(savefile, s);
3463
3464         /* Validate the file */
3465         validate_file(savefile);
3466
3467         /* Game in progress */
3468         game_in_progress = TRUE;
3469
3470         /* Play game */
3471         play_game(p_ptr, FALSE);
3472 }
3473
3474
3475 /*
3476  * Process a menu command
3477  */
3478 static void process_menus(WORD wCmd)
3479 {
3480         int i;
3481
3482         term_data *td;
3483
3484         OPENFILENAME ofn;
3485
3486         /* Analyze */
3487         switch (wCmd)
3488         {
3489                 /* New game */
3490         case IDM_FILE_NEW:
3491         {
3492                 if (!initialized)
3493                 {
3494                         plog(_("まだ初期化中です...", "You cannot do that yet..."));
3495                 }
3496                 else if (game_in_progress)
3497                 {
3498                         plog(_("プレイ中は新しいゲームを始めることができません!", "You can't start a new game while you're still playing!"));
3499                 }
3500                 else
3501                 {
3502                         game_in_progress = TRUE;
3503                         Term_flush();
3504                         play_game(p_ptr, TRUE);
3505                         quit(NULL);
3506                 }
3507                 break;
3508         }
3509
3510         /* Open game */
3511         case IDM_FILE_OPEN:
3512         {
3513                 if (!initialized)
3514                 {
3515                         plog(_("まだ初期化中です...", "You cannot do that yet..."));
3516                 }
3517                 else if (game_in_progress)
3518                 {
3519                         plog(_("プレイ中はゲームをロードすることができません!", "You can't open a new game while you're still playing!"));
3520                 }
3521                 else
3522                 {
3523                         memset(&ofn, 0, sizeof(ofn));
3524                         ofn.lStructSize = sizeof(ofn);
3525                         ofn.hwndOwner = data[0].w;
3526                         ofn.lpstrFilter = "Save Files (*.)\0*\0";
3527                         ofn.nFilterIndex = 1;
3528                         ofn.lpstrFile = savefile;
3529                         ofn.nMaxFile = 1024;
3530                         ofn.lpstrInitialDir = ANGBAND_DIR_SAVE;
3531                         ofn.Flags = OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR | OFN_HIDEREADONLY;
3532
3533                         if (GetOpenFileName(&ofn))
3534                         {
3535                                 /* Load 'savefile' */
3536                                 validate_file(savefile);
3537                                 game_in_progress = TRUE;
3538                                 Term_flush();
3539                                 play_game(p_ptr, FALSE);
3540                                 quit(NULL);
3541                         }
3542                 }
3543                 break;
3544         }
3545
3546         /* Save game */
3547         case IDM_FILE_SAVE:
3548         {
3549                 if (game_in_progress && current_world_ptr->character_generated)
3550                 {
3551                         if (!can_save)
3552                         {
3553                                 plog(_("今はセーブすることは出来ません。", "You may not do that right now."));
3554                                 break;
3555                         }
3556
3557                         /* Hack -- Forget messages */
3558                         msg_flag = FALSE;
3559
3560                         /* Save the game */
3561 #ifdef ZANGBAND
3562                         do_cmd_save_game(p_ptr, FALSE);
3563 #else /* ZANGBAND */
3564                         do_cmd_save_game();
3565 #endif /* ZANGBAND */
3566                 }
3567                 else
3568                 {
3569                         plog(_("今、セーブすることは出来ません。", "You may not do that right now."));
3570                 }
3571                 break;
3572         }
3573
3574         case IDM_FILE_EXIT:
3575         {
3576                 if (game_in_progress && current_world_ptr->character_generated)
3577                 {
3578                         if (!can_save)
3579                         {
3580                                 plog(_("今は終了できません。", "You may not do that right now."));
3581                                 break;
3582                         }
3583
3584                         /* Hack -- Forget messages */
3585                         msg_flag = FALSE;
3586
3587                         forget_lite(p_ptr->current_floor_ptr);
3588                         forget_view(p_ptr->current_floor_ptr);
3589                         clear_mon_lite(p_ptr->current_floor_ptr);
3590
3591                         /* Save the game */
3592 #ifdef ZANGBAND
3593                                 /* do_cmd_save_game(FALSE); */
3594 #else /* ZANGBAND */
3595                                 /* do_cmd_save_game(); */
3596 #endif /* ZANGBAND */
3597                         Term_key_push(SPECIAL_KEY_QUIT);
3598                         break;
3599                 }
3600                 quit(NULL);
3601                 break;
3602         }
3603
3604         /* Show scores */
3605         case IDM_FILE_SCORE:
3606         {
3607                 char buf[1024];
3608                 path_build(buf, sizeof(buf), ANGBAND_DIR_APEX, "scores.raw");
3609
3610                 /* Open the binary high score file, for reading */
3611                 highscore_fd = fd_open(buf, O_RDONLY);
3612
3613                 /* Paranoia -- No score file */
3614                 if (highscore_fd < 0)
3615                 {
3616                         msg_print("Score file unavailable.");
3617                 }
3618                 else
3619                 {
3620                         screen_save();
3621                         Term_clear();
3622
3623                         /* Display the scores */
3624                         display_scores_aux(0, MAX_HISCORES, -1, NULL);
3625
3626                         /* Shut the high score file */
3627                         (void)fd_close(highscore_fd);
3628
3629                         /* Forget the high score fd */
3630                         highscore_fd = -1;
3631                         screen_load();
3632
3633                         /* Hack - Flush it */
3634                         Term_fresh();
3635                 }
3636
3637                 break;
3638         }
3639
3640         /* Open game */
3641         case IDM_FILE_MOVIE:
3642         {
3643                 if (!initialized)
3644                 {
3645                         plog(_("まだ初期化中です...", "You cannot do that yet..."));
3646                 }
3647                 else if (game_in_progress)
3648                 {
3649                         plog(_("プレイ中はムービーをロードすることができません!", "You can't open a movie while you're playing!"));
3650                 }
3651                 else
3652                 {
3653                         memset(&ofn, 0, sizeof(ofn));
3654                         ofn.lStructSize = sizeof(ofn);
3655                         ofn.hwndOwner = data[0].w;
3656                         ofn.lpstrFilter = "Angband Movie Files (*.amv)\0*.amv\0";
3657                         ofn.nFilterIndex = 1;
3658                         ofn.lpstrFile = savefile;
3659                         ofn.nMaxFile = 1024;
3660                         ofn.lpstrInitialDir = ANGBAND_DIR_USER;
3661                         ofn.Flags = OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR;
3662
3663                         if (GetOpenFileName(&ofn))
3664                         {
3665                                 /* Load 'savefile' */
3666                                 prepare_browse_movie_aux(savefile);
3667                                 play_game(p_ptr, FALSE);
3668                                 quit(NULL);
3669                                 return;
3670                         }
3671                 }
3672                 break;
3673         }
3674
3675
3676         case IDM_WINDOW_VIS_0:
3677         {
3678                 plog(_("メインウィンドウは非表示にできません!", "You are not allowed to do that!"));
3679                 break;
3680         }
3681
3682         /* Window visibility */
3683         case IDM_WINDOW_VIS_1:
3684         case IDM_WINDOW_VIS_2:
3685         case IDM_WINDOW_VIS_3:
3686         case IDM_WINDOW_VIS_4:
3687         case IDM_WINDOW_VIS_5:
3688         case IDM_WINDOW_VIS_6:
3689         case IDM_WINDOW_VIS_7:
3690         {
3691                 i = wCmd - IDM_WINDOW_VIS_0;
3692
3693                 if ((i < 0) || (i >= MAX_TERM_DATA)) break;
3694
3695                 td = &data[i];
3696
3697                 if (!td->visible)
3698                 {
3699                         td->visible = TRUE;
3700                         ShowWindow(td->w, SW_SHOW);
3701                         term_data_redraw(td);
3702                 }
3703                 else
3704                 {
3705                         td->visible = FALSE;
3706                         td->posfix = FALSE;
3707                         ShowWindow(td->w, SW_HIDE);
3708                 }
3709
3710                 break;
3711         }
3712
3713         /* Window fonts */
3714         case IDM_WINDOW_FONT_0:
3715         case IDM_WINDOW_FONT_1:
3716         case IDM_WINDOW_FONT_2:
3717         case IDM_WINDOW_FONT_3:
3718         case IDM_WINDOW_FONT_4:
3719         case IDM_WINDOW_FONT_5:
3720         case IDM_WINDOW_FONT_6:
3721         case IDM_WINDOW_FONT_7:
3722         {
3723                 i = wCmd - IDM_WINDOW_FONT_0;
3724
3725                 if ((i < 0) || (i >= MAX_TERM_DATA)) break;
3726
3727                 td = &data[i];
3728
3729                 term_change_font(td);
3730
3731                 break;
3732         }
3733
3734         /* Window Z Position */
3735         case IDM_WINDOW_POS_1:
3736         case IDM_WINDOW_POS_2:
3737         case IDM_WINDOW_POS_3:
3738         case IDM_WINDOW_POS_4:
3739         case IDM_WINDOW_POS_5:
3740         case IDM_WINDOW_POS_6:
3741         case IDM_WINDOW_POS_7:
3742         {
3743                 i = wCmd - IDM_WINDOW_POS_0;
3744
3745                 if ((i < 0) || (i >= MAX_TERM_DATA)) break;
3746
3747                 td = &data[i];
3748
3749                 if (!td->posfix && td->visible)
3750                 {
3751                         td->posfix = TRUE;
3752                         term_window_pos(td, HWND_TOPMOST);
3753                 }
3754                 else
3755                 {
3756                         td->posfix = FALSE;
3757                         term_window_pos(td, data[0].w);
3758                 }
3759
3760                 break;
3761         }
3762
3763         /* Bizarre Display */
3764         case IDM_WINDOW_BIZ_0:
3765         case IDM_WINDOW_BIZ_1:
3766         case IDM_WINDOW_BIZ_2:
3767         case IDM_WINDOW_BIZ_3:
3768         case IDM_WINDOW_BIZ_4:
3769         case IDM_WINDOW_BIZ_5:
3770         case IDM_WINDOW_BIZ_6:
3771         case IDM_WINDOW_BIZ_7:
3772         {
3773                 i = wCmd - IDM_WINDOW_BIZ_0;
3774
3775                 if ((i < 0) || (i >= MAX_TERM_DATA)) break;
3776
3777                 td = &data[i];
3778
3779                 td->bizarre = !td->bizarre;
3780
3781                 term_getsize(td);
3782
3783                 term_window_resize(td);
3784
3785                 break;
3786         }
3787
3788         /* Increase Tile Width */
3789         case IDM_WINDOW_I_WID_0:
3790         case IDM_WINDOW_I_WID_1:
3791         case IDM_WINDOW_I_WID_2:
3792         case IDM_WINDOW_I_WID_3:
3793         case IDM_WINDOW_I_WID_4:
3794         case IDM_WINDOW_I_WID_5:
3795         case IDM_WINDOW_I_WID_6:
3796         case IDM_WINDOW_I_WID_7:
3797         {
3798                 i = wCmd - IDM_WINDOW_I_WID_0;
3799
3800                 if ((i < 0) || (i >= MAX_TERM_DATA)) break;
3801
3802                 td = &data[i];
3803
3804                 td->tile_wid += 1;
3805
3806                 term_getsize(td);
3807
3808                 term_window_resize(td);
3809
3810                 break;
3811         }
3812
3813         /* Decrease Tile Height */
3814         case IDM_WINDOW_D_WID_0:
3815         case IDM_WINDOW_D_WID_1:
3816         case IDM_WINDOW_D_WID_2:
3817         case IDM_WINDOW_D_WID_3:
3818         case IDM_WINDOW_D_WID_4:
3819         case IDM_WINDOW_D_WID_5:
3820         case IDM_WINDOW_D_WID_6:
3821         case IDM_WINDOW_D_WID_7:
3822         {
3823                 i = wCmd - IDM_WINDOW_D_WID_0;
3824
3825                 if ((i < 0) || (i >= MAX_TERM_DATA)) break;
3826
3827                 td = &data[i];
3828
3829                 td->tile_wid -= 1;
3830
3831                 term_getsize(td);
3832
3833                 term_window_resize(td);
3834
3835                 break;
3836         }
3837
3838         /* Increase Tile Height */
3839         case IDM_WINDOW_I_HGT_0:
3840         case IDM_WINDOW_I_HGT_1:
3841         case IDM_WINDOW_I_HGT_2:
3842         case IDM_WINDOW_I_HGT_3:
3843         case IDM_WINDOW_I_HGT_4:
3844         case IDM_WINDOW_I_HGT_5:
3845         case IDM_WINDOW_I_HGT_6:
3846         case IDM_WINDOW_I_HGT_7:
3847         {
3848                 i = wCmd - IDM_WINDOW_I_HGT_0;
3849
3850                 if ((i < 0) || (i >= MAX_TERM_DATA)) break;
3851
3852                 td = &data[i];
3853
3854                 td->tile_hgt += 1;
3855
3856                 term_getsize(td);
3857
3858                 term_window_resize(td);
3859
3860                 break;
3861         }
3862
3863         /* Decrease Tile Height */
3864         case IDM_WINDOW_D_HGT_0:
3865         case IDM_WINDOW_D_HGT_1:
3866         case IDM_WINDOW_D_HGT_2:
3867         case IDM_WINDOW_D_HGT_3:
3868         case IDM_WINDOW_D_HGT_4:
3869         case IDM_WINDOW_D_HGT_5:
3870         case IDM_WINDOW_D_HGT_6:
3871         case IDM_WINDOW_D_HGT_7:
3872         {
3873                 i = wCmd - IDM_WINDOW_D_HGT_0;
3874
3875                 if ((i < 0) || (i >= MAX_TERM_DATA)) break;
3876
3877                 td = &data[i];
3878
3879                 td->tile_hgt -= 1;
3880
3881                 term_getsize(td);
3882
3883                 term_window_resize(td);
3884
3885                 break;
3886         }
3887
3888         case IDM_OPTIONS_NO_GRAPHICS:
3889         {
3890                 if (!inkey_flag)
3891                 {
3892                         plog("You may not do that right now.");
3893                         break;
3894                 }
3895
3896                 if (arg_graphics != GRAPHICS_NONE)
3897                 {
3898                         arg_graphics = GRAPHICS_NONE;
3899                         Term_xtra_win_react();
3900                         Term_key_push(KTRL('R'));
3901                 }
3902
3903                 break;
3904         }
3905
3906         case IDM_OPTIONS_OLD_GRAPHICS:
3907         {
3908                 if (!inkey_flag)
3909                 {
3910                         plog("You may not do that right now.");
3911                         break;
3912                 }
3913
3914                 if (arg_graphics != GRAPHICS_ORIGINAL)
3915                 {
3916                         arg_graphics = GRAPHICS_ORIGINAL;
3917                         Term_xtra_win_react();
3918                         Term_key_push(KTRL('R'));
3919                 }
3920
3921                 break;
3922         }
3923
3924         case IDM_OPTIONS_NEW_GRAPHICS:
3925         {
3926                 if (!inkey_flag)
3927                 {
3928                         plog("You may not do that right now.");
3929                         break;
3930                 }
3931
3932                 if (arg_graphics != GRAPHICS_ADAM_BOLT)
3933                 {
3934                         arg_graphics = GRAPHICS_ADAM_BOLT;
3935                         Term_xtra_win_react();
3936                         Term_key_push(KTRL('R'));
3937                 }
3938
3939                 break;
3940         }
3941
3942         case IDM_OPTIONS_NEW2_GRAPHICS:
3943         {
3944                 if (!inkey_flag)
3945                 {
3946                         plog("You may not do that right now.");
3947                         break;
3948                 }
3949
3950                 if (arg_graphics != GRAPHICS_HENGBAND)
3951                 {
3952                         arg_graphics = GRAPHICS_HENGBAND;
3953                         Term_xtra_win_react();
3954                         Term_key_push(KTRL('R'));
3955                 }
3956
3957                 break;
3958         }
3959
3960         case IDM_OPTIONS_BIGTILE:
3961         {
3962                 td = &data[0];
3963                 if (!inkey_flag)
3964                 {
3965                         plog("You may not do that right now.");
3966                         break;
3967                 }
3968
3969                 arg_bigtile = !arg_bigtile;
3970                 Term_activate(&td->t);
3971                 Term_resize(td->cols, td->rows);
3972                 InvalidateRect(td->w, NULL, TRUE);
3973                 break;
3974         }
3975
3976         case IDM_OPTIONS_MUSIC:
3977         {
3978                 if (!inkey_flag)
3979                 {
3980                         plog("You may not do that right now.");
3981                         break;
3982                 }
3983
3984                 arg_music = !arg_music;
3985                 Term_xtra_win_react();
3986                 Term_key_push(KTRL('R'));
3987                 break;
3988         }
3989
3990         case IDM_OPTIONS_SOUND:
3991         {
3992                 if (!inkey_flag)
3993                 {
3994                         plog("You may not do that right now.");
3995                         break;
3996                 }
3997
3998                 arg_sound = !arg_sound;
3999                 Term_xtra_win_react();
4000                 Term_key_push(KTRL('R'));
4001                 break;
4002         }
4003
4004         /* bg */
4005         case IDM_OPTIONS_BG:
4006         {
4007                 if (!inkey_flag)
4008                 {
4009                         plog("You may not do that right now.");
4010                         break;
4011                 }
4012
4013                 use_bg = !use_bg;
4014                 init_bg();
4015                 Term_xtra_win_react();
4016                 Term_key_push(KTRL('R'));
4017                 break;
4018         }
4019
4020         /* bg */
4021         case IDM_OPTIONS_OPEN_BG:
4022         {
4023                 if (!inkey_flag)
4024                 {
4025                         plog("You may not do that right now.");
4026                         break;
4027                 }
4028                 else
4029                 {
4030                         memset(&ofn, 0, sizeof(ofn));
4031                         ofn.lStructSize = sizeof(ofn);
4032                         ofn.hwndOwner = data[0].w;
4033                         ofn.lpstrFilter = "Bitmap Files (*.bmp)\0*.bmp\0";
4034                         ofn.nFilterIndex = 1;
4035                         ofn.lpstrFile = bg_bitmap_file;
4036                         ofn.nMaxFile = 1023;
4037                         ofn.lpstrInitialDir = NULL;
4038                         ofn.lpstrTitle = _("壁紙を選んでね。", "Choose wall paper.");
4039                         ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
4040
4041                         if (GetOpenFileName(&ofn))
4042                         {
4043                                 /* Load 'savefile' */
4044                                 use_bg = 1;
4045                                 init_bg();
4046                         }
4047
4048                         /* React to changes */
4049                         Term_xtra_win_react();
4050
4051                         /* Hack -- Force redraw */
4052                         Term_key_push(KTRL('R'));
4053                 }
4054                 break;
4055         }
4056
4057         case IDM_DUMP_SCREEN_HTML:
4058         {
4059                 static char buf[1024] = "";
4060                 memset(&ofn, 0, sizeof(ofn));
4061                 ofn.lStructSize = sizeof(ofn);
4062                 ofn.hwndOwner = data[0].w;
4063                 ofn.lpstrFilter = "HTML Files (*.html)\0*.html\0";
4064                 ofn.nFilterIndex = 1;
4065                 ofn.lpstrFile = buf;
4066                 ofn.nMaxFile = 1023;
4067                 ofn.lpstrDefExt = "html";
4068                 ofn.lpstrInitialDir = NULL;
4069                 ofn.lpstrTitle = _("HTMLでスクリーンダンプを保存", "Save screen dump as HTML.");
4070                 ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
4071
4072                 if (GetSaveFileName(&ofn))
4073                 {
4074                         do_cmd_save_screen_html_aux(buf, 0);
4075                 }
4076                 break;
4077         }
4078
4079 #ifdef USE_SAVER
4080
4081         case IDM_OPTIONS_SAVER:
4082         {
4083                 if (hwndSaver)
4084                 {
4085                         DestroyWindow(hwndSaver);
4086                         hwndSaver = NULL;
4087                 }
4088                 else
4089                 {
4090                         /* Create a screen scaver window */
4091                         hwndSaver = CreateWindowEx(WS_EX_TOPMOST, "WindowsScreenSaverClass",
4092                                 "Angband Screensaver",
4093                                 WS_POPUP | WS_MAXIMIZE | WS_VISIBLE,
4094                                 0, 0, GetSystemMetrics(SM_CXSCREEN),
4095                                 GetSystemMetrics(SM_CYSCREEN),
4096                                 NULL, NULL, hInstance, NULL);
4097
4098                         if (hwndSaver)
4099                         {
4100                                 /* Push the window to the bottom */
4101                                 SetWindowPos(hwndSaver, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
4102                         }
4103                         else
4104                         {
4105                                 plog(_("ウィンドウを作成出来ません", "Failed to create saver window"));
4106                         }
4107                 }
4108                 break;
4109         }
4110
4111 #endif
4112
4113         case IDM_OPTIONS_MAP:
4114         {
4115                 windows_map();
4116                 break;
4117         }
4118
4119         case IDM_HELP_CONTENTS:
4120         {
4121 #ifdef HTML_HELP
4122                 char tmp[1024];
4123                 path_build(tmp, sizeof(tmp), ANGBAND_DIR_XTRA_HELP, "zangband.chm");
4124                 if (check_file(tmp))
4125                 {
4126                         HtmlHelp(data[0].w, tmp, HH_DISPLAY_TOPIC, 0);
4127                 }
4128                 else
4129                 {
4130                         plog_fmt(_("ヘルプファイル[%s]が見付かりません。", "Cannot find help file: %s"), tmp);
4131                         plog(_("代わりにオンラインヘルプを使用してください。", "Use the online help files instead."));
4132                 }
4133                 break;
4134 #else /* HTML_HELP */
4135                 char buf[1024];
4136                 char tmp[1024];
4137                 path_build(tmp, sizeof(tmp), ANGBAND_DIR_XTRA_HELP, "zangband.hlp");
4138                 if (check_file(tmp))
4139                 {
4140                         sprintf(buf, "winhelp.exe %s", tmp);
4141                         WinExec(buf, SW_NORMAL);
4142                 }
4143                 else
4144                 {
4145                         plog_fmt(_("ヘルプファイル[%s]が見付かりません。", "Cannot find help file: %s"), tmp);
4146                         plog(_("代わりにオンラインヘルプを使用してください。", "Use the online help files instead."));
4147
4148                 }
4149                 break;
4150 #endif /* HTML_HELP */
4151         }
4152         }
4153 }
4154
4155
4156 static bool process_keydown(WPARAM wParam, LPARAM lParam)
4157 {
4158         int i;
4159         bool mc = FALSE;
4160         bool ms = FALSE;
4161         bool ma = FALSE;
4162
4163         /* Extract the modifiers */
4164         if (GetKeyState(VK_CONTROL) & 0x8000) mc = TRUE;
4165         if (GetKeyState(VK_SHIFT) & 0x8000) ms = TRUE;
4166         if (GetKeyState(VK_MENU) & 0x8000) ma = TRUE;
4167
4168         Term_no_press = (ma) ? TRUE : FALSE;
4169
4170         /* Handle "special" keys */
4171         if (special_key[(byte)(wParam)] || (ma && !ignore_key[(byte)(wParam)]))
4172         {
4173                 bool ext_key = (lParam & 0x1000000L) ? TRUE : FALSE;
4174                 bool numpad = FALSE;
4175
4176                 /* Begin the macro trigger */
4177                 Term_keypress(31);
4178
4179                 /* Send the modifiers */
4180                 if (mc) Term_keypress('C');
4181                 if (ms) Term_keypress('S');
4182                 if (ma) Term_keypress('A');
4183
4184                 /* Extract "scan code" */
4185                 i = LOBYTE(HIWORD(lParam));
4186
4187                 /* Introduce the scan code */
4188                 Term_keypress('x');
4189
4190                 /* Extended key bit */
4191                 switch (wParam)
4192                 {
4193                         /* Numpad Enter and '/' are extended key */
4194                 case VK_DIVIDE:
4195                         Term_no_press = TRUE;
4196                 case VK_RETURN: /* Enter */
4197                         numpad = ext_key;
4198                         break;
4199                         /* Other extended keys are on full keyboard */
4200                 case VK_NUMPAD0:
4201                 case VK_NUMPAD1:
4202                 case VK_NUMPAD2:
4203                 case VK_NUMPAD3:
4204                 case VK_NUMPAD4:
4205                 case VK_NUMPAD5:
4206                 case VK_NUMPAD6:
4207                 case VK_NUMPAD7:
4208                 case VK_NUMPAD8:
4209                 case VK_NUMPAD9:
4210                 case VK_ADD:
4211                 case VK_MULTIPLY:
4212                 case VK_SUBTRACT:
4213                 case VK_SEPARATOR:
4214                 case VK_DECIMAL:
4215                         Term_no_press = TRUE;
4216                 case VK_CLEAR:
4217                 case VK_HOME:
4218                 case VK_END:
4219                 case VK_PRIOR:  /* Page Up */
4220                 case VK_NEXT:   /* Page Down */
4221                 case VK_INSERT:
4222                 case VK_DELETE:
4223                 case VK_UP:
4224                 case VK_DOWN:
4225                 case VK_LEFT:
4226                 case VK_RIGHT:
4227                         numpad = !ext_key;
4228                 }
4229
4230                 /* Special modifiers for keypad keys */
4231                 if (numpad) Term_keypress('K');
4232
4233                 /* Encode the hexidecimal scan code */
4234                 Term_keypress(hexsym[i / 16]);
4235                 Term_keypress(hexsym[i % 16]);
4236
4237                 /* End the macro trigger */
4238                 Term_keypress(13);
4239
4240                 return 1;
4241         }
4242
4243         return 0;
4244 }
4245
4246
4247 #ifdef __MWERKS__
4248 LRESULT FAR PASCAL AngbandWndProc(HWND hWnd, UINT uMsg,
4249         WPARAM wParam, LPARAM lParam);
4250 LRESULT FAR PASCAL AngbandWndProc(HWND hWnd, UINT uMsg,
4251         WPARAM wParam, LPARAM lParam)
4252 #else /* __MWERKS__ */
4253 LRESULT FAR PASCAL AngbandWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
4254 #endif /* __MWERKS__ */
4255 {
4256         PAINTSTRUCT ps;
4257         HDC hdc;
4258         term_data *td;
4259         int i;
4260
4261
4262         /* Acquire proper "term_data" info */
4263         td = (term_data *)GetWindowLong(hWnd, 0);
4264
4265         /* Handle message */
4266         switch (uMsg)
4267         {
4268         case WM_NCCREATE:
4269         {
4270                 SetWindowLong(hWnd, 0, (LONG)(my_td));
4271                 break;
4272         }
4273
4274         case WM_CREATE:
4275         {
4276 #ifdef USE_MUSIC
4277                 mop.dwCallback = (DWORD)hWnd;
4278 #endif
4279                 return 0;
4280         }
4281
4282         case WM_GETMINMAXINFO:
4283         {
4284                 MINMAXINFO FAR *lpmmi;
4285                 RECT rc;
4286
4287                 lpmmi = (MINMAXINFO FAR *)lParam;
4288
4289                 /* this message was sent before WM_NCCREATE */
4290                 if (!td) return 1;
4291
4292                 /* Minimum window size is 80x24 */
4293                 rc.left = rc.top = 0;
4294                 rc.right = rc.left + 80 * td->tile_wid + td->size_ow1 + td->size_ow2;
4295                 rc.bottom = rc.top + 24 * td->tile_hgt + td->size_oh1 + td->size_oh2 + 1;
4296
4297                 /* Adjust */
4298                 AdjustWindowRectEx(&rc, td->dwStyle, TRUE, td->dwExStyle);
4299
4300                 /* Save minimum size */
4301                 lpmmi->ptMinTrackSize.x = rc.right - rc.left;
4302                 lpmmi->ptMinTrackSize.y = rc.bottom - rc.top;
4303
4304                 return 0;
4305         }
4306
4307         case WM_PAINT:
4308         {
4309                 BeginPaint(hWnd, &ps);
4310                 if (td) term_data_redraw(td);
4311                 EndPaint(hWnd, &ps);
4312                 ValidateRect(hWnd, NULL);
4313                 return 0;
4314         }
4315
4316 #ifdef USE_MUSIC
4317         case MM_MCINOTIFY:
4318         {
4319                 if (wParam == MCI_NOTIFY_SUCCESSFUL)
4320                 {
4321                         mciSendCommand(mop.wDeviceID, MCI_SEEK, MCI_SEEK_TO_START, 0);
4322                         mciSendCommand(mop.wDeviceID, MCI_PLAY, MCI_NOTIFY, (DWORD)&mop);
4323                 }
4324                 return 0;
4325         }
4326 #endif
4327
4328         case WM_SYSKEYDOWN:
4329         case WM_KEYDOWN:
4330         {
4331                 if (process_keydown(wParam, lParam))
4332                         return 0;
4333                 break;
4334         }
4335
4336         case WM_CHAR:
4337         {
4338                 if (Term_no_press) Term_no_press = FALSE;
4339                 else Term_keypress(wParam);
4340                 return 0;
4341         }
4342
4343         case WM_LBUTTONDOWN:
4344         {
4345                 mousex = MIN(LOWORD(lParam) / td->tile_wid, td->cols - 1);
4346                 mousey = MIN(HIWORD(lParam) / td->tile_hgt, td->rows - 1);
4347                 mouse_down = TRUE;
4348                 oldx = mousex;
4349                 oldy = mousey;
4350                 return 0;
4351         }
4352
4353         case WM_LBUTTONUP:
4354         {
4355                 HGLOBAL hGlobal;
4356                 LPSTR lpStr;
4357                 int j, sz;
4358                 TERM_LEN dx = abs(oldx - mousex) + 1;
4359                 TERM_LEN dy = abs(oldy - mousey) + 1;
4360                 TERM_LEN ox = (oldx > mousex) ? mousex : oldx;
4361                 TERM_LEN oy = (oldy > mousey) ? mousey : oldy;
4362
4363                 mouse_down = FALSE;
4364                 paint_rect = FALSE;
4365
4366 #ifdef JP
4367                 sz = (dx + 3) * dy;
4368 #else
4369                 sz = (dx + 2) * dy;
4370 #endif
4371                 hGlobal = GlobalAlloc(GHND, sz + 1);
4372                 if (hGlobal == NULL) return 0;
4373                 lpStr = (LPSTR)GlobalLock(hGlobal);
4374
4375                 for (i = 0; i < dy; i++)
4376                 {
4377 #ifdef JP
4378                         char *s;
4379                         char **scr = data[0].t.scr->c;
4380
4381                         C_MAKE(s, (dx + 1), char);
4382                         strncpy(s, &scr[oy + i][ox], dx);
4383
4384                         if (ox > 0)
4385                         {
4386                                 if (iskanji(scr[oy + i][ox - 1])) s[0] = ' ';
4387                         }
4388
4389                         if (ox + dx < data[0].cols)
4390                         {
4391                                 if (iskanji(scr[oy + i][ox + dx - 1])) s[dx - 1] = ' ';
4392                         }
4393
4394                         for (j = 0; j < dx; j++)
4395                         {
4396                                 if (s[j] == 127) s[j] = '#';
4397                                 *lpStr++ = s[j];
4398                         }
4399 #else
4400                         for (j = 0; j < dx; j++)
4401                         {
4402                                 *lpStr++ = data[0].t.scr->c[oy + i][ox + j];
4403                         }
4404 #endif
4405                         if (dy > 1)
4406                         {
4407                                 *lpStr++ = '\r';
4408                                 *lpStr++ = '\n';
4409                         }
4410                 }
4411
4412                 GlobalUnlock(hGlobal);
4413                 if (OpenClipboard(hWnd) == 0)
4414                 {
4415                         GlobalFree(hGlobal);
4416                         return 0;
4417                 }
4418                 EmptyClipboard();
4419                 SetClipboardData(CF_TEXT, hGlobal);
4420                 CloseClipboard();
4421
4422                 Term_redraw();
4423
4424                 return 0;
4425         }
4426
4427         case WM_MOUSEMOVE:
4428         {
4429                 if (mouse_down)
4430                 {
4431                         int dx, dy;
4432                         int cx = MIN(LOWORD(lParam) / td->tile_wid, td->cols - 1);
4433                         int cy = MIN(HIWORD(lParam) / td->tile_hgt, td->rows - 1);
4434                         int ox, oy;
4435
4436                         if (paint_rect)
4437                         {
4438                                 dx = abs(oldx - mousex) + 1;
4439                                 dy = abs(oldy - mousey) + 1;
4440                                 ox = (oldx > mousex) ? mousex : oldx;
4441                                 oy = (oldy > mousey) ? mousey : oldy;
4442                                 Term_inversed_area(hWnd, ox, oy, dx, dy);
4443                         }
4444                         else
4445                         {
4446                                 paint_rect = TRUE;
4447                         }
4448
4449                         dx = abs(cx - mousex) + 1;
4450                         dy = abs(cy - mousey) + 1;
4451                         ox = (cx > mousex) ? mousex : cx;
4452                         oy = (cy > mousey) ? mousey : cy;
4453                         Term_inversed_area(hWnd, ox, oy, dx, dy);
4454
4455                         oldx = cx;
4456                         oldy = cy;
4457                 }
4458                 return 0;
4459         }
4460
4461         case WM_INITMENU:
4462         {
4463                 setup_menus();
4464                 return 0;
4465         }
4466
4467         case WM_CLOSE:
4468         {
4469                 if (game_in_progress && current_world_ptr->character_generated)
4470                 {
4471                         if (!can_save)
4472                         {
4473                                 plog(_("今は終了できません。", "You may not do that right now."));
4474                                 return 0;
4475                         }
4476
4477                         /* Hack -- Forget messages */
4478                         msg_flag = FALSE;
4479
4480                         forget_lite(p_ptr->current_floor_ptr);
4481                         forget_view(p_ptr->current_floor_ptr);
4482                         clear_mon_lite(p_ptr->current_floor_ptr);
4483
4484                         /* Save the game */
4485 #ifdef ZANGBAND
4486                                 /* do_cmd_save_game(FALSE); */
4487 #else /* ZANGBAND */
4488                                 /* do_cmd_save_game(); */
4489 #endif /* ZANGBAND */
4490                         Term_key_push(SPECIAL_KEY_QUIT);
4491                         return 0;
4492                 }
4493                 quit(NULL);
4494                 return 0;
4495         }
4496
4497         case WM_QUERYENDSESSION:
4498         {
4499                 if (game_in_progress && current_world_ptr->character_generated)
4500                 {
4501                         /* Hack -- Forget messages */
4502                         msg_flag = FALSE;
4503
4504                         /* Mega-Hack -- Delay death */
4505                         if (p_ptr->chp < 0) p_ptr->is_dead = FALSE;
4506                         exe_write_diary(p_ptr, DIARY_GAMESTART, 0, _("----ゲーム中断----", "---- Save and Exit Game ----"));
4507
4508                         /* Hardcode panic save */
4509                         p_ptr->panic_save = 1;
4510
4511                         /* Forbid suspend */
4512                         signals_ignore_tstp();
4513
4514                         /* Indicate panic save */
4515                         (void)strcpy(p_ptr->died_from, _("(緊急セーブ)", "(panic save)"));
4516
4517                         /* Panic save */
4518                         (void)save_player(p_ptr);
4519                 }
4520                 quit(NULL);
4521                 return 0;
4522         }
4523
4524         case WM_QUIT:
4525         {
4526                 quit(NULL);
4527                 return 0;
4528         }
4529
4530         case WM_COMMAND:
4531         {
4532                 process_menus(LOWORD(wParam));
4533                 return 0;
4534         }
4535
4536         case WM_SIZE:
4537         {
4538                 /* this message was sent before WM_NCCREATE */
4539                 if (!td) return 1;
4540
4541                 /* it was sent from inside CreateWindowEx */
4542                 if (!td->w) return 1;
4543
4544                 /* was sent from WM_SIZE */
4545                 if (td->size_hack) return 1;
4546
4547                 switch (wParam)
4548                 {
4549                 case SIZE_MINIMIZED:
4550                 {
4551                         /* Hide sub-windows */
4552                         for (i = 1; i < MAX_TERM_DATA; i++)
4553                         {
4554                                 if (data[i].visible) ShowWindow(data[i].w, SW_HIDE);
4555                         }
4556                         return 0;
4557                 }
4558
4559                 case SIZE_MAXIMIZED:
4560                 {
4561                         /* fall through */
4562                 }
4563
4564                 case SIZE_RESTORED:
4565                 {
4566                         TERM_LEN cols = (LOWORD(lParam) - td->size_ow1) / td->tile_wid;
4567                         TERM_LEN rows = (HIWORD(lParam) - td->size_oh1) / td->tile_hgt;
4568
4569                         /* New size */
4570                         if ((td->cols != cols) || (td->rows != rows))
4571                         {
4572                                 /* Save the new size */
4573                                 td->cols = cols;
4574                                 td->rows = rows;
4575
4576                                 if (!IsZoomed(td->w) && !IsIconic(td->w))
4577                                 {
4578                                         normsize.x = td->cols;
4579                                         normsize.y = td->rows;
4580                                 }
4581
4582                                 /* Activate */
4583                                 Term_activate(&td->t);
4584
4585                                 /* Resize the term */
4586                                 Term_resize(td->cols, td->rows);
4587
4588                                 /* Redraw later */
4589                                 InvalidateRect(td->w, NULL, TRUE);
4590                         }
4591
4592                         td->size_hack = TRUE;
4593
4594                         /* Show sub-windows */
4595                         for (i = 1; i < MAX_TERM_DATA; i++)
4596                         {
4597                                 if (data[i].visible) ShowWindow(data[i].w, SW_SHOW);
4598                         }
4599
4600                         td->size_hack = FALSE;
4601
4602                         return 0;
4603                 }
4604                 }
4605                 break;
4606         }
4607
4608         case WM_PALETTECHANGED:
4609         {
4610                 /* Ignore if palette change caused by itself */
4611                 if ((HWND)wParam == hWnd) return 0;
4612
4613                 /* Fall through... */
4614         }
4615
4616         case WM_QUERYNEWPALETTE:
4617         {
4618                 if (!paletted) return 0;
4619
4620                 hdc = GetDC(hWnd);
4621
4622                 SelectPalette(hdc, hPal, FALSE);
4623
4624                 i = RealizePalette(hdc);
4625
4626                 /* if any palette entries changed, repaint the window. */
4627                 if (i) InvalidateRect(hWnd, NULL, TRUE);
4628
4629                 ReleaseDC(hWnd, hdc);
4630
4631                 return 0;
4632         }
4633
4634         case WM_ACTIVATE:
4635         {
4636                 if (wParam && !HIWORD(lParam))
4637                 {
4638                         /* Do something to sub-windows */
4639                         for (i = 1; i < MAX_TERM_DATA; i++)
4640                         {
4641                                 if (!data[i].posfix) term_window_pos(&data[i], hWnd);
4642                         }
4643
4644                         /* Focus on main window */
4645                         SetFocus(hWnd);
4646
4647                         return 0;
4648                 }
4649
4650                 break;
4651         }
4652
4653         case WM_ACTIVATEAPP:
4654         {
4655                 if (IsIconic(td->w)) break;
4656
4657                 for (i = 1; i < MAX_TERM_DATA; i++)
4658                 {
4659                         if (data[i].visible)
4660                         {
4661                                 if (wParam == TRUE)
4662                                 {
4663                                         ShowWindow(data[i].w, SW_SHOW);
4664                                 }
4665                                 else
4666                                 {
4667                                         ShowWindow(data[i].w, SW_HIDE);
4668                                 }
4669                         }
4670                 }
4671         }
4672         }
4673
4674         return DefWindowProc(hWnd, uMsg, wParam, lParam);
4675 }
4676
4677
4678 #ifdef __MWERKS__
4679 LRESULT FAR PASCAL AngbandListProc(HWND hWnd, UINT uMsg,
4680         WPARAM wParam, LPARAM lParam);
4681 LRESULT FAR PASCAL AngbandListProc(HWND hWnd, UINT uMsg,
4682         WPARAM wParam, LPARAM lParam)
4683 #else /* __MWERKS__ */
4684 LRESULT FAR PASCAL AngbandListProc(HWND hWnd, UINT uMsg,
4685         WPARAM wParam, LPARAM lParam)
4686 #endif /* __MWERKS__ */
4687 {
4688         term_data *td;
4689         PAINTSTRUCT ps;
4690         HDC hdc;
4691         int i;
4692
4693
4694         /* Acquire proper "term_data" info */
4695         td = (term_data *)GetWindowLong(hWnd, 0);
4696
4697         /* Process message */
4698         switch (uMsg)
4699         {
4700         case WM_NCCREATE:
4701         {
4702                 SetWindowLong(hWnd, 0, (LONG)(my_td));
4703                 break;
4704         }
4705
4706         case WM_CREATE:
4707         {
4708                 return 0;
4709         }
4710
4711         case WM_GETMINMAXINFO:
4712         {
4713                 MINMAXINFO FAR *lpmmi;
4714                 RECT rc;
4715
4716                 lpmmi = (MINMAXINFO FAR *)lParam;
4717
4718                 /* this message was sent before WM_NCCREATE */
4719                 if (!td) return 1;
4720
4721                 /* Minimum window size is 80x24 */
4722                 rc.left = rc.top = 0;
4723                 rc.right = rc.left + 20 * td->tile_wid + td->size_ow1 + td->size_ow2;
4724                 rc.bottom = rc.top + 3 * td->tile_hgt + td->size_oh1 + td->size_oh2 + 1;
4725
4726                 /* Adjust */
4727                 AdjustWindowRectEx(&rc, td->dwStyle, TRUE, td->dwExStyle);
4728
4729                 /* Save minimum size */
4730                 lpmmi->ptMinTrackSize.x = rc.right - rc.left;
4731                 lpmmi->ptMinTrackSize.y = rc.bottom - rc.top;
4732
4733                 return 0;
4734         }
4735
4736         case WM_SIZE:
4737         {
4738                 TERM_LEN cols;
4739                 TERM_LEN rows;
4740
4741                 /* this message was sent before WM_NCCREATE */
4742                 if (!td) return 1;
4743
4744                 /* it was sent from inside CreateWindowEx */
4745                 if (!td->w) return 1;
4746
4747                 /* was sent from inside WM_SIZE */
4748                 if (td->size_hack) return 1;
4749
4750                 td->size_hack = TRUE;
4751
4752                 cols = (LOWORD(lParam) - td->size_ow1) / td->tile_wid;
4753                 rows = (HIWORD(lParam) - td->size_oh1) / td->tile_hgt;
4754
4755                 /* New size */
4756                 if ((td->cols != cols) || (td->rows != rows))
4757                 {
4758                         /* Save old term */
4759                         term *old_term = Term;
4760
4761                         /* Save the new size */
4762                         td->cols = cols;
4763                         td->rows = rows;
4764
4765                         /* Activate */
4766                         Term_activate(&td->t);
4767
4768                         /* Resize the term */
4769                         Term_resize(td->cols, td->rows);
4770
4771                         /* Activate */
4772                         Term_activate(old_term);
4773
4774                         /* Redraw later */
4775                         InvalidateRect(td->w, NULL, TRUE);
4776
4777                         /* HACK - Redraw all windows */
4778                         p_ptr->window = 0xFFFFFFFF;
4779                         handle_stuff(p_ptr);
4780                 }
4781
4782                 td->size_hack = FALSE;
4783
4784                 return 0;
4785         }
4786
4787         case WM_PAINT:
4788         {
4789                 BeginPaint(hWnd, &ps);
4790                 if (td) term_data_redraw(td);
4791                 EndPaint(hWnd, &ps);
4792                 return 0;
4793         }
4794
4795         case WM_SYSKEYDOWN:
4796         case WM_KEYDOWN:
4797         {
4798                 if (process_keydown(wParam, lParam))
4799                         return 0;
4800                 break;
4801         }
4802
4803         case WM_CHAR:
4804         {
4805                 if (Term_no_press) Term_no_press = FALSE;
4806                 else Term_keypress(wParam);
4807                 return 0;
4808         }
4809
4810         case WM_PALETTECHANGED:
4811         {
4812                 /* ignore if palette change caused by itself */
4813                 if ((HWND)wParam == hWnd) return FALSE;
4814                 /* otherwise, fall through!!! */
4815         }
4816
4817         case WM_QUERYNEWPALETTE:
4818         {
4819                 if (!paletted) return 0;
4820                 hdc = GetDC(hWnd);
4821                 SelectPalette(hdc, hPal, FALSE);
4822                 i = RealizePalette(hdc);
4823                 /* if any palette entries changed, repaint the window. */
4824                 if (i) InvalidateRect(hWnd, NULL, TRUE);
4825                 ReleaseDC(hWnd, hdc);
4826                 return 0;
4827         }
4828
4829         case WM_NCLBUTTONDOWN:
4830         {
4831
4832 #ifdef HTCLOSE
4833                 if (wParam == HTCLOSE) wParam = HTSYSMENU;
4834 #endif /* HTCLOSE */
4835
4836                 if (wParam == HTSYSMENU)
4837                 {
4838                         if (td->visible)
4839                         {
4840                                 td->visible = FALSE;
4841                                 ShowWindow(td->w, SW_HIDE);
4842                         }
4843
4844                         return 0;
4845                 }
4846
4847                 break;
4848         }
4849         }
4850
4851         return DefWindowProc(hWnd, uMsg, wParam, lParam);
4852 }
4853
4854
4855 #ifdef USE_SAVER
4856
4857 #define MOUSE_SENS 40
4858
4859 #ifdef __MWERKS__
4860 LRESULT FAR PASCAL AngbandSaverProc(HWND hWnd, UINT uMsg,
4861         WPARAM wParam, LPARAM lParam);
4862 LRESULT FAR PASCAL AngbandSaverProc(HWND hWnd, UINT uMsg,
4863         WPARAM wParam, LPARAM lParam)
4864 #else /* __MWERKS__ */
4865 LRESULT FAR PASCAL AngbandSaverProc(HWND hWnd, UINT uMsg,
4866         WPARAM wParam, LPARAM lParam)
4867 #endif /* __MWERKS__ */
4868 {
4869         static int iMouse = 0;
4870         static WORD xMouse = 0;
4871         static WORD yMouse = 0;
4872
4873         int dx, dy;
4874
4875
4876         /* Process */
4877         switch (uMsg)
4878         {
4879         case WM_NCCREATE:
4880         {
4881                 break;
4882         }
4883
4884         case WM_SETCURSOR:
4885         {
4886                 SetCursor(NULL);
4887                 return 0;
4888         }
4889
4890         case WM_LBUTTONDOWN:
4891         case WM_MBUTTONDOWN:
4892         case WM_RBUTTONDOWN:
4893         case WM_KEYDOWN:
4894         {
4895                 SendMessage(hWnd, WM_CLOSE, 0, 0);
4896                 return 0;
4897         }
4898
4899         case WM_MOUSEMOVE:
4900         {
4901                 if (iMouse)
4902                 {
4903                         dx = LOWORD(lParam) - xMouse;
4904                         dy = HIWORD(lParam) - yMouse;
4905
4906                         if (dx < 0) dx = -dx;
4907                         if (dy < 0) dy = -dy;
4908
4909                         if ((dx > MOUSE_SENS) || (dy > MOUSE_SENS))
4910                         {
4911                                 SendMessage(hWnd, WM_CLOSE, 0, 0);
4912                         }
4913                 }
4914
4915                 /* Save last location */
4916                 iMouse = 1;
4917                 xMouse = LOWORD(lParam);
4918                 yMouse = HIWORD(lParam);
4919
4920                 return 0;
4921         }
4922
4923         case WM_CLOSE:
4924         {
4925                 DestroyWindow(hwndSaver);
4926                 hwndSaver = NULL;
4927                 return 0;
4928         }
4929         }
4930
4931         return DefWindowProc(hWnd, uMsg, wParam, lParam);
4932 }
4933
4934 #endif /* USE_SAVER */
4935
4936
4937
4938
4939
4940 /*** Temporary Hooks ***/
4941
4942
4943 /*
4944  * Display warning message (see "z-util.c")
4945  */
4946 static void hack_plog(concptr str)
4947 {
4948         /* Give a warning */
4949         if (str)
4950         {
4951 #ifdef JP
4952                 MessageBox(NULL, str, "警告!",
4953                         MB_ICONEXCLAMATION | MB_OK);
4954 #else
4955                 MessageBox(NULL, str, "Warning",
4956                         MB_ICONEXCLAMATION | MB_OK);
4957 #endif
4958
4959         }
4960 }
4961
4962
4963 /*
4964  * Display error message and quit (see "z-util.c")
4965  */
4966 static void hack_quit(concptr str)
4967 {
4968         /* Give a warning */
4969         if (str)
4970         {
4971 #ifdef JP
4972                 MessageBox(NULL, str, "エラー!",
4973                         MB_ICONEXCLAMATION | MB_OK | MB_ICONSTOP);
4974 #else
4975                 MessageBox(NULL, str, "Error",
4976                         MB_ICONEXCLAMATION | MB_OK | MB_ICONSTOP);
4977 #endif
4978
4979         }
4980
4981         /* Unregister the classes */
4982         UnregisterClass(AppName, hInstance);
4983
4984         /* Destroy the icon */
4985         if (hIcon) DestroyIcon(hIcon);
4986
4987         exit(0);
4988 }
4989
4990
4991
4992 /*** Various hooks ***/
4993
4994
4995 /*
4996  * Display warning message (see "z-util.c")
4997  */
4998 static void hook_plog(concptr str)
4999 {
5000         /* Warning */
5001         if (str)
5002         {
5003 #ifdef JP
5004                 MessageBox(data[0].w, str, "警告!",
5005                         MB_ICONEXCLAMATION | MB_OK);
5006 #else
5007                 MessageBox(data[0].w, str, "Warning",
5008                         MB_ICONEXCLAMATION | MB_OK);
5009 #endif
5010
5011         }
5012 }
5013
5014
5015 /*
5016  * Display error message and quit (see "z-util.c")
5017  */
5018 static void hook_quit(concptr str)
5019 {
5020         int i;
5021
5022
5023         /* Give a warning */
5024         if (str)
5025         {
5026 #ifdef JP
5027                 MessageBox(data[0].w, str, "エラー!",
5028                         MB_ICONEXCLAMATION | MB_OK | MB_ICONSTOP);
5029 #else
5030                 MessageBox(data[0].w, str, "Error",
5031                         MB_ICONEXCLAMATION | MB_OK | MB_ICONSTOP);
5032 #endif
5033
5034         }
5035
5036
5037         /* Save the preferences */
5038         save_prefs();
5039
5040
5041         /*** Could use 'Term_nuke_win()' */
5042
5043         /* Destroy all windows */
5044         for (i = MAX_TERM_DATA - 1; i >= 0; --i)
5045         {
5046                 term_force_font(&data[i], NULL);
5047                 if (data[i].font_want) string_free(data[i].font_want);
5048                 if (data[i].w) DestroyWindow(data[i].w);
5049                 data[i].w = 0;
5050         }
5051
5052         /* Free the bitmap stuff */
5053 #ifdef USE_GRAPHICS
5054         if (infGraph.hPalette) DeleteObject(infGraph.hPalette);
5055         if (infGraph.hBitmap) DeleteObject(infGraph.hBitmap);
5056
5057         if (infMask.hPalette) DeleteObject(infMask.hPalette);
5058         if (infMask.hBitmap) DeleteObject(infMask.hBitmap);
5059
5060 #endif /* USE_GRAPHICS */
5061
5062         /*** Free some other stuff ***/
5063
5064         DeleteObject(hbrYellow);
5065
5066         /* bg */
5067         delete_bg();
5068
5069         if (hPal) DeleteObject(hPal);
5070
5071         UnregisterClass(AppName, hInstance);
5072
5073         if (hIcon) DestroyIcon(hIcon);
5074
5075         exit(0);
5076 }
5077
5078
5079
5080 /*** Initialize ***/
5081
5082
5083 /*
5084  * Init some stuff
5085  */
5086 static void init_stuff(void)
5087 {
5088         int i;
5089
5090         char path[1024];
5091
5092
5093         /* Get program name with full path */
5094         GetModuleFileName(hInstance, path, 512);
5095
5096         /* Save the "program name" */
5097         argv0 = path;
5098
5099         /* Get the name of the "*.ini" file */
5100         strcpy(path + strlen(path) - 4, ".INI");
5101
5102         /* Save the the name of the ini-file */
5103         ini_file = string_make(path);
5104
5105         /* Analyze the path */
5106         i = strlen(path);
5107
5108         /* Get the path */
5109         for (; i > 0; i--)
5110         {
5111                 if (path[i] == '\\')
5112                 {
5113                         /* End of path */
5114                         break;
5115                 }
5116         }
5117
5118         /* Add "lib" to the path */
5119         strcpy(path + i + 1, "lib\\");
5120
5121         /* Validate the path */
5122         validate_dir(path, TRUE);
5123
5124         /* Init the file paths */
5125         init_file_paths(path);
5126
5127         /* Hack -- Validate the paths */
5128         validate_dir(ANGBAND_DIR_APEX, FALSE);
5129         validate_dir(ANGBAND_DIR_BONE, FALSE);
5130
5131         /* Allow missing 'edit' directory */
5132         if (!check_dir(ANGBAND_DIR_EDIT))
5133         {
5134                 /* Must have 'data'! */
5135                 validate_dir(ANGBAND_DIR_DATA, TRUE);
5136         }
5137         else
5138         {
5139                 /* Don't need 'data' */
5140                 validate_dir(ANGBAND_DIR_DATA, FALSE);
5141         }
5142
5143         validate_dir(ANGBAND_DIR_FILE, TRUE);
5144         validate_dir(ANGBAND_DIR_HELP, FALSE);
5145         validate_dir(ANGBAND_DIR_INFO, FALSE);
5146         validate_dir(ANGBAND_DIR_PREF, TRUE);
5147         validate_dir(ANGBAND_DIR_SAVE, FALSE);
5148         validate_dir(ANGBAND_DIR_USER, TRUE);
5149         validate_dir(ANGBAND_DIR_XTRA, TRUE);
5150         path_build(path, sizeof(path), ANGBAND_DIR_FILE, _("news_j.txt", "news.txt"));
5151
5152         /* Hack -- Validate the "news.txt" file */
5153         validate_file(path);
5154
5155 #ifdef USE_GRAPHICS
5156
5157         /* Build the "graf" path */
5158         path_build(path, sizeof(path), ANGBAND_DIR_XTRA, "graf");
5159
5160         /* Allocate the path */
5161         ANGBAND_DIR_XTRA_GRAF = string_make(path);
5162
5163         /* Validate the "graf" directory */
5164         validate_dir(ANGBAND_DIR_XTRA_GRAF, TRUE);
5165
5166 #endif /* USE_GRAPHICS */
5167
5168
5169 #ifdef USE_SOUND
5170
5171         /* Build the "sound" path */
5172         path_build(path, sizeof(path), ANGBAND_DIR_XTRA, "sound");
5173
5174         /* Allocate the path */
5175         ANGBAND_DIR_XTRA_SOUND = string_make(path);
5176
5177         /* Validate the "sound" directory */
5178         validate_dir(ANGBAND_DIR_XTRA_SOUND, FALSE);
5179
5180 #endif /* USE_SOUND */
5181
5182 #ifdef USE_MUSIC
5183
5184         /* Build the "music" path */
5185         path_build(path, sizeof(path), ANGBAND_DIR_XTRA, "music");
5186
5187         /* Allocate the path */
5188         ANGBAND_DIR_XTRA_MUSIC = string_make(path);
5189
5190         /* Validate the "music" directory */
5191         validate_dir(ANGBAND_DIR_XTRA_MUSIC, FALSE);
5192
5193 #endif /* USE_MUSIC */
5194
5195         /* Build the "help" path */
5196         path_build(path, sizeof(path), ANGBAND_DIR_XTRA, "help");
5197
5198         /* Allocate the path */
5199         ANGBAND_DIR_XTRA_HELP = string_make(path);
5200
5201         /* Validate the "help" directory */
5202         /* validate_dir(ANGBAND_DIR_XTRA_HELP); */
5203 }
5204
5205 /*!
5206  * @brief (Windows固有)変愚蛮怒が起動済かどうかのチェック
5207  */
5208 static bool is_already_running(void)
5209 {
5210         bool result = FALSE;
5211         HANDLE hMutex;
5212
5213         hMutex = CreateMutex(NULL, TRUE, VERSION_NAME);
5214         if (GetLastError() == ERROR_ALREADY_EXISTS)
5215         {
5216                 result = TRUE;
5217         }
5218         return result;
5219 }
5220
5221
5222 /*!
5223  * @brief (Windows固有)Windowsアプリケーションとしてのエントリポイント
5224  */
5225 int FAR PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrevInst,
5226         LPSTR lpCmdLine, int nCmdShow)
5227 {
5228         int i;
5229
5230         WNDCLASS wc;
5231         HDC hdc;
5232         MSG msg;
5233
5234         setlocale(LC_ALL, "ja_JP.utf8");
5235
5236         /* Unused */
5237         (void)nCmdShow;
5238
5239         /* Save globally */
5240         hInstance = hInst;
5241
5242
5243         /* Prevent multiple run */
5244         if (is_already_running())
5245         {
5246                 MessageBox(NULL,
5247                         _("変愚蛮怒はすでに起動しています。", "Hengband is already running."),
5248                         _("エラー!", "Error"),
5249                         MB_ICONEXCLAMATION | MB_OK | MB_ICONSTOP);
5250                 return FALSE;
5251         }
5252
5253         if (hPrevInst == NULL)
5254         {
5255                 wc.style = CS_CLASSDC;
5256                 wc.lpfnWndProc = AngbandWndProc;
5257                 wc.cbClsExtra = 0;
5258                 wc.cbWndExtra = 4; /* one long pointer to term_data */
5259                 wc.hInstance = hInst;
5260                 wc.hIcon = hIcon = LoadIcon(hInst, AppName);
5261                 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
5262                 wc.hbrBackground = GetStockObject(BLACK_BRUSH);
5263                 wc.lpszMenuName = AppName;
5264                 wc.lpszClassName = AppName;
5265
5266                 if (!RegisterClass(&wc)) exit(1);
5267
5268                 wc.lpfnWndProc = AngbandListProc;
5269                 wc.lpszMenuName = NULL;
5270                 wc.lpszClassName = AngList;
5271
5272                 if (!RegisterClass(&wc)) exit(2);
5273
5274 #ifdef USE_SAVER
5275
5276                 wc.style = CS_VREDRAW | CS_HREDRAW | CS_SAVEBITS | CS_DBLCLKS;
5277                 wc.lpfnWndProc = AngbandSaverProc;
5278                 wc.hCursor = NULL;
5279                 wc.lpszMenuName = NULL;
5280                 wc.lpszClassName = "WindowsScreenSaverClass";
5281
5282                 if (!RegisterClass(&wc)) exit(3);
5283
5284 #endif
5285
5286         }
5287
5288         /* Temporary hooks */
5289         plog_aux = hack_plog;
5290         quit_aux = hack_quit;
5291         core_aux = hack_quit;
5292
5293         /* Prepare the filepaths */
5294         init_stuff();
5295
5296         /* Initialize the keypress analyzer */
5297         for (i = 0; special_key_list[i]; ++i)
5298         {
5299                 special_key[special_key_list[i]] = TRUE;
5300         }
5301         /* Initialize the keypress analyzer */
5302         for (i = 0; ignore_key_list[i]; ++i)
5303         {
5304                 ignore_key[ignore_key_list[i]] = TRUE;
5305         }
5306
5307         /* Determine if display is 16/256/true color */
5308         hdc = GetDC(NULL);
5309         colors16 = (GetDeviceCaps(hdc, BITSPIXEL) == 4);
5310         paletted = ((GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) ? TRUE : FALSE);
5311         ReleaseDC(NULL, hdc);
5312
5313         /* Initialize the colors */
5314         for (i = 0; i < 256; i++)
5315         {
5316                 byte rv, gv, bv;
5317
5318                 /* Extract desired values */
5319                 rv = angband_color_table[i][1];
5320                 gv = angband_color_table[i][2];
5321                 bv = angband_color_table[i][3];
5322
5323                 /* Extract the "complex" code */
5324                 win_clr[i] = PALETTERGB(rv, gv, bv);
5325
5326                 /* Save the "simple" code */
5327                 angband_color_table[i][0] = win_pal[i];
5328         }
5329
5330         /* Prepare the windows */
5331         init_windows();
5332
5333         /* bg */
5334         init_bg();
5335
5336         /* Activate hooks */
5337         plog_aux = hook_plog;
5338         quit_aux = hook_quit;
5339         core_aux = hook_quit;
5340
5341         /* Set the system suffix */
5342         ANGBAND_SYS = "win";
5343
5344         /* Set the keyboard suffix */
5345         if (7 != GetKeyboardType(0))
5346                 ANGBAND_KEYBOARD = "0";
5347         else
5348         {
5349                 /* Japanese keyboard */
5350                 switch (GetKeyboardType(1))
5351                 {
5352                 case 0x0D01: case 0x0D02:
5353                 case 0x0D03: case 0x0D04:
5354                 case 0x0D05: case 0x0D06:
5355                         /* NEC PC-98x1 */
5356                         ANGBAND_KEYBOARD = "NEC98";
5357                         break;
5358                 default:
5359                         /* PC/AT */
5360                         ANGBAND_KEYBOARD = "JAPAN";
5361                 }
5362         }
5363
5364         /* Catch nasty signals */
5365         signals_init();
5366
5367         Term_activate(term_screen);
5368         init_angband(p_ptr);
5369
5370         /* We are now initialized */
5371         initialized = TRUE;
5372 #ifdef CHUUKEI
5373         if (lpCmdLine[0] == '-') {
5374                 switch (lpCmdLine[1])
5375                 {
5376                 case 'p':
5377                 case 'P':
5378                 {
5379                         if (!lpCmdLine[2]) break;
5380                         chuukei_server = TRUE;
5381                         if (connect_chuukei_server(&lpCmdLine[2]) < 0) {
5382                                 msg_print("connect fail");
5383                                 return 0;
5384                         }
5385                         msg_print("connect");
5386                         msg_print(NULL);
5387                         break;
5388                 }
5389
5390                 case 'c':
5391                 case 'C':
5392                 {
5393                         if (!lpCmdLine[2]) break;
5394                         chuukei_client = TRUE;
5395                         connect_chuukei_server(&lpCmdLine[2]);
5396                         play_game(p_ptr, FALSE);
5397                         quit(NULL);
5398                         return 0;
5399                 }
5400                 case 'X':
5401                 case 'x':
5402                 {
5403                         if (!lpCmdLine[2]) break;
5404                         prepare_browse_movie(&lpCmdLine[2]);
5405                         play_game(p_ptr, FALSE);
5406                         quit(NULL);
5407                         return 0;
5408                 }
5409                 }
5410         }
5411 #endif
5412
5413 #ifdef CHUUKEI
5414         /* Did the user double click on a save file? */
5415         if (!chuukei_server) check_for_save_file(lpCmdLine);
5416 #else
5417         /* Did the user double click on a save file? */
5418         check_for_save_file(lpCmdLine);
5419 #endif
5420
5421         /* Prompt the user */
5422         prt(_("[ファイル] メニューの [新規] または [開く] を選択してください。", "[Choose 'New' or 'Open' from the 'File' menu]"), 23, _(8, 17));
5423
5424         Term_fresh();
5425
5426         /* Process messages forever */
5427         while (GetMessage(&msg, NULL, 0, 0))
5428         {
5429                 TranslateMessage(&msg);
5430                 DispatchMessage(&msg);
5431         }
5432         quit(NULL);
5433         return 0;
5434 }
5435
5436
5437 #endif /* WINDOWS */