OSDN Git Service

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