OSDN Git Service

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