OSDN Git Service

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