OSDN Git Service

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