OSDN Git Service

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