// DisplayInterfaceDlg.cpp : implementation file
//

#include "stdafx.h"
#include "TypeLibraryBrowser.h"
#include "DisplayInterfaceDlg.h"

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

/////////////////////////////////////////////////////////////////////////////
// CDisplayInterfaceDlg dialog


CDisplayInterfaceDlg::CDisplayInterfaceDlg(CWnd* pParent /*=NULL*/, ITypeInfoPtr pTypeInfo)
	: CDialog(CDisplayInterfaceDlg::IDD, pParent)
{
	m_pTypeInfo = pTypeInfo ;

	//{{AFX_DATA_INIT(CDisplayInterfaceDlg)
	//}}AFX_DATA_INIT
}


void CDisplayInterfaceDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CDisplayInterfaceDlg)
	DDX_Control(pDX, IDC_EDIT5, m_edHelpString);
	DDX_Control(pDX, IDC_LIST2, m_ListParams);
	DDX_Control(pDX, IDC_EDIT4, m_edGUID);
	DDX_Control(pDX, IDC_EDIT1, m_edMemberType);
	DDX_Control(pDX, IDC_LIST1, m_ListMembers);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CDisplayInterfaceDlg, CDialog)
	//{{AFX_MSG_MAP(CDisplayInterfaceDlg)
	ON_LBN_SELCHANGE(IDC_LIST1, OnSelchangeList1)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CDisplayInterfaceDlg message handlers

BOOL CDisplayInterfaceDlg::OnInitDialog() 
{
	USES_CONVERSION ;

	CDialog::OnInitDialog();
	
/*
Get TYPEATTR structure.
*/

	TYPEATTR *pTA ;
	m_pTypeInfo->GetTypeAttr (&pTA) ;

/*
Get GUID of interface from TYPEATTR. Convert to string, place in
edit contol.
*/

	LPOLESTR pstrGuid ;
	StringFromCLSID (pTA->guid, &pstrGuid) ;
	m_edGUID.SetWindowText (W2A(pstrGuid)) ;
	CoTaskMemFree (pstrGuid) ;

/*
Get name of interface, make it the title of the dialog box.
*/

	BSTR InterfaceName ;
	m_pTypeInfo->GetDocumentation (-1, &InterfaceName, NULL, NULL, NULL) ;

	_bstr_t DlgTitle ;
	if (pTA->typekind == TKIND_INTERFACE)
	{
		DlgTitle += "Interface: " ;
	}
	else
	{
		DlgTitle += "Dispinterface: " ;
	}

	DlgTitle += InterfaceName ;
	SetWindowText ((char *) DlgTitle) ;
	SysFreeString (InterfaceName) ;

/*
Get functions and variables.
*/

	int i ;
	FUNCDESC *pFuncDesc ; VARDESC *pVarDesc ;
	BSTR bstrName ;

	for (i = 0 ; i < pTA->cFuncs ; i ++) 
	{
		 m_pTypeInfo->GetFuncDesc(i, &pFuncDesc) ;
		 m_pTypeInfo->GetDocumentation(pFuncDesc->memid, &bstrName, NULL, NULL, NULL);

		 m_ListMembers.AddString (W2A(bstrName)) ;
		 SysFreeString(bstrName);
		 m_pTypeInfo->ReleaseFuncDesc(pFuncDesc);
	}

	for (i = 0 ; i < pTA->cVars ; i ++) 
	{
		 m_pTypeInfo->GetVarDesc(i, &pVarDesc) ;
		 m_pTypeInfo->GetDocumentation(pVarDesc->memid, &bstrName, NULL, NULL, NULL);

		 m_ListMembers.AddString (W2A(bstrName)) ;
		 SysFreeString(bstrName);
		 m_pTypeInfo->ReleaseVarDesc(pVarDesc);
	}

/*
Free TYPEATTR.
*/
	
	m_pTypeInfo->ReleaseTypeAttr (pTA) ;

	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

void CDisplayInterfaceDlg::OnSelchangeList1() 
{
	USES_CONVERSION ;

	MEMBERID memid ;
/*
Get the TYPEATTR structure from the type info
*/
	TYPEATTR *pTA	;
	m_pTypeInfo->GetTypeAttr(&pTA);

	int CurSel = m_ListMembers.GetCurSel ( ) ;

/*
If it's a function, then
*/
	
	if (CurSel < pTA->cFuncs)
	{
		FUNCDESC *pFuncDesc ;
		m_pTypeInfo->GetFuncDesc(CurSel, &pFuncDesc) ;
		memid = pFuncDesc->memid ;
/*
Find the type of function, add to edit control.
*/
		CString invkind ;
		switch (pFuncDesc->invkind)
		{
			case INVOKE_FUNC: invkind += "function"; break ;
			case INVOKE_PROPERTYGET: invkind += "property get fn"; break ; 
			case INVOKE_PROPERTYPUT: invkind += "property put fn"; break ;
			case INVOKE_PROPERTYPUTREF: invkind += "property put ref fn"; break ;
			default: invkind = "(unknown)" ;
		}
		m_edMemberType.SetWindowText (invkind) ;

/*
Now get names and types of function parameters.
*/
		
		m_ListParams.ResetContent( ) ;

/*
if function takes no params, just set VOID into the edit control
*/


		if (pFuncDesc->cParams == 0) 
		{
			m_ListParams.AddString ("(empty)") ;
		}
		
/*
Use the memid of the funcdesc to get the list of names from the TypeInfo. 
Loop through them all to put them in the list box.  Free each when done,
and release the func desc.
*/
/*
Function isn't void.  Get the list of its parameter names.  The function 
name itself is the first name, so a name count > 1 means that the parameters
are named and that their names have been placed in the array after the func
name.  Loop through and put each name in the list box.
*/

		else 
		{
			const unsigned int MAX_NAMES = 40;
			BSTR rgNames[MAX_NAMES];  
			unsigned int cNames;
			int i ;

			m_pTypeInfo->GetNames(pFuncDesc->memid, rgNames, MAX_NAMES, &cNames) ;  
	  
			if (cNames > 1)
		  	{
	  			for(i = 1; i < (int)cNames; i++)
	  			{
/*
Get the type of the name
*/
					CString strParam ;
					TYPEDESC td = ((pFuncDesc->lprgelemdescParam) + (i-1))->tdesc ;
					MyOwnGetVarTypeName (td, &strParam) ;

					_bstr_t name = rgNames [i] ;
					strParam += ": " ;
					strParam += name ;
					m_ListParams.AddString (strParam) ;
					SysFreeString(rgNames[i]);
	  			}
	  		}

			m_pTypeInfo->ReleaseFuncDesc(pFuncDesc);
		}
	}

/*
Otherwise its a variable
*/

	else
	{
	  	VARDESC *pVarDesc ;  CString str ("variable of type: ") ; 
	  	m_pTypeInfo->GetVarDesc((unsigned int)(CurSel - pTA->cFuncs), &pVarDesc);
		memid = pVarDesc->memid ;
	  	TYPEDESC td = (pVarDesc->elemdescVar).tdesc ;
		MyOwnGetVarTypeName (td, &str) ;
		m_edMemberType.SetWindowText (str) ;
		m_pTypeInfo->ReleaseVarDesc (pVarDesc) ;
	}

/*
Display help string.
*/

	BSTR bstrHelpString ;
	m_pTypeInfo->GetDocumentation (memid, NULL, &bstrHelpString, NULL, NULL) ;
	m_edHelpString.SetWindowText (W2A(bstrHelpString)) ;
	SysFreeString (bstrHelpString) ;

/*
Clean up.
*/

	m_pTypeInfo->ReleaseTypeAttr (pTA) ;
}


   
void CDisplayInterfaceDlg::MyOwnGetVarTypeName (TYPEDESC td, CString *pStr)
{

	static char *VarNames[] = {
	"empty",				// 0
    "SQL style Null",               
    "2 byte signed int",             
    "4 byte signed int", 
    "4 byte real",                  
    "8 byte real",                  
    "currency",                    
	"date", 
    "BSTR",               
    "IDispatch",             
	"SCODE",				//10                
    "BOOL",             
    "VARIANT",                
    "IUnknown",
    "decimal",
    "reserved (15)",		// 15         
	"signed char",                  
    "unsigned char",                
    "2 byte unsigned int",  
    "4 byte unsigned int",               
    "signed 64-bit int",             
    "unsigned 64-bit int",          
    "signed machine int",          
    "unsigned machine int",         
    "C style void",                
    "HRESULT",                               
    "pointer type",                  
    "safe array (use VT_ARRAY in VARIANT)",     
    "C style array",                 
    "user defined type",  	       
    "null terminated string", 
    "null terminated wide string"  } ;

	if (td.vt & VT_BYREF)
	{
		*pStr += "pointer to " ;
	}
	else if (td.vt & VT_ARRAY)
	{
		CString arr ;
		arr.Format ("array [%d] of ", td.lpadesc->cDims) ;
		*pStr += arr ;
	}

	*pStr += VarNames [td.vt] ;
}

