OSDN Git Service

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