/*							dviout for Windows
 *
 *				Menu Bar, Tool Bar. Page Slider, Status Bar,...
 *						1996 written by Otobe & SHIMA
 */
#include <windows.h>   // Win32APIを使用する
#include <commctrl.h>  // Common Controls を使用する
#include <ddeml.h>	   // DDEMLライブラリを使用する
#include <shellapi.h>  // Drag-Drop
#include <assert.h>	   // Using Assertion
#include <io.h>
#include "resource.h"  // ﾘｿｰｽ定義ﾌｧｲﾙを読み込む
#include "root.h"	   // ｱﾌﾟﾘｹｰｼｮﾝ固有の定数
#include "inter.h"
#include "err.h"

#ifndef GWL_WNDPROC
#define GWL_WNDPROC (-4)
#endif

#ifdef USE_INTELLI_MOUSE
extern UINT uMSH_MOUSEWHEEL;
extern UINT WheelScrollLines;
#endif

// Ver 6.0 commctrl.h 
#ifndef	RBB
#define RBBS_GRIPPERALWAYS	0x00000080	// always show the gripper
#endif

#ifdef REBAR
 #ifndef REBARCLASSNAME
 #error	Require new <commctrl.h>
 #endif
#endif

#ifndef TBSTYLE_FLAT
#define TBSTYLE_FLAT			0x0800
#endif

extern char		 g_szFileName[MAX_PATH];	  // dvi-file名
extern OPENFILENAME g_OpenFileName;			   // OPENFILENAME構造体
extern DDESTRUCT	g_ddeData;

extern HWND			hShell;					// HyperJump

extern int g_cyToolBar0;  // the height of toolbar
extern int g_cyStatusBar0; // the height of status bar
extern int g_cyShowMessage;

extern BOOL f_flatscroll;
extern BOOL f_background;
extern BOOL f_presenmenu;
// extern int f_pmenu;
extern int view_back;
extern BOOL f_rev_movebutton;
BOOL f_pagebutton = FALSE;


int f_renew = 1;
int f_lupdown;
int f_quit;
BOOL f_button;		// 2nd Tool Buttons
static BOOL f_org_tool;
BOOL f_rebar = FALSE;

#if	defined(MSVC) || defined(BCPB)
#define	CWPROC	WNDPROC
#else
#define	CWPROC	FARPROC
#endif

static CWPROC lpfnDefCombo;
static CWPROC lpfnDefEdit;
static CWPROC lpfnDefUpDown;
static CWPROC lpfnDefComboEdit;

extern BOOL f_animecursor;
extern BOOL f_directsrc;
extern BOOL f_Wshow;
extern BOOL f_prtlarge;
extern BOOL f_timer;
extern BOOL f_gedit;
extern BOOL f_inch;
extern BOOL f_gridO;
extern BOOL f_Din;
extern int w_grid;

extern BOOL f_m_down;
extern BOOL f_l_down;

extern char	*exec_src_sp;
extern char *exec_gsrc_sp;
extern char *exec_dviprt;

DWORD GetFindReplaceOption(); /* wndproc.c */


/* ステータスバーのペインの数 */
#define NUMSTATUS 4

void SetStatusBar( int c, char* szText )
{
	/* c: ステータスバーのペインの番号（左から０起算）
	   szText: 設定する内容（NULL終端文字列）*/
	/* 設定番号が NUMSTATUS を含んでそれ以上ならば、バグである */
	assert( c < NUMSTATUS );
	SendMessage( g_winData.statusbar.hWnd, SB_SETTEXT, c, (LPARAM)szText );
	return;
}

BOOL ResizeAllWindows( void )
{
	RECT rc;
	short cxClientMain, cyClientMain;
	int cyDVIwindow;

	/* 親ウィンドウのクライアント領域の取得 */
	GetClientRect( g_winData.hMainWnd, &rc );
	cxClientMain = rc.right - rc.left;
	cyClientMain = rc.bottom - rc.top;

	/* まずステータスバーの位置決定 */
	if( g_winData.statusbar.bShown == FALSE )
	{
		if( IsWindowVisible( g_winData.statusbar.hWnd ) )
		{
			ShowWindow( g_winData.statusbar.hWnd, SW_HIDE );
			g_winData.statusbar.cy = 0;
		}
	}
	else
	{
		if( !IsWindowVisible( g_winData.statusbar.hWnd ) )
		{
			ShowWindow( g_winData.statusbar.hWnd, SW_SHOWDEFAULT );
			g_winData.statusbar.cy = g_cyStatusBar0;
		}
	}
	MoveWindow( g_winData.statusbar.hWnd, 0, cyClientMain - g_winData.statusbar.cy,
					cxClientMain, g_winData.statusbar.cy, TRUE );

	/* ツールバーの位置決定 */
	if( g_winData.toolbar.bShown == FALSE )
	{
		if( IsWindowVisible( g_winData.toolbar.hWndToolBar ) )
		{	ShowWindow( g_winData.toolbar.hWndToolBar, SW_HIDE );
			if( f_rebar == FALSE ) g_winData.toolbar.cy = 0;
		}
	}
	else
	{
		if( !IsWindowVisible( g_winData.toolbar.hWndToolBar ) && !f_rebar )
		{
			ShowWindow( g_winData.toolbar.hWndToolBar, SW_SHOWDEFAULT );
			g_winData.toolbar.cy = G_CYTOOLBAR;
//			g_winData.toolbar.cy = g_cyToolBar0;;
//			error(13, "%d,%d", G_CYTOOLBAR, g_cyToolBar0);
		}
	}
	if( !f_rebar ) SendMessage( g_winData.toolbar.hWndToolBar, TB_AUTOSIZE, 0, 0 );

	/* When combo box in tool bar shows a drop down list box,
	   we have to destroy it. Here, we call SetUpSearchFromCombo,
	   which set up strings and destroy list box. */
//	SetUpSearchFromCombo();


	/* We have to set g_winData.info.cy which has the information of size,
	   page slider, status bar need such info to decide the position,
	   so we have to calculate before them. */
	if( g_winData.info.hWnd == NULL && g_winData.hWndPick == NULL )
		g_winData.info.cy = 0;
	else
		g_winData.info.cy = g_cyShowMessage;


	/* スライダの位置決定 */
	if( g_winData.slider.bShown == FALSE )
	{
		if( IsWindowVisible( g_winData.slider.hWnd ) )
		{
			ShowWindow( g_winData.slider.hWnd, SW_HIDE );
			g_winData.slider.cx = 0;
		}
	}
	else
	{
		if( !IsWindowVisible( g_winData.slider.hWnd ) )
		{
			ShowWindow( g_winData.slider.hWnd, SW_SHOWDEFAULT );
			g_winData.slider.cx = 32;
		}
	}
	MoveWindow( g_winData.slider.hWnd, 
				rc.right - g_winData.slider.cx, g_winData.toolbar.cy, 
				g_winData.slider.cx, rc.bottom - rc.top - g_winData.toolbar.cy - g_winData.statusbar.cy - g_winData.info.cy,
				TRUE );
	
	
	/* DVI表示用子ウィンドウの位置決定 */
	cyDVIwindow = cyClientMain - g_winData.toolbar.cy - g_winData.statusbar.cy - g_winData.info.cy;
	MoveWindow( g_winData.dviwin.hWnd, 0, g_winData.toolbar.cy, 
				cxClientMain - g_winData.slider.cx,
				cyClientMain - g_winData.toolbar.cy - g_winData.statusbar.cy - g_winData.info.cy, TRUE );

	if( g_winData.info.hWnd != NULL )
		MoveWindow( g_winData.info.hWnd,
			0, g_winData.toolbar.cy + cyDVIwindow, cxClientMain, g_winData.info.cy, TRUE );
	if( g_winData.hWndPick != NULL )
		MoveWindow( g_winData.hWndPick,
			0, g_winData.toolbar.cy + cyDVIwindow, cxClientMain, g_winData.info.cy, TRUE );

	return TRUE;
}

void SetSpinRange( short min, short max, short current )
{
	/* スピンコントロールの範囲とカレント値を設定
		min: 最小値
		max: 最大値
		current: カレント値 */
	SendMessage( g_winData.toolbar.hWndPageSpin, UDM_SETRANGE, 0L, 
		(f_lupdown)?MAKELPARAM(max,min):MAKELPARAM(min,max) );
	SetDlgItemInt( g_winData.toolbar.hWndToolBar, ID_PAGEEDIT, current, FALSE );
	/* 一旦無効にしないと、なぜかボタンがうまく有効にならないようだ。 */
	EnableWindow( g_winData.toolbar.hWndPageSpin, FALSE );
	EnableWindow( g_winData.toolbar.hWndPageSpin, TRUE );
	/* スライダの範囲を設定 */
	SendMessage( g_winData.slider.hWnd, TBM_SETRANGE, 
							(WPARAM)TRUE, MAKELPARAM(min,max) );
	SendMessage( g_winData.slider.hWnd, TBM_SETPOS,
							(WPARAM)TRUE, (LPARAM)current );
	SendMessage( g_winData.slider.hWnd, TBM_SETTHUMBLENGTH, 8, 0);
	return;
}

void SetMarkRange( short start, short end )
{
	if(!start){
		SendMessage( g_winData.slider.hWnd, TBM_CLEARSEL, TRUE, 0 );
		return;
	}

	if(start > end){
		short tmp;

		tmp = start;
		start = end;
		end = tmp;
	}
	SendMessage( g_winData.slider.hWnd, TBM_SETSELSTART, TRUE, start );
	SendMessage( g_winData.slider.hWnd, TBM_SETSELEND, TRUE, end );
}

static UINT fbuttom[] =
{
	ID_PRINT,
	ID_SEARCH,
	ID_PRECAND,
	ID_NEXTCAND,
	ID_INFO,
	ID_INFO_FONT,
	ID_INFO_BUFFER,
	ID_INFO_URL,
	ID_INFO_ANCHOR,
	ID_INFO_SRC,

	ID_BREOPEN,
	ID_BFORMERHIST,
	ID_BNEXTHIST,
	ID_BMARKPAGE,
	ID_BGOMARK,
	ID_ABOUTB,
	ID_NEXTPAGE,
	ID_PREVPAGE,
	ID_TOPPAGE,
	ID_LASTPAGE
};

static UINT fmenu[] =
{
	ID_REOPEN,
	ID_PRINT,
	ID_DVIPRT,
	ID_ETF,
//	ID_SAVEIMG,
	ID_INFO,
	ID_INFO_FONT,
	ID_INFO_BUFFER,
	ID_INFO_URL,
	ID_INFO_ANCHOR,
	ID_INFO_SRC,
//	ID_TOOLBAR_CHANGE,
	ID_MHAND,
	ID_FIT,
	ID_FULL,
	ID_DOUBLE,
	ID_RDOUBLE,
	ID_VDOUBLE,
	ID_CROSS,
	ID_16PAGE,
//	ID_MACRO1,
//	ID_MACRO2,
//	ID_MACRO3,
//	ID_MACRO4,
//	ID_MACRO5,
	ID_CUTEDGE,
	ID_RECTON,
	ID_RECTCUT,
	ID_RECTREC
};

static HWND *fhwnd[] = {
	&g_winData.toolbar.hWndFindCombo,
	&g_winData.toolbar.hWndPageEdit,
	&g_winData.toolbar.hWndPageSpin,
	&g_winData.slider.hWnd
};

void EnableETFInfo(BOOL flag)
{
	EnableMenuItem(g_winData.hMenu, ID_INFO_ETF,
				((flag)?MFS_ENABLED:MFS_GRAYED)|MF_BYCOMMAND);
}

void EnableInitInfo(BOOL flag)
{
	EnableMenuItem(g_winData.hMenu, ID_INFO_INIT,
				((flag)?MFS_ENABLED:MFS_GRAYED)|MF_BYCOMMAND);
}

void EnableButton( BOOL flag )
{
	static BOOL old_flag = TRUE;
	int	i;

	if(old_flag != flag){
		for(i = 0; i < sizeof(fbuttom)/sizeof(UINT); i++)
			SendMessage(g_winData.toolbar.hWndToolBar, TB_ENABLEBUTTON, 
			fbuttom[i], flag);
		for(i=0; i < sizeof(fmenu)/sizeof(UINT); i++)
			EnableMenuItem(g_winData.hMenu, fmenu[i],
				((flag)?MFS_ENABLED:MFS_GRAYED)|MF_BYCOMMAND);
		EnableMenuItem(GetSubMenu(g_winData.hMenu, 0), 8, 	// Save as image
				((flag)?MFS_ENABLED:MFS_GRAYED)|MF_BYPOSITION);
		EnableMenuItem(GetSubMenu(g_winData.hMenu, 7), 8, 	// Change Japanese font
				((flag)?MFS_ENABLED:MFS_GRAYED)|MF_BYPOSITION);
		EnableMenuItem(GetSubMenu(g_winData.hMenu, 7), 9, 	// Macro
				((flag)?MFS_ENABLED:MFS_GRAYED)|MF_BYPOSITION);
		EnableMenuItem(g_winData.hMenu,1, 					// Jump
			((flag)?MFS_ENABLED:MFS_GRAYED)|MF_BYPOSITION);
		EnableMenuItem(g_winData.hMenu,2, 					// Search
			((flag)?MFS_ENABLED:MFS_GRAYED)|MF_BYPOSITION);
		DrawMenuBar(g_winData.hMainWnd);
		for(i=0; i < sizeof(fhwnd)/sizeof(HWND *); i++)
			EnableWindow(*fhwnd[i], flag);
		old_flag = flag;
	}
}

static DWORD tButtonID[] = {
	ID_INFO, ID_INFO_FONT, ID_INFO_BUFFER, ID_INFO_KEY, ID_INFO_PARA, ID_ABOUT, 
	ID_BREOPEN, ID_BFORMERHIST, ID_BNEXTHIST, ID_BMARKPAGE, ID_BGOMARK, ID_ABOUTB
};

/*
 cond 0: set status 0
	  1: set status 1
	  2: change status
	 -1: get status
*/
int ChangeToolBar(int cond)
{
	static int status;
	int old_status;
	int num, shift;

	old_status = status;
	switch(cond){
		case 0:
		case 1:
			status = cond;
			break;
		case 2:
			status = 1 - status;
			break;
		default:
			if(cond > 0xfff)
				return (f_org_tool = f_button = status = (cond & 1));
			break;
	}
	if(old_status != status){
		shift = (status)?6:0;
		for(num = 0; num < 6; num++){
			SendMessage(g_winData.toolbar.hWndToolBar, TB_SETCMDID,
				num + 28, tButtonID[num + shift]);
			SendMessage(g_winData.toolbar.hWndToolBar, TB_CHANGEBITMAP, 
				tButtonID[num + shift], num + 11 + shift);
		}
	}
	return old_status;
}

void SetButton(void)
{
	if(g_szFileName[0] > ' '){
		EnableButton(TRUE);
		SendMessage(g_winData.toolbar.hWndToolBar, TB_ENABLEBUTTON, 
			ID_BNEXTHIST, TRUE);
		SendMessage(g_winData.toolbar.hWndToolBar, TB_ENABLEBUTTON, 
			ID_BGOMARK, TRUE);
	}
	ChangeToolBar(f_button);
}

static void MoveRebar( void )
{
	RECT rc;
	int x, y, cx, cy;
	x = y = 0; // for future.
	GetWindowRect( g_winData.hMainWnd, &rc );
	cx = rc.right - rc.left;
	cy = rc.bottom - rc.top;

	MoveWindow( GetDlgItem(g_winData.hMainWnd, ID_REBAR),
		x, y,
		cx, cy, TRUE );
}


static HWND ToolBar( HWND hWndParent )
{
	HWND hWndToolBar;
	int index;
	HWND hWndRebar = NULL;
#ifdef REBAR
	RECT rc;
#endif

	static TBBUTTON tbButtons[] = {
		{ 0, ID_FILEOPEN, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 }, // 1
		{ 1, ID_F_HISTORY, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 },
		{ 2, ID_PRINT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 },
		{ 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0L, 0 },
		{ 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0L, 0 },
		{ 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0L, 0 },
		{ 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0L, 0 },
		{ 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0L, 0 },
		{ 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0L, 0 }, 
		{ 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0L, 0 }, // 10
		{ 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0L, 0 },
		{ 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0L, 0 },
		{ 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0L, 0 },
		{ 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0L, 0 },
		{ 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0L, 0 },
		{ 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0L, 0 },
		{ 3, ID_SEARCH, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 },
		{ 4, ID_PRECAND, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 },
		{ 5, ID_NEXTCAND, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 },
		{ 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0L, 0 }, // 20
		{ 6, ID_MAGNIFY, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 },
		{ 7, ID_REDUCE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 },
		{ 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0L, 0 },
		{ 8, ID_HYPER, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 },
		{ 9, ID_MHAND, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 },
		{ 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0L, 0 },
		{10, ID_OPTION, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 },
		{ 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0L, 0 },
		{11, ID_INFO, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 },
		{12, ID_INFO_FONT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 }, // 30
		{13, ID_INFO_BUFFER, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 },
		{14, ID_INFO_KEY, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 },
		{15, ID_INFO_PARA, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 },
		{16, ID_ABOUT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 },
		{ 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0L, 0 },
		{17, ID_TOPPAGE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 },
		{18, ID_PREVPAGE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 },
		{19, ID_NEXTPAGE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 },
		{20, ID_LASTPAGE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 },
	};

	static TBBUTTON tbDynaButtons[] = {
		{ 0, ID_FILEOPEN, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 }, // 1
		{ 1, ID_F_HISTORY, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 },
		{ 2, ID_PRINT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 },
		{ 3, ID_SEARCH, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 },
		{ 4, ID_PRECAND, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 },
		{ 5, ID_NEXTCAND, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 },
		{ 6, ID_MAGNIFY, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 },
		{ 7, ID_REDUCE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 },
		{ 8, ID_HYPER, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 },
		{ 9, ID_MHAND, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 },
		{10, ID_OPTION, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 },
		{11, ID_INFO, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 },
		{12, ID_INFO_FONT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 },
		{13, ID_INFO_BUFFER, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 },
		{14, ID_INFO_KEY, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 },
		{15, ID_INFO_PARA, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 },
		{16, ID_ABOUT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 },
		{17, ID_TOPPAGE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 },
		{18, ID_PREVPAGE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 },
		{19, ID_NEXTPAGE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 },
		{20, ID_LASTPAGE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0 },
	};

#ifdef REBAR // for future. Now always FALSE.
	if( GetVersionLevel() > 0 ) f_rebar = TRUE;
#endif

	/* Build a rebar. */
	if( f_rebar )
	{
#ifdef REBAR
		REBARINFO rbi;
		GetWindowRect( hWndParent, &rc );
		hWndRebar = CreateWindowEx( WS_EX_TOOLWINDOW,
			REBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
			WS_CLIPCHILDREN | RBS_VARHEIGHT | CCS_NODIVIDER,
			0, 0, 0, 0,
			hWndParent, (HMENU)ID_REBAR, g_winData.hInstance, NULL );
		ZeroMemory( &rbi, sizeof(REBARINFO) );
		rbi.cbSize = sizeof(REBARINFO);
		rbi.fMask = 0;
		rbi.himl = (HIMAGELIST)NULL;
		SendMessage( hWndRebar, RB_SETBARINFO, 0, (LPARAM)&rbi );
#endif
	}

	g_winData.dviwin.loupe.fShape = RestoreInt( "Settings", "LoupeMode", FALSE );
	if((g_winData.dviwin.loupe.skip = HIWORD(g_winData.dviwin.loupe.fShape)) < 1)
		g_winData.dviwin.loupe.skip = 4;
	f_lupdown = (g_winData.dviwin.loupe.fShape & F_LUPDOWN);
	g_winData.dviwin.loupe.bKillCursor = (g_winData.dviwin.loupe.fShape & LOUPE_KILL_CURSOR)?TRUE:FALSE;
	if(g_winData.dviwin.loupe.fShape & F_LTOOLBAR){
		ChangeToolBar(0x1001);
		for(index = 11; index < 17; index++){
			tbButtons[index + (28-11)].iBitmap =  index + 6;
			tbButtons[index + (28-11)].idCommand = tButtonID[index - (11 - 6)];
		}
	}
	for( index = 35; index <= 38; index++ )
	{
		tbButtons[index].iBitmap = index - 12;
	}
	hWndToolBar = CreateToolbarEx(
					hWndParent,
					WS_CHILD | WS_VISIBLE | TBSTYLE_TOOLTIPS,
					ID_TOOLBAR,
					f_pagebutton?27:23,	 // number of bitmaps.
					g_winData.hInstance,
					IDB_TOOLBAR, // resource ID for toolbar bitmap.
					f_rebar?((LPCTBBUTTON)&tbDynaButtons):((LPCTBBUTTON)&tbButtons),
					f_rebar?(f_pagebutton?21:16):(f_pagebutton?39:34),
					16, 15,		// size of a button with pixels
					16, 15,		// size of a bitmap with pixels
					sizeof(TBBUTTON) ); // size of a structure
	if( f_rebar )	g_winData.toolbar.bShown = FALSE;

	g_winData.toolbar.hWndFindCombo = CreateWindowEx( 0L,
						"COMBOBOX",
						NULL,
						WS_CHILD | WS_BORDER | WS_VISIBLE |
						//CBS_HASSTRINGS | CBS_DROPDOWN | CBS_AUTOSCROLL,
						CBS_DROPDOWN | CBS_AUTOHSCROLL,
						f_rebar?0:70, 0, 102, 160, // position and size
						f_rebar?hWndParent:hWndToolBar,
						(HMENU)ID_FINDCOMBO,
						g_winData.hInstance,
						NULL );
	g_winData.toolbar.hWndPageEdit	= CreateWindowEx( WS_EX_CLIENTEDGE,	// 0L, // for Windows XP
						"EDIT",
						NULL,
						WS_CHILD | WS_VISIBLE |		// WS_BORDER  // for Windows XP
						ES_AUTOHSCROLL,
						f_rebar?0:(f_pagebutton?628:528), 0, 64, 26, // position and size
						f_rebar?hWndParent:hWndToolBar,
						(HMENU)ID_PAGEEDIT,
						g_winData.hInstance,
						NULL );
	g_winData.toolbar.hWndPageSpin = CreateWindowEx( 0L,
						UPDOWN_CLASS,
						NULL,
						WS_CHILD | WS_BORDER | WS_VISIBLE | // UDS_WRAP |
						UDS_NOTHOUSANDS |
						UDS_ARROWKEYS | UDS_ALIGNRIGHT | UDS_SETBUDDYINT,
						f_rebar?0:(f_pagebutton?670:570), 1, 22, 24,
						f_rebar?hWndParent:hWndToolBar,
						(HMENU)ID_UPDOWN,
						g_winData.hInstance,
						NULL );
	/* エディットコントロールをスピンコントロールのバディーに設定 */
	SendMessage( g_winData.toolbar.hWndPageSpin, UDM_SETBUDDY,
					 (LONG)g_winData.toolbar.hWndPageEdit, 0L );
	
	g_winData.toolbar.hWndNombreStatic = CreateWindowEx( 0L,
						"STATIC",
						NULL,
						WS_CHILD | WS_VISIBLE,
						f_rebar?0:(f_pagebutton?692:592), 2, 120, 26,
						f_rebar?hWndParent:hWndToolBar,
						(HMENU)ID_NOMBRESTATIC,
						g_winData.hInstance,
						NULL );
	SetWindowText( g_winData.toolbar.hWndNombreStatic, "( )" );
	SetSpinRange( 0, 0, 1 );


	if( hWndToolBar == NULL )
	{
		MessageBox( NULL, "Fail to create Tool Bar", NULL, MB_OK );
	}
	else
	{
		LONG lStyle;
		lStyle = GetWindowLong( hWndToolBar, GWL_STYLE );
		if( GetVersionLevel() > 0 ) // Make it FLAT.
			lStyle |= TBSTYLE_FLAT;
		SetWindowLong( hWndToolBar, GWL_STYLE, lStyle );

		if( GetVersionLevel() > 0 && f_rebar )
		{
			if( hWndRebar )
			{
#ifdef REBAR
				REBARBANDINFO rbbi;
				RECT rc;
				DWORD dwHeight;
				ZeroMemory( &rbbi, sizeof(REBARBANDINFO) );
				/* Common parameters */
				rbbi.cbSize		  = sizeof(REBARBANDINFO);
				rbbi.fMask		  = RBBIM_COLORS | 
										RBBIM_SIZE | 
										RBBIM_CHILD | 
										RBBIM_CHILDSIZE | 
										RBBIM_STYLE | 
										RBBIM_TEXT;
				rbbi.fStyle		  = RBBS_CHILDEDGE | RBBS_GRIPPERALWAYS;


				GetWindowRect( g_winData.toolbar.hWndFindCombo, &rc );
				rbbi.lpText		= "Combo Box";
				rbbi.hwndChild	= g_winData.toolbar.hWndFindCombo;
				rbbi.cxMinChild = 0;
				rbbi.cyMinChild = rc.bottom - rc.top;
				rbbi.cx			  = 200;
				SendMessage( hWndRebar, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbbi );

				dwHeight = SendMessage( hWndToolBar, TB_GETBUTTONSIZE, 0, 0 );
				rbbi.lpText		= "ToolBar";
				rbbi.hwndChild	= hWndToolBar;
				rbbi.cxMinChild = 0;
				rbbi.cyMinChild = HIWORD(dwHeight);
				rbbi.cx			  = 250;
				SendMessage( hWndRebar, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbbi );
				MoveRebar();
#endif
			}
		}
	}

	return hWndToolBar;
}


/* メインウィンドウのウィンドウプロシージャ */
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT message, UINT wParam, LONG lParam)
{
	static int StatusWidth[NUMSTATUS];
	static WORD	 cxClientMain = 0; //MAINｸﾗｲｱﾝﾄ領域のxｻｲｽﾞ
	static WORD	 cyClientMain = 0; //MAINｸﾗｲｱﾝﾄ領域のyｻｲｽﾞ
	TOOLINFO tbToolInfo;
	static HWND hWndTT;
	LPTOOLTIPTEXT lpToolTipText;
//	static CHAR szBuf[128];
	int idx;
	RECT rc;
	RECT rc_tmp;
	static char szWindowTitle[265];
	int topage; //ページの移動先
	int i; // counter
//	HDC hdc; // you can destroy this valiable any time.
//	DWORD dwColor; // also.
	char *tmsg;
//	MSG msg; // used in PeekMessage which is in WM_VSCROLL
	HANDLE hMemFile;
	DWORD dwStyle;
	
	switch( message )
	{
		case WM_CREATE:
			if( g_winData.hInstance != ((LPCREATESTRUCT)lParam)->hInstance )
			{
				g_winData.hInstance = ((LPCREATESTRUCT)lParam)->hInstance;
			}
			g_winData.toolbar.hWndEditInCombo = NULL; 
			return 0;
		
		case WM_SIZE:
			if( cxClientMain != LOWORD(lParam) )
			{
				cxClientMain = LOWORD(lParam);
			}
			if( cyClientMain != HIWORD(lParam) )
			{
				cyClientMain = HIWORD(lParam);
			}
			/* ステータスバーのサイズ計算 */
			ResizeAllWindows();
			MoveRebar();
			StatusWidth[0] = cxClientMain*6/23;
			StatusWidth[1] = cxClientMain*11/23;
			StatusWidth[2] = cxClientMain*16/23;
			StatusWidth[3] = -1;
			SendMessage( g_winData.statusbar.hWnd, SB_SETPARTS,
							 NUMSTATUS, (LPARAM)StatusWidth );
			if( g_winData.info.hWnd != NULL )
				SendMessage( g_winData.info.hWnd, WM_SIZE, 0, 0 );
			break;
			
		case WM_USER_INITIATE:
			/* 「ﾌｧｲﾙを開く」ダイアログデータの初期化 */
			g_OpenFileName.lStructSize		 = sizeof(g_OpenFileName);
			g_OpenFileName.hwndOwner		 = g_winData.hMainWnd;
			g_OpenFileName.hInstance		 = NULL;
			g_OpenFileName.lpstrFilter		 = NULL; // 要指定
			g_OpenFileName.lpstrCustomFilter = NULL;
			g_OpenFileName.nMaxCustFilter	 = 0;
			g_OpenFileName.nFilterIndex		 = 0;
			g_OpenFileName.lpstrFile		 = NULL; // 要指定
			g_OpenFileName.nMaxFile			 = MAX_PATH*sizeof(TCHAR);// 要指定
			g_OpenFileName.lpstrFileTitle	 = NULL; // 要指定
			g_OpenFileName.nMaxFileTitle	 = MAX_PATH*sizeof(TCHAR);// 要指定
			g_OpenFileName.lpstrInitialDir	 = NULL;
			g_OpenFileName.lpstrTitle		 = NULL; // 要指定
			g_OpenFileName.Flags			 = 0;	 // 要指定
			g_OpenFileName.nFileOffset		 = 0;
			g_OpenFileName.nFileExtension	 = 0;
			g_OpenFileName.lpstrDefExt		 = NULL;  // 要指定
			g_OpenFileName.lCustData		 = 0;
			g_OpenFileName.lpfnHook			 = NULL;
			g_OpenFileName.lpTemplateName	 = NULL;
#if 0
			/* ヒープエリアの作成 */
			g_winData.hHeap = HeapCreate( 0, /* ﾋｰﾌﾟｱｸｾｽはｼﾘｱﾗｲｽﾞする。*/
						  1024*1024, /* デフォルトで１Ｍバイト確保 */
						  0 );		 /* 限界まで拡張可 */
#endif			
			/* ファイルマネージャからのドラッグアンドドロップを許可 */
			DragAcceptFiles( g_winData.hMainWnd, 1);
			
			/* クライアント領域の取得 */
			GetClientRect( g_winData.hMainWnd, &rc );
			cxClientMain = rc.right - rc.left;
			cyClientMain = rc.bottom - rc.top;
			
			/* メニューバーのハンドルの取得 */
			g_winData.hMenu = GetMenu( g_winData.hMainWnd );

			/* ステータスバーの作成 */
			g_winData.statusbar.hWnd = CreateWindowEx( 0L,
				STATUSCLASSNAME,
				"",
				WS_CHILD | WS_VISIBLE | SBS_SIZEGRIP,
				0, rc.bottom - g_winData.statusbar.cy,
				rc.right - rc.left, g_winData.statusbar.cy,
				g_winData.hMainWnd,
				(HMENU)ID_STATUSBAR,
				g_winData.hInstance,
				NULL );
			if( g_winData.statusbar.hWnd == NULL )
			{
				MessageBox( NULL, "Status Bar not created.", NULL, MB_OK );
				return 0;
			}else{
				GetWindowRect( g_winData.statusbar.hWnd, &rc_tmp );
				g_winData.statusbar.cy = g_cyStatusBar0 = rc_tmp.bottom - rc_tmp.top;
			}
			SendMessage( g_winData.statusbar.hWnd, SB_SETPARTS,
						 NUMSTATUS, (LPARAM)StatusWidth );

			SetStatusWindow();
			/* Restore HERE! */
			f_flatscroll = RestoreInt( "Settings", "FlatScrollBar", FALSE );
			f_pagebutton = RestoreInt( "Settings", "PageButton", TRUE );
			f_rev_movebutton = RestoreInt( "Settings", "ReverseMove", FALSE );

			/* ツールバーの作成 */
			g_winData.toolbar.hWndToolBar = ToolBar( g_winData.hMainWnd );
//			GetWindowRect( g_winData.toolbar.hWndToolBar, &rc_tmp );
//			g_cyToolBar0 = rc_tmp.bottom - rc_tmp.top;
 
			/* トラックバーの作成 */
			if( f_flatscroll && GetVersionLevel() > 0 )
			{
				dwStyle = 0L;
			}
			else
			{
				dwStyle = WS_EX_CLIENTEDGE;
			}
			g_winData.slider.hWnd = CreateWindowEx( dwStyle,
						TRACKBAR_CLASS,
						NULL,
						WS_CHILD | WS_VISIBLE | TBS_AUTOTICKS |
						TBS_VERT | TBS_LEFT | TBS_ENABLESELRANGE,
						rc.right - g_winData.slider.cx, g_winData.toolbar.cy,
						g_winData.slider.cx,
						rc.bottom - rc.top - g_winData.statusbar.cy - g_winData.toolbar.cy,
						g_winData.hMainWnd,
						(HMENU)ID_SLIDER,
						g_winData.hInstance,
						NULL );
			if( g_winData.slider.hWnd == NULL )
			{
				MessageBox( g_winData.hMainWnd, "Creating Slider failed.",
							NULL, MB_OK );
			}
			SendMessage( g_winData.slider.hWnd, TBM_SETRANGE, 
								TRUE, MAKELPARAM(1,1) );
			SendMessage( g_winData.slider.hWnd, TBM_SETLINESIZE,
								0, 1 );
			SendMessage( g_winData.slider.hWnd, TBM_SETPAGESIZE,
								0, 1 );

			/* 表示ウィンドウの調整 */
			SendMessage( g_winData.dviwin.hWnd, WM_USER_INITIATE, 0, 0L );
			
			/* ツールバーのコントロールに対するツールチップ表示
			   およびツールバーでの処理のための
			   それぞれのウィンドウプロシージャのフック */
			lpfnDefCombo = (CWPROC)GetWindowLong(
								g_winData.toolbar.hWndFindCombo, GWL_WNDPROC );
			SetWindowLong( g_winData.toolbar.hWndFindCombo, GWL_WNDPROC, 
								(LONG)ComboWndProc );
			lpfnDefEdit	 = (CWPROC)GetWindowLong(
								g_winData.toolbar.hWndPageEdit, GWL_WNDPROC );
			SetWindowLong( g_winData.toolbar.hWndPageEdit, GWL_WNDPROC,
								(LONG)PageEditProc );
			lpfnDefUpDown  = (CWPROC)GetWindowLong(
								g_winData.toolbar.hWndPageSpin, GWL_WNDPROC );
			SetWindowLong( g_winData.toolbar.hWndPageSpin, GWL_WNDPROC,
								(LONG)PageSpinProc );

			/* ツールヒントウィンドウの設定 */
			hWndTT = (HWND)SendMessage( g_winData.toolbar.hWndToolBar, TB_GETTOOLTIPS, 0, 0 );
			if( hWndTT != NULL )
			{
				/* TOOLINFO構造体の設定 */
				tbToolInfo.cbSize = sizeof(tbToolInfo);
				tbToolInfo.uFlags = TTF_IDISHWND | TTF_CENTERTIP;
				tbToolInfo.hinst = g_winData.hInstance;
				tbToolInfo.hwnd = g_winData.hMainWnd;

				tbToolInfo.uId = (UINT)g_winData.toolbar.hWndFindCombo;
				tbToolInfo.lpszText = (LPSTR)IDM_COMBO;
				SendMessage(hWndTT, TTM_ADDTOOL, 0, 
					(LPARAM)(LPTOOLINFO)&tbToolInfo);

				tbToolInfo.uId = (UINT)g_winData.toolbar.hWndPageEdit;
				tbToolInfo.lpszText = (LPSTR)IDM_PAGEEDIT;
				SendMessage(hWndTT, TTM_ADDTOOL, 0, 
					(LPARAM)(LPTOOLINFO)&tbToolInfo);
			}
			else
			{
				MessageBox( NULL, 
					"Cannot get Window Handle of\n"
					"TOOL Hint", NULL, MB_OK );
			}
			/* DDEの登録 */
			g_ddeData.hszService1
				= DdeCreateStringHandle( g_ddeData.idInst,
												 "DVIOUT", 0 );
			g_ddeData.hszService2
				= DdeCreateStringHandle( g_ddeData.idInst,
												 "WinDVI", 0 );
			g_ddeData.hszTopic1
				= DdeCreateStringHandle( g_ddeData.idInst, "DVIOUT", 0 );
			g_ddeData.hszTopic2
				= DdeCreateStringHandle( g_ddeData.idInst, "WinDVI", 0 );
			DdeNameService( g_ddeData.idInst, 
					g_ddeData.hszService1, 0L, DNS_REGISTER );
			DdeNameService( g_ddeData.idInst, 
					g_ddeData.hszService2, 0L, DNS_REGISTER );

			RestoreGlobal();

			EnableButton( FALSE );
			EnableETFInfo( FALSE );
			EnableInitInfo( FALSE );
			CheckMenu(ID_DVIOUTSPECIAL, f_dvioutspecial );
			CheckMenu(ID_SRCSPECIAL, f_srcspecial );
			CheckMenu(ID_HYPERTEX, f_hypertex );
			CheckMenu(ID_USEETF, f_use_etf );
			CheckMenu(ID_PRESENMENU, f_presenmenu);
			CheckMenu(ID_COVERSHEET, g_winData.dviwin.cover_sheet.fOn );
			CheckMenu(ID_REVERSE_MOVEBUTTON, f_rev_movebutton );
			CheckMenu(ID_TOOLBAR_VIEW,g_winData.toolbar.bShown );
			CheckMenu(ID_STATUS_VIEW, g_winData.statusbar.bShown );
			CheckMenu(ID_SLIDER_VIEW, g_winData.slider.bShown );
			CheckMenu(ID_SCROLLBAR_VIEW, g_winData.dviwin.bScrollBarShown );
			CheckMenu(ID_PAGEBUTTON, f_pagebutton );
			CheckMenuSet(ID_WHITEDEF + f_background, ID_WHITEDEF, ID_WHITEBACK);
			CheckMenu(ID_ANIMECURSOR, f_animecursor );
			CheckMenu(ID_CSHOW, f_Wshow);
			CheckMenu(ID_DIRECTSRC, f_directsrc );
			CheckMenu(ID_CHKCOLOR, g_bCheckColorSpecial);	
			CheckMenu(ID_GEDIT, f_gedit );
			CheckMenu(ID_DIN, f_Din);
			CheckMenuSet(ID_DRLINE, ID_DRLINE, ID_DRLINE);
			CheckMenuSet(ID_DRRED, ID_DRRED, ID_DRRED);

			if( GetVersionLevel() < 1 )
				EnableMenuItem( g_winData.hMenu, ID_FLAT_SCROLLBAR, MF_GRAYED );
			CheckMenu(ID_FLAT_SCROLLBAR, f_flatscroll );
			if(view_back == -1)
				i= ID_VBACK_DEF;
			else if(view_back == 0xffffff)
				i = ID_VBACK_WHITE;
			else
				i = ID_VBACK_BLACK;
			CheckMenuSet(i, ID_VBACK_DEF, ID_VBACK_BLACK);
			CheckMenu(ID_USELBUTTON, g_winData.dviwin.cover_sheet.fButton & CS_LBUTTON);
			CheckMenu(ID_USERBUTTON, g_winData.dviwin.cover_sheet.fButton & CS_RBUTTON);
			if(g_winData.dviwin.cover_sheet.fPlace & CS_BOTTOM){
				if(g_winData.dviwin.cover_sheet.fPlace & CS_RIGHT)
					i = ID_COVERBR;
				else if(g_winData.dviwin.cover_sheet.fPlace & CS_LEFT)
					i = ID_COVERBL;
				else
					i = ID_COVERB;
			}else{
				if(g_winData.dviwin.cover_sheet.fPlace & CS_RIGHT)
					i = ID_COVERR;
				else
					i = ID_COVERL;
			}
			CheckMenuSet(i, ID_COVERB, ID_COVERBL);
			if(g_winData.dviwin.cover_sheet.fOn)
				i = g_winData.dviwin.cover_sheet.bOnForPause?ID_COVERSHEET:ID_COVERON;
			else
				i = ID_COVEROFF;
			CheckMenuSet(i, ID_COVERSHEET, ID_COVEROFF);
			CheckMenu(ID_SCROL2PAUSE, g_winData.dviwin.cover_sheet.bScrollToPause);
			CheckMenuSet(ID_PENBLACK, ID_PENBLACK, ID_PENWHITE);
			CheckMenuSet(ID_PENW1, ID_PENW1, ID_PENW4);
			CheckMenuSet(ID_PENT1, ID_PENT1, ID_PENT5);
			switch( g_cyShowMessage/80 )
			{
				case 1:
					i = ID_INF_SMALL;
					break;
				case 2:
					i = ID_INF_MEDIUM;
					break;
				case 4:
					i = ID_INF_LARGE;
					break;
			}
			CheckMenuSet(i, ID_INF_LARGE, ID_INF_SMALL);

			if(!IsJapanese()){
				f_English = TRUE;
				i = FALSE;
				if(my_access("^x\\DOC\\dviouttipse.html", 0) != 0)
					EnableMenuItem(g_winData.hMenu,ID_TIPS, 
						MFS_GRAYED|MF_BYCOMMAND);
			}else{
				i = TRUE;
				if(my_access("^x\\DOC\\dvioutQA.html", 0) != 0)
					EnableMenuItem(g_winData.hMenu,ID_TROUBLE_HELP, 
						MFS_GRAYED|MF_BYCOMMAND);
				if(my_access("^x\\DOC\\dviouttips.html", 0) != 0)
					EnableMenuItem(g_winData.hMenu,ID_TIPS, 
						MFS_GRAYED|MF_BYCOMMAND);
			}
			if(f_English)
				CheckMenu(ID_ENGLISH_HELP, 1);
			if(i && !f_English){	// OS supports Japanese & Japanese mode
				f_English = TRUE;
				if(access(GetHelpPath(), 0))	// non-existence of dvioute.hlp
					i = FALSE;
				f_English = FALSE;
			}
			if(!i)
				EnableMenuItem(g_winData.hMenu,ID_ENGLISH_HELP, 
					MFS_GRAYED|MF_BYCOMMAND);
			if(f_spcolor)
				CheckMenu(ID_COLOR, 1);
			if(f_rpcolor>=2 && f_rpcolor!=6)
				CheckMenu(ID_REPCOLOR, 1);
			if(g_winData.dviwin.loupe.fShape & F_LMEASURE)
				CheckMenu(ID_LMEASURE, 1);
			if(g_winData.dviwin.loupe.bKillCursor)
				CheckMenu(ID_LCURSOR, 1);
			CheckMenu(ID_WARNING_VIEW, 1);
			CheckMenu(ID_GRAPHIC, 1);
			CheckMenu(ID_FLASHLESS, 1);
			tmsg = GetParaString("y");
			if(tmsg != NULL && *tmsg && tmsg[strlen(tmsg)-1] == 'L')
				CheckMenu(ID_LANDSCAPE, 1);

/*			if( g_winData.dviwin.loupe.fShape & F_LCIRCLE )
				CheckMenu(ID_LCIRCLE, 1);
*/			ResizeAllWindows();

			/* 必要ならDVIファイルを開く */
			if( strcmp( g_szFileName, "" ) != 0 )
			{
				PostMessage( g_winData.hMainWnd, WM_USER_FILE_OPEN, 0, 0 );
			}

			break;

		case WM_USER_ALREADY_EXIST:
			hMemFile = OpenFileMapping( FILE_MAP_READ, FALSE, "DVIOUT.TEL" );
			if( hMemFile != NULL )
			{
				LPVOID lpView = MapViewOfFile( hMemFile, 
										FILE_MAP_READ, 0, 0, 0 );
				if( (BYTE*)lpView != NULL )
				{
					i = f_renew;
					f_renew = 0;
					if(IsIconic(g_winData.hMainWnd))
						ShowWindow(g_winData.hMainWnd, SW_RESTORE);
					SetForegroundWindow( g_winData.hMainWnd );
					f_renew = i;
					DefineDVIFileName( lpView );
					UnmapViewOfFile( (LPVOID)lpView );
					CloseHandle( hMemFile );
					PostMessage( g_winData.hMainWnd, WM_USER_FILE_OPEN, 0, 0 );
				}
				else
				{
					MessageBox( g_winData.dviwin.hWnd, 
								"I cannot read memory mapped file.",
								NULL, MB_OK );
					break;
				}
			}
			else
			{
				MessageBox( g_winData.dviwin.hWnd,
							"I cannot open memory mapped file.",
							NULL, MB_OK );
				break;
			}
			break;

		case WM_MOUSEMOVE:
			break;

		case WM_NOTIFY:
			switch( ((LPNMHDR)lParam)->code ) 
			{
				case TTN_NEEDTEXT:		
					// Display the ToolTip text.
					lpToolTipText = (LPTOOLTIPTEXT)lParam;
					i = ChangeToolBar(-1);
					switch(lpToolTipText->hdr.idFrom){
						case ID_FILEOPEN:
							lpToolTipText->lpszText = "Open DVI file";
							break;
						case ID_F_HISTORY:
							lpToolTipText->lpszText = "File History";
							break;
						case ID_PRINT:
							lpToolTipText->lpszText = "Print";
							break;
						case ID_SEARCH:
							lpToolTipText->lpszText = "Search";
							break;
						case ID_PRECAND:
							lpToolTipText->lpszText = "Upward Search";
							break;
						case ID_NEXTCAND:
							lpToolTipText->lpszText = "Downward Search";
							break;
						case ID_MAGNIFY:
							lpToolTipText->lpszText = "Magnify";
							break;
						case ID_REDUCE:
							lpToolTipText->lpszText = "Reduce";
							break;
						case ID_HYPER:
							lpToolTipText->lpszText = 
								(f_hyper & F_H_IGNORE)?
								"source/HyperJump Off -> On":"souce/HyperJump On -> Off";
							break;
						case ID_MHAND:
							lpToolTipText->lpszText = "Cursor";
							break;
						case ID_OPTION:
							lpToolTipText->lpszText = "Change Settings";
							break;

						case ID_BREOPEN:
						case ID_INFO:
							lpToolTipText->lpszText = (i)?
							  (((idx = GetUserKey(1)) != 0)?
								 (((tmsg = GetUserInfo(idx)) != NULL)?
								   tmsg:"User1")
								:"reNew")
							  :"Screen/File info";
							break;

						case ID_BFORMERHIST:
						case ID_INFO_FONT:
							lpToolTipText->lpszText = (i)?
							  (((idx = GetUserKey(2)) != 0)?
								 (((tmsg = GetUserInfo(idx)) != NULL)?
								   tmsg:"User2")
								:"Backward History")
							  :"Font info";
							break;

						case ID_BNEXTHIST:
						case ID_INFO_BUFFER:
							lpToolTipText->lpszText = (i)?
							  (((idx = GetUserKey(3)) != 0)?
								 (((tmsg = GetUserInfo(idx)) != NULL)?
								   tmsg:"User3")
								:"Forward History")
							  :"Buffer info";
							break;

						case ID_BMARKPAGE:
						case ID_INFO_KEY:
							lpToolTipText->lpszText = (i)?
							  (((idx = GetUserKey(4)) != 0)?
								 (((tmsg = GetUserInfo(idx)) != NULL)?
								   tmsg:"User4")
								:"Mark")
							  :"Key info";
							break;

						case ID_BGOMARK:
						case ID_INFO_PARA:
							lpToolTipText->lpszText = (i)?
							  (((idx = GetUserKey(5)) != 0)?
								 (((tmsg = GetUserInfo(idx)) != NULL)?
								   tmsg:"User5")
								:"Goto Mark")
							  :"Parameter info";
							break;

						case ID_ABOUTB:
						case ID_ABOUT:
							lpToolTipText->lpszText = (i)?
							  (((idx = GetUserKey(0)) != 0)?
								 (((tmsg = GetUserInfo(idx)) != NULL)?
								   tmsg:"user")
								:((!exec_dviprt||!*exec_dviprt)?"dvipdfm":"dviprt"))
							  :"About dviout";
							break;
						case ID_NEXTPAGE:
							lpToolTipText->lpszText = f_rev_movebutton?"Previous Page":"Next Page";
							break;
						case ID_PREVPAGE:
							lpToolTipText->lpszText = f_rev_movebutton?"Next Page":"Previous Page";
							break;
						case ID_TOPPAGE:
							lpToolTipText->lpszText = f_rev_movebutton?"Bottom Page":"Top Page";
							break;
						case ID_LASTPAGE:
							lpToolTipText->lpszText = f_rev_movebutton?"Top Page":"Bottom Page";
							break;
						
						default:
							lpToolTipText->lpszText = "";
							break;
					}
					break;
#if	0
				case TBN_QUERYDELETE:
					// Toolbar customization -- can we delete this button?
					return TRUE;

				case TBN_GETBUTTONINFO:
					// The toolbar needs information about a button.
					return FALSE;

				case TBN_QUERYINSERT:
					// Can this button be inserted? Just say yo.
					return TRUE;

				case TBN_CUSTHELP:
					// Need to display custom help.
					MessageBox(hwnd, "We have no help.",NULL, MB_OK);
					break;

				case TBN_TOOLBARCHANGE:
					// Done dragging a bitmap to the toolbar.
					SendMessage(g_winData.toolbar.hWndToolBar, TB_AUTOSIZE, 0L, 0L);
					break;
				default:
					return TRUE;
#endif
			}
			break;

		case WM_DESTROY:
			/* DDE登録の終了処理 */
			DdeNameService( g_ddeData.idInst,
					g_ddeData.hszService1, 0L, DNS_UNREGISTER );
			DdeNameService( g_ddeData.idInst,
					g_ddeData.hszService2, 0L, DNS_UNREGISTER );
			DdeFreeStringHandle( g_ddeData.idInst, g_ddeData.hszService1 );
			DdeFreeStringHandle( g_ddeData.idInst, g_ddeData.hszService2 );
			DdeFreeStringHandle( g_ddeData.idInst, g_ddeData.hszTopic1 );
			DdeFreeStringHandle( g_ddeData.idInst, g_ddeData.hszTopic2 );

			/* we will not reseve current condition if the dviout is 
			  not the first one
			 */
			if(g_winData.szAppName[6] > '0')
				f_quit = 1;

			/* When parent window is destroying, before done,
			   we have to set the position and size of window
			   to the registry. but if we set them though
			   the window are maximized or minimized, we come to
			   cry in next session. because users couldn't restore them
			   if they are not power users. */

			if( !f_quit ){
				if( !IsZoomed( g_winData.hMainWnd ) 
				 && !IsIconic( g_winData.hMainWnd ) )
				{
					GetWindowRect( g_winData.hMainWnd, &rc );
					ReserveInt( "Settings", "xPos", rc.left );
					ReserveInt( "Settings", "yPos", rc.top );
					ReserveInt( "Settings", "Width", rc.right - rc.left );
					ReserveInt( "Settings", "Height", rc.bottom - rc.top );
				}
				ReserveComboList();
			}
			/* Send WM_DESTROY message to DVI-window because we destory 
			our heap, but DVI-window free memories in WM_DESTROY handler.
			I am afraid of making a serious error.
			Please tell me that messages are more early
			child windows or parent window. */
			SendMessage( g_winData.dviwin.hWnd, WM_DESTROY, wParam, lParam );
			
			if( !f_quit )
				ReserveGlobal();
#if 0
			HeapDestroy( g_winData.hHeap ); // ﾌﾟﾗｲﾍﾞｰﾄﾋｰﾌﾟを破棄
#endif
			AllFree();
			PostQuitMessage( 0 );  // WM_QUITをﾎﾟｽﾄする
			return 0;

		case WM_COMMAND:
			if( (HWND)lParam == g_winData.toolbar.hWndPageEdit )
			{
				char szPage[17];
				switch( HIWORD(wParam) )
				{
					case EN_CHANGE:
						/* This message are to be sent when the string in
						   edit box is modified. But if it has keyboard focus
						   we regard user want to continue to input the page
						   number to jump. And edit box will be modified when
						   users operate slider, so I checked the case
						   wheter slider has focus or not.
						   More, that the current page is 0 means no DVI files
						   are shown. In these cases we must not do anything.*/
						if(	 GetFocus() == g_winData.toolbar.hWndPageEdit
						  || GetCurrentPage() == 0 
						  || GetFocus() == g_winData.slider.hWnd ) break;
						GetWindowText( g_winData.toolbar.hWndPageEdit, szPage, 16 );
						topage = atoi( szPage );
						if( topage == 0 || topage > GetTotalPage() )
						{
							wsprintf( szPage, "%d", GetCurrentPage() );
							SetWindowText( g_winData.toolbar.hWndPageEdit, szPage );
						}
						else if(topage != GetCurrentPage())
						{
							SendMessage( g_winData.dviwin.hWnd, WM_USER_NEW_PAGE,
										 (WPARAM)topage, 0 );
						}
						SetFocus( g_winData.dviwin.hWnd );
						break;
					default:
						break;
				}
			}
			else if( (HWND)lParam == g_winData.toolbar.hWndFindCombo )
			{
				switch( HIWORD(wParam) )
				{
					case CBN_EDITCHANGE:
cmb_edit_subclassification:
						if( g_winData.toolbar.hWndEditInCombo == NULL )
						{
							g_winData.toolbar.hWndEditInCombo = GetFocus();
							lpfnDefComboEdit = (CWPROC)GetWindowLong(
									g_winData.toolbar.hWndEditInCombo, GWL_WNDPROC );
							SetWindowLong( g_winData.toolbar.hWndEditInCombo,
									GWL_WNDPROC, (LONG)ComboEditProc );
						}
						if( GetFocus() == g_winData.toolbar.hWndEditInCombo )
						{
							break;
						}
						break;

					case CBN_SELCHANGE:
					case CBN_DBLCLK:
						PostMessage( g_winData.dviwin.hWnd, WM_USER_FINDNEXT, 0, 0 );
						goto cmb_edit_subclassification;
					default:
						break;
				}
			}
			else
				SendMessage( g_winData.dviwin.hWnd, message, wParam, lParam );
			break;

		case WM_SYSCOMMAND:
			switch( wParam ){
			case SC_CLOSE:
				SendMessage( g_winData.hMainWnd, WM_CLOSE, 0, 0 );
				break;
			}
			break;

		case WM_SYSKEYDOWN: // for F10 key.
		case WM_SYSKEYUP:
		case WM_KEYDOWN:
		case WM_CHAR:
		case WM_USER_FILE_OPEN:
		case WM_DROPFILES:
		case WM_PAINT:
			MoveRebar();
			SendMessage( g_winData.dviwin.hWnd, message, wParam, lParam );
			break;

		case WM_ERASEBKGND:
			return TRUE;

		case WM_ACTIVATE:
			switch( LOWORD(wParam) )
			{
				static BOOL f_chk_renew = FALSE;
				case WA_INACTIVE: // our application comes to be inactive.
					i = lstrlen( current_name );
					if( i == 0 ) break;
					wsprintf( szWindowTitle, "%s - %s",
						current_name, g_winData.szWindowTitle );
					wsprintf( szWindowTitle, "%s - %s", current_name_pt, 
						g_winData.szWindowTitle );
					SetWindowText( g_winData.hMainWnd, szWindowTitle );
					/* If we are capturing mouse cursor, release it. */
					if( g_winData.dviwin.bCapture )
					{
						ReleaseCapture();
						g_winData.dviwin.bCapture = FALSE;
					}
					/* If the loupe is shown hide it. */
					if( g_winData.dviwin.loupe.bShown )
					{
						ShowWindow( g_winData.dviwin.loupe.hWnd, SW_HIDE );
						g_winData.dviwin.loupe.bShown = FALSE;
					}
					break;

				case WA_ACTIVE:
				case WA_CLICKACTIVE:
				default: /* our application comes to be active */
					if(f_chk_renew == TRUE)
						break;
					 if( (i = lstrlen(current_name)) != 0 ){
						f_chk_renew = TRUE;
						if(!IsIconic(g_winData.hMainWnd)){
							wsprintf( szWindowTitle, "%s(%d/%d) - %s", 
								current_name,
								GetCurrentPage(), GetTotalPage(),
								g_winData.szWindowTitle );
							SetWindowText( g_winData.hMainWnd, szWindowTitle );
						}
						if(f_renew && CheckRenew(1) == 1){
							id_dvi++;
							PostMessage( g_winData.dviwin.hWnd, WM_COMMAND, 
								MAKEWPARAM(ID_REOPEN,0), 0L );
						}
					}
					f_chk_renew = FALSE;
					break;
			}
// adding part
#if 0
			InvalidateRect( g_winData.dviwin.hWnd, NULL, TRUE ); 
			UpdateWindow( g_winData.dviwin.hWnd );
			UpdateWindow( g_winData.toolbar.hWndToolBar );
			UpdateWindow( g_winData.statusbar.hWnd );
#endif
			break;

		case WM_VSCROLL:
			if( (HWND)lParam != g_winData.slider.hWnd ) break;
			switch( LOWORD(wParam) )
			{
				static WORD precom;
				case TB_TOP:
					topage = 1;
					break;
				case TB_BOTTOM:
					topage = GetTotalPage();
					break;
				case TB_PAGEUP:
				case TB_PAGEDOWN:
					if( precom != 0 )
					{
						SendMessage( g_winData.slider.hWnd, TBM_SETPOS,
							TRUE, GetCurrentPage() );
						return 0;
					}
					precom = 1;
				case TB_LINEUP:
				case TB_LINEDOWN:
				case TB_THUMBPOSITION:
					topage = SendMessage( g_winData.slider.hWnd, 
								TBM_GETPOS, 0, 0 );
					break;
				case TB_THUMBTRACK:
					SetPageView( SendMessage( g_winData.slider.hWnd, 
								 TBM_GETPOS, 0, 0 ) );
					return 0;
				case SB_ENDSCROLL:
					precom = 0;
					return 0;
				default:
					return 0;
			}
			SetFocus( g_winData.dviwin.hWnd );
			if(topage != GetCurrentPage())
			{
#ifdef	DOUBLE_PAGE
				if(IS_2PAGE){
					if(topage == GetCurrentPage() - 1){
						if(topage > 1)
							topage--;
						else if(IS_ODD2EVEN)
							break;
					}else if(topage == GetCurrentPage() + 1){
						if(topage != GetTotalPage())
							topage++;
						else if(((f_2page - topage) & 1) != 0)
							break;
					}
				}
#endif
				SendMessage( g_winData.dviwin.hWnd, WM_USER_NEW_PAGE,
										 (WPARAM)topage, 0 );
			}
			break;

		#ifdef USE_INTELLI_MOUSE
		case WM_MOUSEWHEEL:
			// Caution! The value zDelta is (int)wParam in WM_MOUSEWHEEL
			i = (short)(HIWORD(wParam));
			goto intel_m;
		#endif

		case WM_CLOSE:
			SendMessage( g_winData.dviwin.hWnd, WM_CLOSE, 0, 0);
			DestroyWindow( g_winData.hMainWnd );
			return 0;

		case 0x0319: // Intelli Mouse Explorer.
			SendMessage( g_winData.dviwin.hWnd, message, wParam, lParam );
			break;
		default:
			#ifdef USE_INTELLI_MOUSE
			if( message == uMSH_MOUSEWHEEL )
			{
				// Caution! The value zDelta is (int)wParam in MSH_MOUSEWHEEL
				i = (int)wParam;
intel_m:		if( f_m_down )
					SendMessage( g_winData.dviwin.hWnd, WM_KEYDOWN, 
						( i < 0 )?((f_l_down)?VK_SPACE:VK_NEXT)
								 :((f_l_down)?VK_BACK:VK_PRIOR), 0 );
				else if( GetKeyState( VK_SHIFT ) < 0 ){
					SendMessage( g_winData.dviwin.hWnd, WM_COMMAND,
						( i < 0 )?ID_DOWNPAGE:ID_UPPAGE, 0 );
				}else if( GetKeyState( VK_CONTROL ) < 0 ){
#if	0
					static int w_count;
					if(!(w_count++ & 0x1))
#endif
						SendMessage( g_winData.dviwin.hWnd, WM_COMMAND, 
							( i < 0 )?ID_REDUCE:ID_MAGNIFY, 0);
				}else SendMessage( g_winData.dviwin.hWnd, WM_USER_VSCROLL, -i, 0 );
			}
			#endif
			break;
	}
	return DefWindowProc( hwnd, message, wParam, lParam );
}

LRESULT CALLBACK ComboWndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
{
	switch( message )
	{
		case WM_LBUTTONDOWN:
		case WM_MOUSEMOVE:
		case WM_LBUTTONUP:
		{
			MSG msg;
			HWND hWndTT;
			msg.lParam = lParam;
			msg.wParam = wParam;
			msg.message = message;
			msg.hwnd = hwnd;
			hWndTT = (HWND)SendMessage( g_winData.toolbar.hWndToolBar, TB_GETTOOLTIPS, 0,0 );
			SendMessage( hWndTT, TTM_RELAYEVENT, 0, (LPARAM)(LPMSG)&msg );
			break;
		}
/*
		case WM_MOVE:
			SendMessage( g_winData.toolbar.hWndFindCombo, CB_SHOWDROPDOWN, FALSE, 0 );
			if( g_winData.info.hWnd != NULL )
				SendMessage( g_winData.info.hWnd, WM_SIZE, 0, 0 );
			break;
 */
/*
		case WM_COMMAND:
			if(LOWORD(wParam) == IDOK)
				goto sc;
			break;
 */
		case WM_KEYDOWN:
sc:			if((char)wParam == VK_RETURN)
				SendMessage( g_winData.dviwin.hWnd, WM_USER_FINDNEXT, 0, 0 );
			break;
		default:
			break;
	}
	return CallWindowProc(lpfnDefCombo,hwnd,message,wParam,lParam);
}

LRESULT CALLBACK ComboEditProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
{
	switch( message )
	{
		case WM_LBUTTONDOWN:
			SetFocus( g_winData.toolbar.hWndFindCombo );
		case WM_MOUSEMOVE:
		case WM_LBUTTONUP:
		{
			MSG msg;
			HWND hWndTT;
			msg.lParam = lParam;
			msg.wParam = wParam;
			msg.message = message;
			msg.hwnd = hwnd;
			hWndTT = (HWND)SendMessage( g_winData.toolbar.hWndToolBar, TB_GETTOOLTIPS, 0,0 );
			SendMessage( hWndTT, TTM_RELAYEVENT, 0, (LPARAM)(LPMSG)&msg );
			break;
		}
		case WM_CHAR:
			if(wParam == 0x0d)		// I am not sure why is this nessesary?
				return 0;
			break;
		case WM_LBUTTONDBLCLK:
			goto cmd_find;
		case WM_KEYDOWN:
			switch( wParam )
			{
				case VK_RETURN:
cmd_find:			SendMessage( g_winData.dviwin.hWnd, WM_USER_FINDNEXT, 0, 0 );
					break;
				default:
					break;
			}
		break;
	}
	return CallWindowProc(lpfnDefComboEdit,hwnd,message,wParam,lParam);
}

LRESULT CALLBACK PageEditProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
{
	/* In this function we wait for users' hitting Enter key.
	   While Enter key not hit, users want to edit the number of
	   pages to jump yet.
	   But when Enter key will be hit, I only release keyboard focus
	   from edit box. In main procedure, we have to check the edit
	   box has focus, if true, user will continue to set the number.
	   But else, the number is that user want to jump. */

	switch( message )
	{
		case WM_MOUSEMOVE:
		case WM_LBUTTONDOWN:
		case WM_LBUTTONUP:
		{
			MSG msg;
			HWND hWndTT;
			msg.lParam = lParam;
			msg.wParam = wParam;
			msg.message = message;
			msg.hwnd = hwnd;
			hWndTT = (HWND)SendMessage( g_winData.toolbar.hWndToolBar, TB_GETTOOLTIPS, 0,0 );
			SendMessage( hWndTT, TTM_RELAYEVENT, 0, (LPARAM)(LPMSG)&msg );
			break;
		}
		
		case WM_CHAR:
			if(wParam == 0x0d)	// I am not sure why is this nesessary?
				return 0;
			break;

		case WM_KEYDOWN:
			switch( wParam )
			{
				char szPage[17];
				int topage;
				int mode;
				case VK_RETURN:
					GetWindowText( g_winData.toolbar.hWndPageEdit, szPage, 16 );
					
					/* If szPage starts with `+' or `-' symbol, it means
					   that the number directly specifies the differences
					   of pages between current and to jump. */
					switch( szPage[0] )
					{
						case '+':
							mode = PLUS;
							break;
						case '-':
							mode = MINUS;
							break;
						case '.':
							mode = BOTTOM;
							break;
						default:
							mode = NORMAL;
					}
					/* get the number from szPage. */
					if( mode )
					{
						topage = atoi( szPage + 1 );
					}
					else
					{
						topage = atoi( szPage );
					}
					/* Now we have to calculate topage, because if
					   szPage starts '-' or '+' character it means
					   deffernce of pages but in main routine
					   topage always means the DVI page. */
					switch( mode )
					{
						case PLUS:
							topage += GetCurrentPage();
							break;
						case MINUS:
							topage = GetCurrentPage() - topage;
							break;
						case BOTTOM:
							if( GetKeyState(VK_SHIFT) < 0 
							 || GetKeyState(VK_CONTROL) < 0 ){
								topage = GetMaxNombrePage() - topage;
								goto search_nombre;
							}else
								topage = GetTotalPage() - topage;
							break;
						default:
							/* If SHIFT or CONTROL key was down,
							   topage means nombre.
							   I must modify it to DVI mean. */
							if( GetKeyState(VK_SHIFT) < 0 
							 || GetKeyState(VK_CONTROL) < 0 ){
search_nombre:					if(topage > GetMaxNombrePage())
									topage = GetMaxNombrePage();
								topage = SearchPage(topage, 0);
							}
							break;
					}
					if( topage <= 0 )
						topage = 1;
					if( topage > GetTotalPage() )
						topage = GetTotalPage();
					SetFocus( g_winData.dviwin.hWnd );
					wsprintf( szPage, "%d", topage );
					SetWindowText( g_winData.toolbar.hWndPageEdit, szPage );
					break;
			}
		break;
	}
	return CallWindowProc(lpfnDefEdit, hwnd, message, wParam, lParam);
}

LRESULT CALLBACK PageSpinProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
{
	/* This will be called back from Windows system when some messages will
	   be sent to spin control in toolbar.
	   This proceeds only mouse button messages.
	   If mouse button are down our user will change pages, but
	   when mouse button are up on it, this has probability that
	   mouse was clicked some where else, moved and released here,
	   so users set mouse button down here, I have to set `start changing',
	   and when up, we have to check whether we are in changing mode. */

	static BOOL changing = FALSE;
	switch( message )
	{
		case WM_LBUTTONDOWN:
			if( changing == FALSE )
			{
				changing = TRUE;
				break;
			}
			else
			{
				break;
			}
		case WM_LBUTTONUP:
			if( changing == FALSE ) break;
			if( GetFocus() != g_winData.dviwin.hWnd )
			{
				SetFocus( g_winData.dviwin.hWnd );
				SendMessage( g_winData.toolbar.hWndPageEdit, WM_KEYDOWN,
							(WPARAM)VK_RETURN, 0 );
				changing = FALSE;
				break;
			}

		default:
			break;
	}
	return CallWindowProc(lpfnDefUpDown,hwnd,message,wParam,lParam);
}

void AddStringToCombo( char* szText )
{
	/* This function sets szText to drop down list box contained in
	   combo box. not set it edit box because this function will be
	   called restoring from registry.
	   If you want to set szText to edit box, you have to call
	   SetStringToCombo function. */
	int nIndex;
	if( szText[0] == '\0' ) return;
	nIndex = SendMessage( g_winData.toolbar.hWndFindCombo, CB_FINDSTRINGEXACT,
													-1, (LPARAM)szText );
	if( nIndex != CB_ERR ) /* found same string at nIndex */
	{
		SendMessage( g_winData.toolbar.hWndFindCombo, CB_DELETESTRING,
												nIndex, 0 );
	}
	
	/* If the number of list items is (strictly) larger than 9,
	   because it is too large, delete them.
	   So when returning from this function the max of the count must
	   be less or equal than 10 */
	while( SendMessage( g_winData.toolbar.hWndFindCombo, CB_GETCOUNT, 0, 0 ) > 9 )
	{
		SendMessage( g_winData.toolbar.hWndFindCombo, CB_DELETESTRING, 9, 0 );
	}
	
	/* the length of szText must be less than MAX_FIND_LEN */
	if( lstrlen( szText ) > MAX_FIND_LEN )
		szText[MAX_FIND_LEN] = 0;
	SendMessage( g_winData.toolbar.hWndFindCombo, CB_INSERTSTRING,
												0, (LPARAM)szText );
	return;
}

void SetStringToCombo( char* szText )
{
	/* This function sets szText to edit box in combo box.
	   Not add string to its drop down list box.
	   If you want to add string to it, you have to call
	   AddStringToCombo function.
	   There is no function to do the two operations. */

	/* If szText is NULL string, we have nothing to do. */
	if( szText[0] == '\0' ) return;

	/* Otherwise, we set szText to combo box. */
	SetWindowText( g_winData.toolbar.hWndFindCombo, szText );
	return;
}

void RestoreComboList( void )
{
	/* This function restores strings from registory which must be put
	   in drop down list box, and which must be reserved at the time
	   of out previous section. This restores those and set up drop
	   down list box with them. So you need not call AddStringToCombo[
	   function or else. */

	char szCombo[MAX_FIND_LEN+1];
	int i;
	szCombo[0] = '\0';
	for( i = 9; i >= 0; i-- )
	{
		char num[2];
		wsprintf( num, "%d", i );
		RestoreString( szCombo, MAX_FIND_LEN, "FIND", num, "" );
		if( szCombo[0] != '\0' )
		{
			AddStringToCombo( szCombo );
		}
	}
	return;
}

void ReserveComboList( void )
{
	/* This function reserves strings in drop down list box to the registry.
	   This function never delete string in the registry if the number
	   of string in list box is less than that of registry, because such
	   case will not happen I believe. So if you want to delete some
	   strings from registry, you have to use registry editor. */

	char szCombo[MAX_FIND_LEN+1];
	int c = SendMessage( g_winData.toolbar.hWndFindCombo, CB_GETCOUNT, 0, 0 );
	c--;
	for( ; c >= 0; c-- )
	{
		char num[2];
		wsprintf( num, "%d", c );
		SendMessage( g_winData.toolbar.hWndFindCombo, CB_GETLBTEXT,
									(WPARAM)c, (LPARAM)szCombo );
		ReserveString( "FIND", num, szCombo );
	}
	ReserveInt( "FIND", "flag", GetFindReplaceOption());
	return;
}


void RestoreGlobal( void )
{
	int flag;
	/* If you have no special reason, please restore global variable to
	   registry in this function. */
	RestoreComboList();
	g_winData.dviwin.loupe.CTRL_size_scale = RestoreInt( "Settings", "CTRLoupe", (8<<16)|480 );
	g_winData.statusbar.bShown = RestoreInt( "Settings", "Status", TRUE );
	g_winData.slider.bShown = RestoreInt( "Settings", "PageSlider", TRUE );
	g_winData.dviwin.bScrollBarShown = RestoreInt( "Settings", "ScrollBar", TRUE );
	flag = RestoreInt( "Settings", "ToolBar", TRUE );
	g_winData.toolbar.bShown = (flag & 1)?TRUE:FALSE;
	f_English = (flag & 2)?TRUE:FALSE;
	f_pagebutton = RestoreInt( "Settings", "PageButton", TRUE );
	g_cyShowMessage = RestoreInt( "Settings", "InfWindow", 80 );
	flag = RestoreInt( "Settings", "AmimeCursor", TRUE);
	f_animecursor = (flag&1)?TRUE:FALSE;
	f_directsrc = (flag&2)?TRUE:FALSE;
	g_bCheckColorSpecial = (flag&4)?FALSE:TRUE;
	f_prtlarge = (flag&8)?TRUE:FALSE;
	if(flag&16)
		PostMessage(g_winData.dviwin.hWnd, WM_COMMAND, ID_TIMER, 0L );
	f_gedit = (flag&32)?FALSE:TRUE;
	f_Din = (flag&64)?TRUE:FALSE;
	if(exec_src_sp == NULL){
		RestoreString(common_work, 0xff, "Settings", "src", "");
		if(common_work[0] != 0)
			exec_src_sp = dup_string(common_work);
	}
	if(exec_gsrc_sp == NULL){
		RestoreString(common_work, 0xff, "Settings", "gsrc", "");
		if(common_work[0] != 0)
			exec_gsrc_sp = dup_string(common_work);
	}
	flag = RestoreInt( "Settings", "grid", 0);
	if(flag & 0x80000000 )
		f_gridO = TRUE;
	if(flag)
		f_inch = (flag & 0x40000000)?TRUE:FALSE;
	flag &= 0x3fffffff;
	if(flag >= 200000)
		w_grid = flag;
}

void ReserveGlobal( void )
{
	int flag;
 
	ReserveComboList();
	ReserveInt( "Settings", "LoupeMode", 
			(g_winData.dviwin.loupe.fShape & (0xff|F_LHAND))
		|	(ChangeToolBar(-1)?F_LTOOLBAR:0)
		|	((f_lupdown)?F_LUPDOWN:0)
		|	((g_winData.dviwin.loupe.bKillCursor)?LOUPE_KILL_CURSOR:0)
		|	(g_winData.dviwin.loupe.skip << 16) );
	ReserveInt( "Settings", "LoupeDiam", g_winData.dviwin.loupe.diam );
	ReserveInt( "Settings", "LoupeDiv", g_winData.dviwin.loupe.div );
	ReserveInt( "Settings", "Status", g_winData.statusbar.bShown );
	ReserveInt( "Settings", "PageSlider", g_winData.slider.bShown );
	ReserveInt( "Settings", "ScrollBar", g_winData.dviwin.bScrollBarShown );
	ReserveInt( "Settings", "FlatScrollBar", f_flatscroll );
	ReserveInt( "Settings", "ReverseMove", f_rev_movebutton );
	flag = ((g_winData.toolbar.bShown)?1:0)
		|	((f_English)?2:0);
	ReserveInt( "Settings", "ToolBar", flag );
	ReserveInt( "Settings", "PageButton", f_pagebutton );
	flag =  ((f_animecursor)?1:0)
		|	((f_directsrc)?2:0)
		|	((g_bCheckColorSpecial)?0:4)
		|   ((f_prtlarge)?8:0)
		|   ((f_timer)?16:0)
		|	((f_gedit)?0:32)
		|	((f_Din)?64:0);
	ReserveInt( "Settings", "AmimeCursor", flag);
	ReserveInt( "Settings", "InfWindow", g_cyShowMessage );
	ReserveInt( "Settings", "grid", w_grid|(f_inch?0x4000000:0)|
		(f_gridO?0x80000000:0) );
}

