OSDN Git Service

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