OSDN Git Service

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