OSDN Git Service

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