// WgnuplotCtl.cpp : Implementation of the CWgnuplotCtrl ActiveX Control class.

#include "stdafx.h"
#include "wgnuplot.h"
#include "WgnuplotCtl.h"
#include "WgnuplotPpg.h"

#include "src/plot.h"
#include "src/term_api.h"
#include "src\plot.h"
#include "src\util.h"
#include "src\win\wgnuplib.h"
#include "src\win\wgnuplib.h"
#include "src\term_api.h"
#include "src\getcolor.h"
#include "src\datafile.h"
#include "src\misc.h"
#include "src\fit.h"
#include "src\setshow.h"
#include "src\win\wgnuplib.h"
#include "src\win\wcommon.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define WIN_XMAX (24000)
#define WIN_YMAX (18000)
#define WIN_HCHAR (WIN_XMAX/75)
#define WIN_VCHAR (WIN_YMAX/25)
#define WIN_HTIC (WIN_XMAX/160)
#define WIN_VTIC WIN_HTIC


IMPLEMENT_DYNCREATE(CWgnuplotCtrl, COleControl)


/////////////////////////////////////////////////////////////////////////////
// Message map

BEGIN_MESSAGE_MAP(CWgnuplotCtrl, COleControl)
	//{{AFX_MSG_MAP(CWgnuplotCtrl)
	ON_WM_CREATE()
	ON_WM_SIZE()
	//}}AFX_MSG_MAP
	ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties)
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// Dispatch map

BEGIN_DISPATCH_MAP(CWgnuplotCtrl, COleControl)
	//{{AFX_DISPATCH_MAP(CWgnuplotCtrl)
	DISP_FUNCTION(CWgnuplotCtrl, "Open", Open, VT_BOOL, VTS_BSTR)
	//}}AFX_DISPATCH_MAP
	DISP_FUNCTION_ID(CWgnuplotCtrl, "AboutBox", DISPID_ABOUTBOX, AboutBox, VT_EMPTY, VTS_NONE)
END_DISPATCH_MAP()


/////////////////////////////////////////////////////////////////////////////
// Event map

BEGIN_EVENT_MAP(CWgnuplotCtrl, COleControl)
	//{{AFX_EVENT_MAP(CWgnuplotCtrl)
	// NOTE - ClassWizard will add and remove event map entries
	//    DO NOT EDIT what you see in these blocks of generated code !
	//}}AFX_EVENT_MAP
END_EVENT_MAP()


/////////////////////////////////////////////////////////////////////////////
// Property pages

// TODO: Add more property pages as needed.  Remember to increase the count!
BEGIN_PROPPAGEIDS(CWgnuplotCtrl, 1)
	PROPPAGEID(CWgnuplotPropPage::guid)
END_PROPPAGEIDS(CWgnuplotCtrl)


/////////////////////////////////////////////////////////////////////////////
// Initialize class factory and guid

IMPLEMENT_OLECREATE_EX(CWgnuplotCtrl, "WGNUPLOT.WgnuplotCtrl.1",
	0xd39ed769, 0x633a, 0x436d, 0xaa, 0x92, 0x34, 0x2a, 0x55, 0x24, 0x56, 0xa5)


/////////////////////////////////////////////////////////////////////////////
// Type library ID and version

IMPLEMENT_OLETYPELIB(CWgnuplotCtrl, _tlid, _wVerMajor, _wVerMinor)


/////////////////////////////////////////////////////////////////////////////
// Interface IDs

const IID BASED_CODE IID_DWgnuplot =
		{ 0x3dd8ef3f, 0xb15d, 0x42cb, { 0x82, 0x68, 0xb5, 0xc4, 0xb4, 0x92, 0x1f, 0x40 } };
const IID BASED_CODE IID_DWgnuplotEvents =
		{ 0x4d379176, 0x91a4, 0x4816, { 0xa7, 0xab, 0x8e, 0x8e, 0xd0, 0xc6, 0xa0, 0x8e } };


/////////////////////////////////////////////////////////////////////////////
// Control type information

static const DWORD BASED_CODE _dwWgnuplotOleMisc =
	OLEMISC_ACTIVATEWHENVISIBLE |
	OLEMISC_SETCLIENTSITEFIRST |
	OLEMISC_INSIDEOUT |
	OLEMISC_CANTLINKINSIDE |
	OLEMISC_RECOMPOSEONRESIZE;

IMPLEMENT_OLECTLTYPE(CWgnuplotCtrl, IDS_WGNUPLOT, _dwWgnuplotOleMisc)


/////////////////////////////////////////////////////////////////////////////
// CWgnuplotCtrl::CWgnuplotCtrlFactory::UpdateRegistry -
// Adds or removes system registry entries for CWgnuplotCtrl

BOOL CWgnuplotCtrl::CWgnuplotCtrlFactory::UpdateRegistry(BOOL bRegister)
{
	// TODO: Verify that your control follows apartment-model threading rules.
	// Refer to MFC TechNote 64 for more information.
	// If your control does not conform to the apartment-model rules, then
	// you must modify the code below, changing the 6th parameter from
	// afxRegApartmentThreading to 0.

	if (bRegister)
		return AfxOleRegisterControlClass(
			AfxGetInstanceHandle(),
			m_clsid,
			m_lpszProgID,
			IDS_WGNUPLOT,
			IDB_WGNUPLOT,
			afxRegApartmentThreading,
			_dwWgnuplotOleMisc,
			_tlid,
			_wVerMajor,
			_wVerMinor);
	else
		return AfxOleUnregisterClass(m_clsid, m_lpszProgID);
}

static CWgnuplotCtrl* __instance__=NULL;
extern TW textwin;

/////////////////////////////////////////////////////////////////////////////
// CWgnuplotCtrl::CWgnuplotCtrl - Constructor

CWgnuplotCtrl::CWgnuplotCtrl()
{
	InitializeIIDs(&IID_DWgnuplot, &IID_DWgnuplotEvents);

	// TODO: Initialize your control's instance data here.
	TextInit(&textwin);
	init_memory();
	init_terminal();
	update_gpval_variables(3);
	reset_command();
	init_color();  /*  Initialization of color  */
	///load_rcfile();
	init_fit();

	__instance__ = this;
}


/////////////////////////////////////////////////////////////////////////////
// CWgnuplotCtrl::~CWgnuplotCtrl - Destructor

CWgnuplotCtrl::~CWgnuplotCtrl()
{
	// TODO: Cleanup your control's instance data here.
}


/////////////////////////////////////////////////////////////////////////////
// CWgnuplotCtrl::OnDraw - Drawing function

void CWgnuplotCtrl::OnDraw(
			CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
{
	// TODO: Replace the following code with your own drawing code.
	pdc->FillRect(rcBounds, CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));
}


/////////////////////////////////////////////////////////////////////////////
// CWgnuplotCtrl::DoPropExchange - Persistence support

void CWgnuplotCtrl::DoPropExchange(CPropExchange* pPX)
{
	ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
	COleControl::DoPropExchange(pPX);

	// TODO: Call PX_ functions for each persistent custom property.

}


/////////////////////////////////////////////////////////////////////////////
// CWgnuplotCtrl::OnResetState - Reset control to default state

void CWgnuplotCtrl::OnResetState()
{
	COleControl::OnResetState();  // Resets defaults found in DoPropExchange

	// TODO: Reset any other control state here.
}

/////////////////////////////////////////////////////////////////////////////
// CWgnuplotCtrl::AboutBox - Display an "About" box to the user

void CWgnuplotCtrl::AboutBox()
{
	CDialog dlgAbout(IDD_ABOUTBOX_WGNUPLOT);
	dlgAbout.DoModal();
}

extern GW graphwin;
extern int WIN_last_linetype;
void WIN_graphics();
/////////////////////////////////////////////////////////////////////////////
// CWgnuplotCtrl message handlers
int CWgnuplotCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (COleControl::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	char szModuleName[ MAX_PATH ] = {'\0' ,};	
	
	GetModuleFileName(NULL , (LPSTR) szModuleName, MAX_PATH);
	
	get_user_env(); /* this hasn't been called yet */
	//m_pIniFilePath = gp_strdup("~\\wgnuplot.ini");
	//gp_expand_tilde(&(m_pIniFilePath));
	
	/* if tilde expansion fails use current directory as
	default - that was the previous default behaviour */
	//if ('~' == m_pIniFilePath[0]) 
	//{
	//	free(m_pIniFilePath);
	//	m_pIniFilePath = "wgnuplot.ini";
	//}

	graphwin.hParent = m_hWnd;
	
	Open( "D:\\프로젝트\\코디마\\데이터\\plot.wplt" );

	return 0;
}

/**	\brief	컨트롤의 크기가 변경될때마다 그래프 윈도우의 크기도 같이 변경시킨다.

	\param	nType	a parameter of type UINT
	\param	cx	a parameter of type int
	\param	cy	a parameter of type int

	\return	void	
*/
void CWgnuplotCtrl::OnSize(UINT nType, int cx, int cy) 
{
	COleControl::OnSize(nType, cx, cy);

	if( graphwin.hWndGraph )
	{
		::SetWindowPos( graphwin.hWndGraph , NULL , 0 , 0 , cx , cy , SWP_NOACTIVATE | SWP_NOZORDER );
	}
	/*
	if( m_graphWnd.GetSafeHwnd() )
	{
		m_graphWnd.SetWindowPos( NULL , 0 , 0 , cx , cy , SWP_NOACTIVATE | SWP_NOZORDER );
	}
	*/
}

/**	\brief	주어진 파일을 파싱하여 그래프를 그린다.

	\param	pszFilePath	a parameter of type LPCTSTR

	\return	BOOL	
*/
BOOL CWgnuplotCtrl::Open(LPCTSTR pszFilePath) 
{
	assert( pszFilePath && "pszFilePath is NULL");

	// TODO: Add your dispatch handler code here
	if( pszFilePath )
	{
		FILE *fp = fopen( pszFilePath , "r" );
		if( fp )
		{
			load_file( fp , (char *)pszFilePath  , FALSE);
			fclose( fp );
		}
	}

	return TRUE;
}

LRESULT CALLBACK WINEXPORT WndGraphProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);

LPSTR szGraphClass = "wgnuplot_graph";

/**	\brief	그래프 윈도우를 생성한다.

	\param	lpgw	a parameter of type LPGW

	\return	void	
*/
void CWgnuplotCtrl::GraphInit(LPGW lpgw)
{
	HMENU sysmenu;
	WNDCLASS wndclass;
	char buf[80];
	
	if (!lpgw->hPrevInstance) 
	{
		wndclass.style = CS_HREDRAW | CS_VREDRAW;
		wndclass.lpfnWndProc = WndGraphProc;
		wndclass.cbClsExtra = 0;
		wndclass.cbWndExtra = 2 * sizeof(void FAR *);
		wndclass.hInstance = lpgw->hInstance;
		wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
		wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
		wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
		wndclass.lpszMenuName = NULL;
		wndclass.lpszClassName = szGraphClass;
		RegisterClass(&wndclass);
	}
	
	ReadGraphIni(lpgw);
	
	if( NULL == lpgw->hWndGraph )
	{
		/*
		CRect rect;
		rect.left  = lpgw->Origin.x;
		rect.top   = lpgw->Origin.y;
		rect.right = rect.left + lpgw->Size.x;
		rect.bottom= rect.top + lpgw->Size.y;
		if( m_graphWnd.Create(szGraphClass, lpgw->Title, WS_CHILD | WS_VISIBLE | WS_BORDER , rect , this , 0x100) )
		{
			lpgw->hWndGraph = m_graphWnd.m_hWnd;
		}
		*/
		
		lpgw->hWndGraph = CreateWindow(szGraphClass, lpgw->Title,
			///WS_OVERLAPPEDWINDOW , 
			WS_CHILD | WS_VISIBLE ,
			lpgw->Origin.x, lpgw->Origin.y,
			lpgw->Size.x, lpgw->Size.y,
			graphwin.hParent , NULL, lpgw->hInstance, lpgw);
	}
	if( lpgw->hWndGraph ) ::ShowWindow(lpgw->hWndGraph, SW_SHOWNORMAL);

	/*
	lpgw->hPopMenu = CreatePopupMenu();
	AppendMenu(lpgw->hPopMenu, MF_STRING | (lpgw->graphtotop ? MF_CHECKED : MF_UNCHECKED),
	M_GRAPH_TO_TOP, "Bring to &Top");
	AppendMenu(lpgw->hPopMenu, MF_STRING | (lpgw->color ? MF_CHECKED : MF_UNCHECKED),
	M_COLOR, "C&olor");
	AppendMenu(lpgw->hPopMenu, MF_STRING, M_COPY_CLIP, "&Copy to Clipboard");
	#if WINVER >= 0x030a
	AppendMenu(lpgw->hPopMenu, MF_STRING, M_BACKGROUND, "&Background...");
	AppendMenu(lpgw->hPopMenu, MF_STRING, M_CHOOSE_FONT, "Choose &Font...");
	AppendMenu(lpgw->hPopMenu, MF_STRING, M_LINESTYLE, "&Line Styles...");
	#endif
	AppendMenu(lpgw->hPopMenu, MF_STRING, M_PRINT, "&Print...");
	if (lpgw->IniFile != (LPSTR)NULL) {
	wsprintf(buf,"&Update %s",lpgw->IniFile);
	AppendMenu(lpgw->hPopMenu, MF_STRING, M_WRITEINI, (LPSTR)buf);
	}
	
	  /// modify the system menu to have the new items we want
	  sysmenu = GetSystemMenu(lpgw->hWndGraph,0);
	  AppendMenu(sysmenu, MF_SEPARATOR, 0, NULL);
	  AppendMenu(sysmenu, MF_POPUP, (UINT)lpgw->hPopMenu, "&Options");
	  AppendMenu(sysmenu, MF_STRING, M_ABOUT, "&About");
	  
	    if (!IsWindowVisible(lpgw->lptw->hWndParent)) 
	    {
	    AppendMenu(sysmenu, MF_SEPARATOR, 0, NULL);
	    AppendMenu(sysmenu, MF_STRING, M_COMMANDLINE, "C&ommand Line");
	    }
	*/
}

/**	\brief	The CWgnuplotCtrl::GetInstance function


	\return	CWgnuplotCtrl*	
*/
CWgnuplotCtrl* CWgnuplotCtrl::GetInstance()
{
	return __instance__;
}

/**	\brief	ini 파일을 읽는다.

	\param	lpgw	a parameter of type LPGW

	\return	void	
*/
void CWgnuplotCtrl::ReadGraphIni(LPGW lpgw)
{
	assert( lpgw && "lpgw is NULL" );
	if( lpgw )
	{
		LPSTR file = lpgw->IniFile;
		LPSTR section = lpgw->IniSection;
		char profile[81];
		char entry[32];
		LPSTR p;
		int i,r,g,b,colorstyle,monostyle;
		COLORREF ref;
		BOOL bOKINI;
		
		bOKINI = (file != (LPSTR)NULL) && (section != (LPSTR)NULL);
		if (!bOKINI)
			profile[0] = '\0';
		
		if (bOKINI)
			GetPrivateProfileString(section, "GraphOrigin", "", profile, 80, file);
		if ( (p = GetInt(profile, (LPINT)&lpgw->Origin.x)) == NULL)
			lpgw->Origin.x = CW_USEDEFAULT;
		if ( (p = GetInt(p, (LPINT)&lpgw->Origin.y)) == NULL)
			lpgw->Origin.y = CW_USEDEFAULT;
		if (bOKINI)
			GetPrivateProfileString(section, "GraphSize", "", profile, 80, file);
		if ( (p = GetInt(profile, (LPINT)&lpgw->Size.x)) == NULL)
			lpgw->Size.x = CW_USEDEFAULT;
		if ( (p = GetInt(p, (LPINT)&lpgw->Size.y)) == NULL)
			lpgw->Size.y = CW_USEDEFAULT;
		
		if (bOKINI)
			GetPrivateProfileString(section, "GraphFont", "", profile, 80, file);
		{
			char FAR *size;
			size = strchr(profile,',');
			if (size)
			{
				*size++ = '\0';
				if ( (p = GetInt(size, (LPINT)&lpgw->fontsize)) == NULL)
					lpgw->fontsize = WINFONTSIZE;
			}
			strcpy(lpgw->fontname, profile);
			if (lpgw->fontsize == 0)
				lpgw->fontsize = WINFONTSIZE;
			if (!(*lpgw->fontname)) 
			{
				if (LOWORD(GetVersion()) == 3)
					strcpy(lpgw->fontname,WIN30FONT);
				else
					strcpy(lpgw->fontname,WINFONT);
			}
			/* set current font as default font */
			strcpy(lpgw->deffontname, lpgw->fontname);
			lpgw->deffontsize = lpgw->fontsize;
		}
		
		if (bOKINI)
			GetPrivateProfileString(section, "GraphColor", "", profile, 80, file);
		if ( (p = GetInt(profile, (LPINT)&lpgw->color)) == NULL)
			lpgw->color = TRUE;
		
		if (bOKINI)
			GetPrivateProfileString(section, "GraphToTop", "", profile, 80, file);
		if ( (p = GetInt(profile, (LPINT)&lpgw->graphtotop)) == NULL)
			lpgw->graphtotop = TRUE;
		
		lpgw->background = RGB(255,255,255);
		if (bOKINI)
			GetPrivateProfileString(section, "GraphBackground", "", profile, 80, file);
		if ( ((p = GetInt(profile, (LPINT)&r)) != NULL) &&
			((p = GetInt(p, (LPINT)&g)) != NULL) &&
			((p = GetInt(p, (LPINT)&b)) != NULL) )
			lpgw->background = RGB(r,g,b);
		
		StorePen(lpgw, 0,RGB(0,0,0),PS_SOLID,PS_SOLID);
		if (bOKINI)
			GetPrivateProfileString(section, "Border", "", profile, 80, file);
		if ( ((p = GetInt(profile, (LPINT)&r)) != NULL) &&
			((p = GetInt(p, (LPINT)&g)) != NULL) &&
			((p = GetInt(p, (LPINT)&b)) != NULL) &&
			((p = GetInt(p, (LPINT)&colorstyle)) != NULL) &&
			((p = GetInt(p, (LPINT)&monostyle)) != NULL) )
			StorePen(lpgw,0,RGB(r,g,b),colorstyle,monostyle);
		
		StorePen(lpgw, 1,RGB(192,192,192),PS_DOT,PS_DOT);
		if (bOKINI)
			GetPrivateProfileString(section, "Axis", "", profile, 80, file);
		if ( ((p = GetInt(profile, (LPINT)&r)) != NULL) &&
			((p = GetInt(p, (LPINT)&g)) != NULL) &&
			((p = GetInt(p, (LPINT)&b)) != NULL) &&
			((p = GetInt(p, (LPINT)&colorstyle)) != NULL) &&
			((p = GetInt(p, (LPINT)&monostyle)) != NULL) )
			StorePen(lpgw,1,RGB(r,g,b),colorstyle,monostyle);
		
		for (i=0; i<WGNUMPENS; i++)
		{
			ref = wginitcolor[ i%WGDEFCOLOR ];
			colorstyle = wginitstyle[ (i/WGDEFCOLOR) % WGDEFSTYLE ];
			monostyle  = wginitstyle[ i%WGDEFSTYLE ];
			StorePen(lpgw, i+2,ref,colorstyle,monostyle);
			wsprintf(entry,"Line%d",i+1);
			if (bOKINI)
				GetPrivateProfileString(section, entry, "", profile, 80, file);
			if ( ((p = GetInt(profile, (LPINT)&r)) != NULL) &&
				((p = GetInt(p, (LPINT)&g)) != NULL) &&
				((p = GetInt(p, (LPINT)&b)) != NULL) &&
				((p = GetInt(p, (LPINT)&colorstyle)) != NULL) &&
				((p = GetInt(p, (LPINT)&monostyle)) != NULL) )
				StorePen(lpgw,i+2,RGB(r,g,b),colorstyle,monostyle);
		}
	}
}

/* Helper functions for bookkeeping of pens, brushes and fonts */

/* Set up LOGPEN structures based on information coming from wgnuplot.ini, via
 * ReadGraphIni() 
 */
void CWgnuplotCtrl::StorePen(LPGW lpgw, int i, COLORREF ref, int colorstyle, int monostyle)
{
	LOGPEN FAR *plp;
	
	plp = &lpgw->colorpen[i];
	plp->lopnColor = ref;
	if (colorstyle < 0) 
	{
		plp->lopnWidth.x = -colorstyle;
		plp->lopnStyle = 0;
	} 
	else 
	{
		plp->lopnWidth.x = 1;
		plp->lopnStyle = colorstyle % 5;
	}
	plp->lopnWidth.y = 0;
	
	plp = &lpgw->monopen[i];
	plp->lopnColor = RGB(0,0,0);
	if (monostyle < 0) 
	{
		plp->lopnWidth.x = -monostyle;
		plp->lopnStyle = 0;
	} 
	else 
	{
		plp->lopnWidth.x = 1;
		plp->lopnStyle = monostyle % 5;
	}
	plp->lopnWidth.y = 0;
}
