OSDN Git Service

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