OSDN Git Service

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