/*
 * w_procs.c : NetHack display interfaces for win32 tile version
 *
 * Copyright (c) Yukihiko Aoki 1999, 2005
 * NetHack may be freely redistributed.  See license for details.
 *
 */

#include "hack.h"

#ifdef NH2K_EXTENDS

#include "win32api.h"
#include "w_main.h"
#include "func_tab.h"
#include "dlb.h"

#ifdef _DEBUG
static char dbuf[256];
#endif

/*
 *	Interface definition, for windows.c
 */
struct window_procs nh2k_procs = {
	"nh2k",
	0L,
	0L,
	nh2k_init_nhwindows,
	nh2k_player_selection,
	nh2k_askname,
	nh2k_get_nh_event,
	nh2k_exit_nhwindows,
	nh2k_suspend_nhwindows,
	nh2k_resume_nhwindows,
	nh2k_create_nhwindow,
	nh2k_clear_nhwindow,
	nh2k_display_nhwindow,
	nh2k_destroy_nhwindow,
	nh2k_curs,
	nh2k_putstr,
	nh2k_display_file,
	nh2k_start_menu,
	nh2k_add_menu,
	nh2k_end_menu,
	nh2k_select_menu,
	genl_message_menu,
	nh2k_update_inventory,
	nh2k_mark_synch,
	nh2k_wait_synch,
#ifdef CLIPPING
	nh2k_cliparound,
#endif
#ifdef POSITIONBAR
	donull,
#endif
	nh2k_print_glyph,
	nh2k_raw_print,
	nh2k_raw_print_bold,
	nh2k_nhgetch,
	nh2k_nh_poskey,
	nh2k_nhbell,
	nh2k_doprev_message,
	nh2k_yn_function,
	nh2k_getlin,
	nh2k_get_ext_cmd,
	nh2k_number_pad,
	nh2k_delay_output,
#ifdef MAKE_SOUND
	nh2k_make_sound,
#endif
#ifdef DISPLAY_EFFECT
	nh2k_display_effect,
#endif
	/* other defs that really should go away (they're tty specific) */
	nh2k_start_screen,
	nh2k_end_screen,
	genl_outrip,
	genl_preference_update
};

/* clean up and quit */
STATIC_OVL void bail(const char *mesg)
{
	clearlocks();
	nh2k_exit_nhwindows(mesg);
	terminate(EXIT_SUCCESS);
	/*NOTREACHED*/
}

/*
 * init_nhwindows
 */
void nh2k_init_nhwindows(int *argcp, char **argv)
{
#ifdef _DEBUG
	sprintf( dbuf, "nh2k_init_nhwindows:\n" );
	OutputDebugString( dbuf );
#endif

	/* register all window classes */
	RegisterNetHackWindows(g_hInstance);

	/* load resources */
	LoadSkins(g_hInstance);

	/* allocate the input buffer */
	Key_init();

	/* create main window */
	g_baseHwnd = BaseWnd_create();

//DoPropertySheet(g_baseHwnd);

	/* load menu window property */
	MenuWnd_setDefault();

//	  NHWnd_loadProperty("SYSTEM", &g_sysprop, sizeof(SYSTEMPROP), System_defaultProperty);

	/* hi-score must show in window */
	flags.toptenwin = TRUE;
/*	  CmdWnd_create();*/

    /* Now we can display messeges in windows */
    iflags.window_inited = TRUE;
}

/***************************************************************************************
 * exit_nhwindows
 ***************************************************************************************/
void nh2k_exit_nhwindows(const char *str)
{
#ifdef _DEBUG
	sprintf( dbuf, "nh2k_exit_nhwindows: str=%s\n", str );
	OutputDebugString( dbuf );
#endif
	/* free tiles */
	disp_procs.uninit();

	/* Destroy other windows if exist */
	NHWnd_destroyAll();

	/* Free input buffer */
	Key_uninit();

	/* free resources */
	FreeSkins();

	/* Unregister window classes */
	UnregisterNetHackWindows(g_hInstance);

	/* Destroy main window */
	/*DestroyWindow(g_baseHwnd);*/
}

/***************************************************************************************
 * player_selection
 ***************************************************************************************/
void nh2k_player_selection()
{
	int i, k, n;
	char pick4u = 'n', thisch, lastch = 0;
	char pbuf[QBUFSZ], plbuf[QBUFSZ];
	winid win;
	anything any;
	menu_item *selected = 0;

#ifdef _DEBUG
	sprintf( dbuf, "nh2k_player_selection:\n" );
	OutputDebugString( dbuf );
#endif

	/* prevent an unnecessary prompt */
	rigid_role_checks();

	/* Should we randomly pick for the player? */
	if (!flags.randomall &&
		(flags.initrole == ROLE_NONE || flags.initrace == ROLE_NONE ||
		flags.initgend == ROLE_NONE || flags.initalign == ROLE_NONE)) {

		char *prompt = build_plselection_prompt(pbuf, QBUFSZ, flags.initrole,
				flags.initrace, flags.initgend, flags.initalign);

		do {
			pick4u = lowc(yn_function(prompt, NULL, 'y'));
			if (index(quitchars, pick4u))
				pick4u = 'y';
		} while(!index(ynqchars, pick4u));
		
		if (pick4u != 'y' && pick4u != 'n') {
give_up:	/* Quit */
			if (selected) 
				free((genericptr_t) selected);
			bail((char *)0);
			/*NOTREACHED*/
			return;
		}
	}

	(void)	root_plselection_prompt(plbuf, QBUFSZ - 1,
			flags.initrole, flags.initrace, flags.initgend, flags.initalign);

	/* Select a role, if necessary */
	/* we'll try to be compatible with pre-selected race/gender/alignment,
	 * but may not succeed */
	if (flags.initrole < 0) {
		char rolenamebuf[QBUFSZ];
		/* Process the choice */
		if (pick4u == 'y' || flags.initrole == ROLE_RANDOM || flags.randomall) {
			/* Pick a random role */
			flags.initrole = pick_role(flags.initrace, flags.initgend,
						flags.initalign, PICK_RANDOM);
			if (flags.initrole < 0) {
/*			tty_putstr(BASE_WINDOW, 0, "Incompatible role!");*/
				flags.initrole = randrole();
			}
		} else {
/*JP
		tty_putstr(BASE_WINDOW, 0, "Choosing Character's Role");
*/
//		nh2k_putstr(BASE_WINDOW, 0, "職業選択");
		/* Prompt for a role */
		win = create_nhwindow(NHW_MENU);
		start_menu(win);
		any.a_void = 0; 		/* zero out all bits */
		for (i = 0; roles[i].name.m; i++) {
			if (ok_role(i, flags.initrace, flags.initgend,
							flags.initalign)) {
				any.a_int = i+1;	/* must be non-zero */
				thisch = lowc(roles[i].name.m[0]);
				if (thisch == lastch) thisch = highc(thisch);
				if (flags.initgend != ROLE_NONE && flags.initgend != ROLE_RANDOM) {
					if (flags.initgend == 1  && roles[i].name.f)
						Strcpy(rolenamebuf, roles[i].name.f);
					else
						Strcpy(rolenamebuf, roles[i].name.m);
				} else {
					if (roles[i].name.f) {
						Strcpy(rolenamebuf, roles[i].name.m);
						Strcat(rolenamebuf, "/");
						Strcat(rolenamebuf, roles[i].name.f);
					} else 
						Strcpy(rolenamebuf, roles[i].name.m);
				}	
#if 0 /*JP*/
				add_menu(win, NO_GLYPH, &any, thisch,
					0, ATR_NONE, an(rolenamebuf), MENU_UNSELECTED);
#else
				add_menu(win, NO_GLYPH, &any, thisch,
					0, ATR_NONE, jtrns_mon(roles[i].name.m), MENU_UNSELECTED);
#endif
				lastch = thisch;
			}
		}
		any.a_int = pick_role(flags.initrace, flags.initgend,
					flags.initalign, PICK_RANDOM)+1;
		if (any.a_int == 0) /* must be non-zero */
			any.a_int = randrole()+1;
		add_menu(win, NO_GLYPH, &any , '*', 0, ATR_NONE,
/*JP
				"Random", MENU_UNSELECTED);
*/
				"適当", MENU_UNSELECTED);
		any.a_int = i+1;	/* must be non-zero */
		add_menu(win, NO_GLYPH, &any , 'q', 0, ATR_NONE,
/*JP
				"Quit", MENU_UNSELECTED);
*/
				"中断", MENU_UNSELECTED);
/*JP
		Sprintf(pbuf, "Pick a role for your %s", plbuf);
*/
		Sprintf(pbuf, "%s職業を選択してください．", plbuf);
		end_menu(win, pbuf);
		n = select_menu(win, PICK_ONE, &selected);
		destroy_nhwindow(win);

		/* Process the choice */
		if (n != 1 || selected[0].item.a_int == any.a_int)
			goto give_up;		/* Selected quit */

		flags.initrole = selected[0].item.a_int - 1;
		free((genericptr_t) selected),	selected = 0;
		}
		(void)	root_plselection_prompt(plbuf, QBUFSZ - 1,
			flags.initrole, flags.initrace, flags.initgend, flags.initalign);
	}
	
	/* Select a race, if necessary */
	/* force compatibility with role, try for compatibility with
	 * pre-selected gender/alignment */
	if (flags.initrace < 0 || !validrace(flags.initrole, flags.initrace)) {
		/* pre-selected race not valid */
		if (pick4u == 'y' || flags.initrace == ROLE_RANDOM || flags.randomall) {
		flags.initrace = pick_race(flags.initrole, flags.initgend,
							flags.initalign, PICK_RANDOM);
		if (flags.initrace < 0) {
/*			tty_putstr(BASE_WINDOW, 0, "Incompatible race!");*/
			flags.initrace = randrace(flags.initrole);
		}
		} else {	/* pick4u == 'n' */
		/* Count the number of valid races */
		n = 0;	/* number valid */
		k = 0;	/* valid race */
		for (i = 0; races[i].noun; i++) {
			if (ok_race(flags.initrole, i, flags.initgend,
							flags.initalign)) {
			n++;
			k = i;
			}
		}
		if (n == 0) {
			for (i = 0; races[i].noun; i++) {
			if (validrace(flags.initrole, i)) {
				n++;
				k = i;
			}
			}
		}

		/* Permit the user to pick, if there is more than one */
		if (n > 1) {
/*			tty_clear_nhwindow(BASE_WINDOW);*/
/*JP
			tty_putstr(BASE_WINDOW, 0, "Choosing Race");
*/
/*			tty_putstr(BASE_WINDOW, 0, "種族選択");*/
			win = create_nhwindow(NHW_MENU);
			start_menu(win);
			any.a_void = 0; 		/* zero out all bits */
			for (i = 0; races[i].noun; i++)
			if (ok_race(flags.initrole, i, flags.initgend,
							flags.initalign)) {
				any.a_int = i+1;	/* must be non-zero */
#if 0 /*JP*/
				add_menu(win, NO_GLYPH, &any, races[i].noun[0],
				0, ATR_NONE, races[i].noun, MENU_UNSELECTED);
#else
				add_menu(win, NO_GLYPH, &any, races[i].noun[0],
				0, ATR_NONE, jtrns_mon(races[i].noun), MENU_UNSELECTED);
#endif
			}
			any.a_int = pick_race(flags.initrole, flags.initgend,
					flags.initalign, PICK_RANDOM)+1;
			if (any.a_int == 0) /* must be non-zero */
			any.a_int = randrace(flags.initrole)+1;
			add_menu(win, NO_GLYPH, &any , '*', 0, ATR_NONE,
/*JP
					"Random", MENU_UNSELECTED);
*/
					"適当", MENU_UNSELECTED);
			any.a_int = i+1;	/* must be non-zero */
			add_menu(win, NO_GLYPH, &any , 'q', 0, ATR_NONE,
/*JP
					"Quit", MENU_UNSELECTED);
*/
					"中断", MENU_UNSELECTED);
/*JP
			Sprintf(pbuf, "Pick the race of your %s", plbuf);
*/
			Sprintf(pbuf, "%s種族を選択してください．", plbuf);
			end_menu(win, pbuf);
			n = select_menu(win, PICK_ONE, &selected);
			destroy_nhwindow(win);
			if (n != 1 || selected[0].item.a_int == any.a_int)
			goto give_up;		/* Selected quit */

			k = selected[0].item.a_int - 1;
			free((genericptr_t) selected),	selected = 0;
		}
		flags.initrace = k;
		}
		(void)	root_plselection_prompt(plbuf, QBUFSZ - 1,
			flags.initrole, flags.initrace, flags.initgend, flags.initalign);
	}

	/* Select a gender, if necessary */
	/* force compatibility with role/race, try for compatibility with
	 * pre-selected alignment */
	if (flags.initgend < 0 || !validgend(flags.initrole, flags.initrace,
						flags.initgend)) {
		/* pre-selected gender not valid */
		if (pick4u == 'y' || flags.initgend == ROLE_RANDOM || flags.randomall) {
		flags.initgend = pick_gend(flags.initrole, flags.initrace,
						flags.initalign, PICK_RANDOM);
		if (flags.initgend < 0) {
/*			tty_putstr(BASE_WINDOW, 0, "Incompatible gender!");*/
			flags.initgend = randgend(flags.initrole, flags.initrace);
		}
		} else {	/* pick4u == 'n' */
		/* Count the number of valid genders */
		n = 0;	/* number valid */
		k = 0;	/* valid gender */
		for (i = 0; i < ROLE_GENDERS; i++) {
			if (ok_gend(flags.initrole, flags.initrace, i,
							flags.initalign)) {
			n++;
			k = i;
			}
		}
		if (n == 0) {
			for (i = 0; i < ROLE_GENDERS; i++) {
			if (validgend(flags.initrole, flags.initrace, i)) {
				n++;
				k = i;
			}
			}
		}

		/* Permit the user to pick, if there is more than one */
		if (n > 1) {
/*			tty_clear_nhwindow(BASE_WINDOW);*/
/*JP
			tty_putstr(BASE_WINDOW, 0, "Choosing Gender");
*/
/*			tty_putstr(BASE_WINDOW, 0, "性別選択");*/
			win = create_nhwindow(NHW_MENU);
			start_menu(win);
			any.a_void = 0; 		/* zero out all bits */
			for (i = 0; i < ROLE_GENDERS; i++)
			if (ok_gend(flags.initrole, flags.initrace, i,
								flags.initalign)) {
				any.a_int = i+1;
				add_menu(win, NO_GLYPH, &any, genders[i].adj[0],
/*JP
				0, ATR_NONE, genders[i].adj, MENU_UNSELECTED);
*/
				0, ATR_NONE, genders[i].j, MENU_UNSELECTED);
			}
			any.a_int = pick_gend(flags.initrole, flags.initrace,
						flags.initalign, PICK_RANDOM)+1;
			if (any.a_int == 0) /* must be non-zero */
			any.a_int = randgend(flags.initrole, flags.initrace)+1;
			add_menu(win, NO_GLYPH, &any , '*', 0, ATR_NONE,
/*JP
					"Random", MENU_UNSELECTED);
*/
					"適当", MENU_UNSELECTED);
			any.a_int = i+1;	/* must be non-zero */
			add_menu(win, NO_GLYPH, &any , 'q', 0, ATR_NONE,
/*JP
					"Quit", MENU_UNSELECTED);
*/
					"中断", MENU_UNSELECTED);
/*JP
			Sprintf(pbuf, "Pick the gender of your %s", plbuf);
*/
			Sprintf(pbuf, "%s性別を選んでください", plbuf);
			end_menu(win, pbuf);
			n = select_menu(win, PICK_ONE, &selected);
			destroy_nhwindow(win);
			if (n != 1 || selected[0].item.a_int == any.a_int)
			goto give_up;		/* Selected quit */

			k = selected[0].item.a_int - 1;
			free((genericptr_t) selected),	selected = 0;
		}
		flags.initgend = k;
		}
		(void)	root_plselection_prompt(plbuf, QBUFSZ - 1,
			flags.initrole, flags.initrace, flags.initgend, flags.initalign);
	}

	/* Select an alignment, if necessary */
	/* force compatibility with role/race/gender */
	if (flags.initalign < 0 || !validalign(flags.initrole, flags.initrace,
							flags.initalign)) {
		/* pre-selected alignment not valid */
		if (pick4u == 'y' || flags.initalign == ROLE_RANDOM || flags.randomall) {
		flags.initalign = pick_align(flags.initrole, flags.initrace,
							flags.initgend, PICK_RANDOM);
		if (flags.initalign < 0) {
/*			tty_putstr(BASE_WINDOW, 0, "Incompatible alignment!");*/
			flags.initalign = randalign(flags.initrole, flags.initrace);
		}
		} else {	/* pick4u == 'n' */
		/* Count the number of valid alignments */
		n = 0;	/* number valid */
		k = 0;	/* valid alignment */
		for (i = 0; i < ROLE_ALIGNS; i++) {
			if (ok_align(flags.initrole, flags.initrace, flags.initgend,
							i)) {
			n++;
			k = i;
			}
		}
		if (n == 0) {
			for (i = 0; i < ROLE_ALIGNS; i++) {
				if (validalign(flags.initrole, flags.initrace, i)) {
					n++;
					k = i;
				}
			}
		}

		/* Permit the user to pick, if there is more than one */
		if (n > 1) {
/*			tty_clear_nhwindow(BASE_WINDOW);*/
/*JP
			tty_putstr(BASE_WINDOW, 0, "Choosing Alignment");
*/
/*			tty_putstr(BASE_WINDOW, 0, "属性選択");*/
			win = create_nhwindow(NHW_MENU);
			start_menu(win);
			any.a_void = 0; 		/* zero out all bits */
			for (i = 0; i < ROLE_ALIGNS; i++)
			if (ok_align(flags.initrole, flags.initrace,
							flags.initgend, i)) {
				any.a_int = i+1;
				add_menu(win, NO_GLYPH, &any, aligns[i].adj[0],
/*JP
				 0, ATR_NONE, aligns[i].adj, MENU_UNSELECTED);
*/
				 0, ATR_NONE, aligns[i].j, MENU_UNSELECTED);
			}
			any.a_int = pick_align(flags.initrole, flags.initrace,
						flags.initgend, PICK_RANDOM)+1;
			if (any.a_int == 0) /* must be non-zero */
			any.a_int = randalign(flags.initrole, flags.initrace)+1;
			add_menu(win, NO_GLYPH, &any , '*', 0, ATR_NONE,
/*JP
					"Random", MENU_UNSELECTED);
*/
					"適当", MENU_UNSELECTED);
			any.a_int = i+1;	/* must be non-zero */
			add_menu(win, NO_GLYPH, &any , 'q', 0, ATR_NONE,
/*JP
					"Quit", MENU_UNSELECTED);
*/
					"中断", MENU_UNSELECTED);
/*JP
			Sprintf(pbuf, "Pick the alignment of your %s", plbuf);
*/
			Sprintf(pbuf, "%s属性を選択してください", plbuf);
			end_menu(win, pbuf);
			n = select_menu(win, PICK_ONE, &selected);
			destroy_nhwindow(win);
			if (n != 1 || selected[0].item.a_int == any.a_int)
			goto give_up;		/* Selected quit */

			k = selected[0].item.a_int - 1;
			free((genericptr_t) selected),	selected = 0;
		}
		flags.initalign = k;
		}
	}
	/* Success! */
/*	tty_display_nhwindow(BASE_WINDOW, FALSE);*/
}

/***************************************************************************************
 * askname
 ***************************************************************************************/
void nh2k_askname()
{
	char buf[BUFSZ];
	int length;

#ifdef _DEBUG
	sprintf(dbuf, "nh2k_askname: \n");
	OutputDebugString(dbuf);
#endif

	buf[0] = '\0';
	do {
		InputWnd_doModal("あなたは誰？", buf, BUFSZ - 1);
    } while (strcmp(buf,"\033\000") == 0);
	length = strlen(buf);
	if (length >= PL_NSIZ) {
		length = PL_NSIZ - 1;
	}
	strncpy(plname, buf, length);
	plname[length] = '\0';
}

/***************************************************************************************
 * get_nh_event
 ***************************************************************************************/
void nh2k_get_nh_event()
{
	MSG msg;
/*
	while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
*/
/*
	if(GetMessage(&msg, NULL, 0, 0)) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
*/
	if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != 0) {
		if (!TranslateAccelerator(msg.hwnd, g_hAccel, &msg)) {
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}
}

/***************************************************************************************
 * suspend_nhwindows
 ***************************************************************************************/
void nh2k_suspend_nhwindows(const char *str)
{
#ifdef _DEBUG
	sprintf(dbuf, "nh2k_suspend_nhwindows: str=%s\n", str);
	OutputDebugString(dbuf);
#endif
}

/***************************************************************************************
 * create_nhwindow
 ***************************************************************************************/
void nh2k_resume_nhwindows()
{
#ifdef _DEBUG
	sprintf(dbuf, "nh2k_resume_nhwindows: \n");
	OutputDebugString(dbuf);
#endif
}

/***************************************************************************************
 * create_nhwindow
 ***************************************************************************************/
winid nh2k_create_nhwindow(int type)
{
	WINDESC *wd;

#ifdef _DEBUG
	sprintf( dbuf, "nh2k_create_nhwindow: \n" );
	OutputDebugString( dbuf );
#endif

	wd = NHWnd_createDesc(type);
	if(wd) {
		return (winid)wd;
	}else {
		raw_print( "Error: nh2k_create_nhwindow" );
	}

	return WIN_ERR;
}

/***************************************************************************************
 * clear_nhwindow
 ***************************************************************************************/
void nh2k_clear_nhwindow(winid window)
{
	WINDESC *wd = (WINDESC*)window;

#ifdef _DEBUG
	sprintf( dbuf, "nh2k_clear_nhwindow: \n" );
	OutputDebugString( dbuf );
#endif

	if(NHWnd_isValid(wd)) {
		if(wd->procClear) {
			wd->procClear(wd);
		}
	}else {
		raw_print( "Error: nh2k_clear_nhwindow" );
	}
}

/***************************************************************************************
 * display_nhwindow
 ***************************************************************************************/
void nh2k_display_nhwindow(winid window, boolean blocking)
{
	WINDESC *wd = (WINDESC*)window;

#ifdef _DEBUG
	sprintf( dbuf, "nh2k_display_nhwindow: \n" );
	OutputDebugString( dbuf );
#endif

	if(NHWnd_isValid(wd)) {
		ShowWindow(wd->hwnd, SW_SHOW);
		if(wd->procDisplay) {
			wd->procDisplay(wd);
		}
		if(blocking) {
			NHWnd_more(wd);
		}
	}else {
		raw_print("Error: nh2k_display_nhwindow");
	}
}

/***************************************************************************************
 * destroy_nhwindow
 ***************************************************************************************/
void nh2k_destroy_nhwindow(winid window)
{
	WINDESC* wd = (WINDESC*)window;

#ifdef _DEBUG
	sprintf( dbuf, "nh2k_destroy_nhwindow: \n" );
	OutputDebugString( dbuf );
#endif

	if(NHWnd_isValid(wd)) {
		NHWnd_destroyDesc(wd);
	}else {
		pline("Error: nh2k_destroy_nhwindow");
	}
}

/***************************************************************************************
 * curs
 ***************************************************************************************/
void nh2k_curs(winid window, register int col, register int row)
{
	WINDESC *wd = (WINDESC*)window;

#ifdef _DEBUG
	sprintf( dbuf, "nh2k_curs: \n" );
	OutputDebugString( dbuf );
#endif

	if(NHWnd_isValid(wd)) {
		if(wd->procSetCursor) {
			wd->procSetCursor(wd, col, row);
		}
	}else {
		raw_print("Error: nh2k_curs");
	}
}

/***************************************************************************************
 * putstr
 ***************************************************************************************/
void nh2k_putstr(winid window, int attr, const char *str)
{
	WINDESC *wd = (WINDESC*)window;

#ifdef _DEBUG
	sprintf(dbuf, "nh2k_putstr: %s\n", str);
	OutputDebugString(dbuf);
#endif

	if(NHWnd_isValid(wd)) {
		if(wd->procPutStr) {
			wd->procPutStr(wd, attr, str);
		}
	}else {
		nh2k_raw_print("Error: nh2k_putstr");
	}
}

/***************************************************************************************
 * display_file
 ***************************************************************************************/
void nh2k_display_file(const char *fname, boolean complain)
{
	char	buf[BUFSZ];
	dlb 	*fp;
	int 	yy=0;
	winid	window;
	int 	length;

#ifdef _DEBUG
	sprintf( dbuf, "nh2k_display_file: fname=%s\n", fname );
	OutputDebugString( dbuf );
#endif

	fp = dlb_fopen(fname, "r");
	if(!fp) {
		if(complain) {
			pline("Cannot open \"%s\".", fname);
		}
	} else {
		window = create_nhwindow(NHW_TEXT);
		while(dlb_fgets(buf, BUFSZ, fp)) {
			length = strlen(buf);
			if(length >= 2 && buf[length-2] == '\r') {
				buf[length-2] = '\0';
			}

			putstr(window, ATR_NONE, buf);
		}
		display_nhwindow(window, TRUE);
		destroy_nhwindow(window);
		dlb_fclose(fp);
	}
}

/***************************************************************************************
 * update_inventory
 ***************************************************************************************/
void nh2k_update_inventory()
{
#ifdef _DEBUG
	sprintf(dbuf,"nh2k_update_inventory:\n");
	OutputDebugString(dbuf);
#endif
}

/***************************************************************************************
 * mark_synch
 ***************************************************************************************/
void nh2k_mark_synch()
{
#ifdef _DEBUG
	sprintf(dbuf,"nh2k_mark_synch:\n");
	OutputDebugString(dbuf);
#endif
}

/***************************************************************************************
 * wait_synch
 ***************************************************************************************/
void nh2k_wait_synch()
{
#ifdef _DEBUG
	sprintf(dbuf,"nh2k_wait_synch:\n");
	OutputDebugString(dbuf);
#endif
}

/***************************************************************************************
 * cliparound
 ***************************************************************************************/
void nh2k_cliparound(int x, int y)
{
	WINDESC *wd = (WINDESC*)WIN_MAP;

#ifdef _DEBUG
	sprintf( dbuf, "nh2k_cliparound: \n" );
	OutputDebugString( dbuf );
#endif

	if(NHWnd_isValid(wd)) {
		MapWnd_clip(x,y);
	}
}

/***************************************************************************************
 * print_glyph
 ***************************************************************************************/
void nh2k_print_glyph(winid window, xchar col, xchar row, int glyph)
{
	WINDESC *wd = (WINDESC*)window;
	int fg, bg;

#ifdef _DEBUG
	sprintf( dbuf, "nh2k_print_glyph:\n" );
	OutputDebugString( dbuf );
#endif

	if(glyph == cmap_to_glyph(S_stone)) {
		bg = fg = glyph;
	}else {
		/**** ここから *****/
		if(Blind || (viz_array && !cansee(col, row))) {
			struct rm *lev = &levl[col][row];
			bg = lev->glyph;
			if(glyph_is_object(bg)) {
				if(!lev->waslit) {
					bg = cmap_to_glyph(S_stone);
				}else {
					bg = back_to_glyph(col, row);
				}
			}
		}else {
			/***** ここまで追加 *****/
			bg = back_to_glyph(col, row);
		}
		if(bg == glyph) {
			fg = cmap_to_glyph(S_stone);
		}else {
			fg = glyph;
		}
	}
/*
	if(glyph == cmap_to_glyph(S_stone)) {
		bg = fg = glyph;
	}else {
		bg = back_to_glyph(col, row);
		if(bg == glyph) {
			fg = cmap_to_glyph(S_stone);
		}else {
			fg = glyph;
		}
	}
*/

	if(NHWnd_isValid(wd) && wd->type == NHW_MAP) {
		MapWnd_setGlyph(wd, col, row, bg, fg);
	}else {
		/* Unsupported type of window */
		nh2k_raw_print( "print_glyph to bad window type." );
	}
}


/***************************************************************************************
 * raw_print
 ***************************************************************************************/
void nh2k_raw_print( const char *str )
{
#ifdef _DEBUG
	sprintf(dbuf, "nh2k_raw_print: str=%s\n", str);
	OutputDebugString(dbuf);
#endif
	if (str != NULL && strlen(str) > 0) {
		MessageBox(NULL, str, "NetHack", MB_OK);
	}
}

/***************************************************************************************
 * raw_print_bold
 ***************************************************************************************/
void nh2k_raw_print_bold(const char *str)
{
#ifdef _DEBUG
	sprintf(dbuf, "nh2k_raw_print_bold: str=%s\n", str);
	OutputDebugString(dbuf);
#endif

	if (str != NULL && strlen(str) > 0) {
		MessageBox(NULL, str, "NetHack", MB_OK);
	}
}

/***************************************************************************************
 * nhgetch
 ***************************************************************************************/
int nh2k_nhgetch()
{
#ifdef _DEBUG
	sprintf( dbuf, "nh2k_nhgetch: \n" );
	OutputDebugString( dbuf );
#endif

	return Key_getChar();
}

/***************************************************************************************
 * nh_poskey
 ***************************************************************************************/
int nh2k_nh_poskey( int *x, int *y, int *mod )
{
#ifdef _DEBUG
	sprintf( dbuf, "nh2k_nh_poskey: \n" );
	OutputDebugString( dbuf );
#endif

	return Key_getChar();
}

/***************************************************************************************
 * doprev_message
 ***************************************************************************************/
int nh2k_doprev_message()
{
	WINDESC *wd = (WINDESC*)WIN_MESSAGE;

#ifdef _DEBUG
	sprintf( dbuf, "nh2k_doprev_message: \n" );
	OutputDebugString( dbuf );
#endif

	if(NHWnd_isValid(wd)) {
		MesgWnd_cmdPrev(wd);
	}

	return 0;
}

/***************************************************************************************
 * yn_function
 ***************************************************************************************/
char nh2k_yn_function(const char *query, const char *choices, char def)
{
	WINDESC *wd = (WINDESC *)WIN_MESSAGE;
	char	 ch;
	int 	 keyStat;

#ifdef _DEBUG
	sprintf(dbuf, "nh2k_yn_function: %s\n", query);
	OutputDebugString( dbuf );
#endif

	keyStat = Key_setStatus(KEYSTAT_MENUSELECT);
	if (!g_sysprop.ask_popup && NHWnd_isValid(wd)) {
		ch = MesgWnd_ask(wd, query, choices, def);
    } else {
		ch = AskWnd_doModal(query, choices, def);
	}
	Key_setStatus(keyStat);

	return ch;
}

/***************************************************************************************
 * delay_output
 ***************************************************************************************/
void nh2k_delay_output()
{
	int i;

#ifdef _DEBUG
	sprintf( dbuf, "nh2k_delay_output: \n" );
	OutputDebugString( dbuf );
#endif

	for(i = 0; i < 5; i++) {
		get_nh_event();
		Sleep(10);
	}
}

/***************************************************************************************
 * end_screen
 ***************************************************************************************/
void nh2k_end_screen()
{
#ifdef _DEBUG
	sprintf(dbuf,"nh2k_end_screen:\n");
	OutputDebugString(dbuf);
#endif
}

/***************************************************************************************
 * get_ext_cmd
 ***************************************************************************************/
int nh2k_get_ext_cmd()
{
	extern struct ext_func_tab extcmdlist[];
	char	buf[256];
	char	fixedbuf[256];
	int 	i=0;
	int 	j;
	winid	id;
	int 	max_len=0;
	anything ident;
	menu_item *selected;
	int 	retn;
	int 	selid;
	int 	curidx = 0;
	int 	samecnt = 0;

#ifdef _DEBUG
	sprintf(dbuf, "nh2k_get_ext_cmd:\n");
	OutputDebugString(dbuf);
#endif

	while(extcmdlist[i].ef_txt != NULL) {
		if(strlen(extcmdlist[i].ef_txt) > max_len) {
			max_len = strlen( extcmdlist[i].ef_txt );
		}
		i++;
	}

	do {
		id = create_nhwindow(NHW_MENU);
		start_menu(id);

		for (i = 0; extcmdlist[i].ef_txt != NULL; i++) {
			if (curidx > 0 && strncmp(fixedbuf, extcmdlist[i].ef_txt, curidx) != 0) {
				continue;
			} else {
				strncpy(buf, extcmdlist[i].ef_txt, strlen(extcmdlist[i].ef_txt));
				for( j=strlen(extcmdlist[i].ef_txt);j<=max_len; j++ ) {
					buf[j] = ' ';
				}
				sprintf( &buf[j], "%s", extcmdlist[i].ef_desc );
				ident.a_void = (char*)i;
				add_menu(id, NO_GLYPH, &ident, extcmdlist[i].ef_txt[curidx], 0, ATR_NONE, buf, FALSE);
			}
		}
		end_menu(id, NULL);
		retn = select_menu(id, PICK_ONE, &selected);
		if(retn <= 0) {
			return -1;
		}
		selid = (int)selected->item.a_void;
		free(selected);
		destroy_nhwindow(id);
		curidx++;
		strncpy(fixedbuf, extcmdlist[selid].ef_txt, curidx);
		fixedbuf[curidx] = '\0';
		samecnt = 0;
		for (i = 0; extcmdlist[i].ef_txt != NULL; i++) {
			if (strncmp(fixedbuf, extcmdlist[i].ef_txt, curidx) == 0) {
				samecnt++;
			}
		}
	} while (samecnt > 1);

	return selid;
}

/***************************************************************************************
 * getlin
 ***************************************************************************************/
void nh2k_getlin(const char *ques, char *input)
{
	int keyStat;

#ifdef _DEBUG
	sprintf(dbuf, "nh2k_getlin: %s\n", ques);
	OutputDebugString(dbuf);
#endif

	keyStat = Key_setStatus(KEYSTAT_DIALOGINPUT);
	flush_screen(1);
	InputWnd_doModal(ques, input, BUFSZ);
	Key_setStatus(keyStat);
}

/***************************************************************************************
 * nhbell
 ***************************************************************************************/
void nh2k_nhbell()
{
#ifdef _DEBUG
	sprintf(dbuf,"nh2k_nhbell:\n");
	OutputDebugString(dbuf);
#endif
}

/***************************************************************************************
 * number_pad
 ***************************************************************************************/
void nh2k_number_pad( int x )
{
#ifdef _DEBUG
	sprintf(dbuf,"nh2k_number_pad: x=%d\n",x);
	OutputDebugString(dbuf);
#endif
}

/***************************************************************************************
 * start_screen
 ***************************************************************************************/
void nh2k_start_screen()
{
#ifdef _DEBUG
	sprintf(dbuf,"nh2k_start_screen:\n");
	OutputDebugString(dbuf);
#endif
}

/***************************************************************************************
 * start_menu
 ***************************************************************************************/
void nh2k_start_menu( winid window )
{
	WINDESC *wd = (WINDESC*)window;

#ifdef _DEBUG
	sprintf( dbuf, "nh2k_start_menu: \n" );
	OutputDebugString( dbuf );
#endif

	if(NHWnd_isValid(wd) && (wd->type==NHW_MENU || wd->type==NHW_TEXT)) {
		MenuWnd_startMenu( wd );
	}
	else {
		pline( "Error: nh2k_start_menu" );
	}
}

/***************************************************************************************
 * add_menu
 ***************************************************************************************/
void nh2k_add_menu(
	winid window,
	int glyph,
	const anything *identifier,
	char ch,
	char gch,
	int attr,
	const char *str,
	boolean preselected)
{
	WINDESC *wd = (WINDESC*)window;

#ifdef _DEBUG
	sprintf( dbuf, "nh2k_add_menu: \n" );
	OutputDebugString( dbuf );
#endif

	if(NHWnd_isValid(wd) && (wd->type==NHW_MENU || wd->type==NHW_TEXT) ) {
		MenuWnd_addMenu(wd,glyph,identifier,ch,gch,attr,str,preselected);
	}else {
		pline("Error: nh2k_add_menu");
	}
}

/***************************************************************************************
 * end_menu
 ***************************************************************************************/
void nh2k_end_menu(winid window, const char *prompt)
{
	WINDESC *wd = (WINDESC*)window;

#ifdef _DEBUG
	sprintf( dbuf, "nh2k_end_menu: \n" );
	OutputDebugString( dbuf );
#endif

	if(NHWnd_isValid(wd) && (wd->type==NHW_MENU || wd->type==NHW_TEXT)) {
		MenuWnd_endMenu(wd, prompt);
	}else {
		pline("Error: nh2k_end_menu");
	}
}

/***************************************************************************************
 * select_menu
 ***************************************************************************************/
int nh2k_select_menu(winid window, int how, menu_item **menu_list)
{
	WINDESC *wd  = (WINDESC*)window;
	int 	 ret = -1;
	int 	 keyStat;

#ifdef _DEBUG
	sprintf( dbuf, "nh2k_select_menu: \n" );
	OutputDebugString( dbuf );
#endif

	if(NHWnd_isValid((WINDESC *) WIN_MESSAGE)) {
		clear_nhwindow(WIN_MESSAGE);
	}

	keyStat = Key_setStatus(KEYSTAT_MENUSELECT);
	if(NHWnd_isValid(wd) && (wd->type==NHW_MENU || wd->type==NHW_TEXT)) {
		ret = MenuWnd_selectMenu(wd, how, menu_list);
	}else {
		pline("Error: nh2k_select_menu");
	}
	Key_setStatus(keyStat);

	return ret;
}

/***************************************************************************************
 * display_effect
 ***************************************************************************************/
#ifdef DISPLAY_EFFECT
void nh2k_display_effect(winid window, int col, int row, int type)
{
	if(NHWnd_isValid((WINDESC *)window)) {
		MapWnd_cmdEffect((WINDESC *)window, col, row, type);
	}
}
#endif /* DISPLAY_EFFECT */

/***************************************************************************************
 * make_sound
 ***************************************************************************************/
#ifdef MAKE_SOUND
void nh2k_make_sound(int type)
{
	const char *filename;

#ifdef _DEBUG
	sprintf(dbuf, "nh2k_make_sound: &d\n", type);
	OutputDebugString(dbuf);
#endif

	if(filename = Sound_getFilename(type)) {
		if(_access(filename, 00) == 0) {
			PlaySound(filename, NULL, SND_FILENAME|SND_ASYNC);
		}
	}
}
#endif /* MAKE_SOUND */

#endif /* NH2K_EXTENDS */
