#include <windows.h>
#include "typbrows.h"
#include "resource.h"

void InitTypeInfo (LPTYPEINFO pTypeInfo, HWND hParent)
{
	MEMBERID memid;
	BSTR bstrName;
	unsigned int i;
	FUNCDESC FAR *pfuncdesc;
	VARDESC  FAR *pvardesc;
	TCHAR out [256], *pStr ;
	HRESULT hr ;

/*
STEP 8
Get a TYPEATTR structure describing this type via the method 
ITypeInfo::GetTypeAttr( ).  Store a pointer to the TYPEATTR structure in 
the variable pTypeAttr.   
*/
	TYPEATTR *pTypeAttr	;


/*
Get the GUID from the attributes and set it into its edit control
*/

	hr = StringFromCLSID(pTypeAttr->guid, &pStr);
	SetDlgItemText(hParent, IDC_GUID, pStr) ;
	SysFreeString (pStr) ;

/*
Same for the locale
*/

	wsprintf (out, TEXT("0x%x"), pTypeAttr->lcid) ;
	SetDlgItemText (hParent, IDC_LOCALE, out) ;
/*
Do the same for the version
*/
	wsprintf(out, TEXT("%u.%02u"),pTypeAttr->wMajorVerNum, pTypeAttr->wMinorVerNum);
	SetDlgItemText (hParent,IDC_VERSION, out);
	
/*
STEP 9
For each function in the TYPEATTR, get its description in a FUNCDESC.  
Use the member id from the funcdesc to get the function's name from the 
TypeInfo via the method GetDocumentation( ). The placement of the name 
into the text control has been done for you. Finally release the string 
and the funcdesc.
*/
	for(i = 0; i < pTypeAttr->cFuncs; i++)
	{

	  SendDlgItemMessage (hParent, IDC_LIST1, LB_ADDSTRING, 0, (LPARAM)bstrName);
	  SysFreeString(bstrName);
	}
          
/*
STEP 9
For each variable in the TYPEATTR, get its description in a VARDESC.  Use
the member ID from the vardesc to get the variable's name from the TypeInfo.
Place the name into the list box, then release the string and the vardesc.
*/
      
	for(i = 0; i < pTypeAttr->cVars; i++)
	{
	  SendDlgItemMessage (hParent, IDC_LIST1, LB_ADDSTRING, 0, (LPARAM)bstrName);
	  SysFreeString(bstrName);
	}


/*
STEP 8 Continued
Release the type attr
*/

}

void SetSelectedMember(LPTYPEINFO pTypeInfo, DWORD index, HWND hParent)
{
	MEMBERID memid;
	TCHAR out [256], *psz ;
	BSTR bstrDoc, bstrHelpFile ;
	DWORD dwHelpContext ;



/*
Get the TYPEATTR structure from the type info
*/
	TYPEATTR *pTypeAttr	;

	pTypeInfo->GetTypeAttr(&pTypeAttr);

	
/* 
if this is a function, fill the param list, otherwise just fill in the 
item info.
*/  

	if(index < pTypeAttr->cFuncs)
	{
	  int i;
	  unsigned int cNames;
	  FUNCDESC *pfuncdesc;
	  const unsigned int MAX_NAMES = 40;
	  BSTR rgNames[MAX_NAMES];  

    
/*
Get the funcdesc of the function.
*/
    
		pTypeInfo->GetFuncDesc((unsigned int) index, &pfuncdesc) ;
		memid = pfuncdesc->memid;

/*
Get the documentation from the type info, place into text controls
*/
  		pTypeInfo->GetDocumentation(pfuncdesc->memid, 
  			NULL, &bstrDoc, &dwHelpContext, &bstrHelpFile);

		wsprintf(out, TEXT("%ld"), dwHelpContext);
		SetDlgItemText (hParent,IDC_HELPCONTEXT, out);

		psz = (bstrDoc != NULL) ? bstrDoc : TEXT("<none>");
		SetDlgItemText (hParent,IDC_HELPSTRING, psz);
		if (bstrDoc) SysFreeString (bstrDoc) ;
		
		psz = (bstrHelpFile != NULL) ? bstrHelpFile : TEXT("<none>") ;
		SetDlgItemText (hParent, IDC_HELPFILE, psz) ;
		if (bstrHelpFile) SysFreeString (bstrHelpFile) ;

		wsprintf (out, TEXT("0x%x"), pfuncdesc->memid) ;
		SetDlgItemText (hParent, IDC_MEMID, out) ;
/*
Get the type of the function, set name into edit control
*/
		GetFuncTypeName (pfuncdesc->invkind, out, sizeof(out));
		SetDlgItemText (hParent, IDC_FUNCTYPE, out) ;
/*
Do the same for the return type
*/

		GetVarTypeName (pfuncdesc->elemdescFunc.tdesc, out) ;
		SetDlgItemText (hParent, IDC_RETURNTYPE, out) ;
/*
if function takes no params, just set VOID into the edit control
*/


		if (pfuncdesc->cParams == 0) 
		{
			SendDlgItemMessage(hParent, IDC_LIST2, LB_ADDSTRING, 0, (LPARAM)TEXT("[void]")) ;
		}
		
/*
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 
		{
			pTypeInfo->GetNames(memid, rgNames, MAX_NAMES, &cNames) ;  
	  
			if (cNames > 1)
		  	{
	  			for(i = 1; i < (int)cNames; i++)
	  			{
					SendDlgItemMessage(hParent, IDC_LIST2, LB_ADDSTRING, 0, (LPARAM)rgNames[i]);
					SysFreeString(rgNames[i]);
	  			}
	  		}
/*
Parameters aren't named.  Get their types from the FUNCDESC, get the 
name strings describing their types from our utility function.  Put
into list box. 
*/

			else
	  		{                 
	  			TCHAR type [128] ;
	  		
				for (i = 0 ; i < pfuncdesc->cParams; i++)
				{   
					TYPEDESC td = ((pfuncdesc->lprgelemdescParam) + i)->tdesc ;
					GetVarTypeName (td, out) ;
					wsprintf (type, TEXT("[%s]"), out) ;
					SendDlgItemMessage(hParent, IDC_LIST2, LB_ADDSTRING, 0, (LPARAM)type);
				}
	  		}
	  	}
	  	//SysFreeString(rgNames[0]);   
	  
		pTypeInfo->ReleaseFuncDesc(pfuncdesc);
	}    
/*
Otherwise it's a variable, get its memid.  Get its type from the VARDESC,
get the name corresponding to this type from our utility function,
and put it in the list box
*/
	
	else
	{
	  	VARDESC FAR *pvardesc;
        TCHAR type [128] ;
        
	  	pTypeInfo->GetVarDesc(
		  (unsigned int)(index - pTypeAttr->cFuncs), &pvardesc);
	  	memid = pvardesc->memid;
	  
	  	TYPEDESC td = (pvardesc->elemdescVar).tdesc ;
		GetVarTypeName (td, out) ;
		wsprintf (type, TEXT("[%s]"), out) ;
		SendDlgItemMessage(hParent, IDC_LIST2, LB_ADDSTRING, 0, (LPARAM)type);
	
	  	SetDlgItemText (hParent, IDC_FUNCTYPE, (LPTSTR)TEXT("Variable")) ;

/*
Get the documentation from the type info, place into text controls
*/
  		pTypeInfo->GetDocumentation(memid, 
  			NULL, &bstrDoc, &dwHelpContext, &bstrHelpFile);

		wsprintf(out, TEXT("%ld"), dwHelpContext);
		SetDlgItemText (hParent,IDC_HELPCONTEXT, out);

		psz = (bstrDoc != NULL) ? bstrDoc : TEXT("<none>");
		SetDlgItemText (hParent,IDC_HELPSTRING, psz);
		if (bstrDoc) SysFreeString (bstrDoc) ;
		
		psz = (bstrHelpFile != NULL) ? bstrHelpFile : TEXT("<none>") ;
		SetDlgItemText (hParent, IDC_HELPFILE, psz) ;
		if (bstrHelpFile) SysFreeString (bstrHelpFile) ;

		wsprintf (out, TEXT("0x%x"), memid) ;
		SetDlgItemText (hParent, IDC_MEMID, out) ;

		SetDlgItemText (hParent, IDC_RETURNTYPE, TEXT("<none>")) ;


	  	pTypeInfo->ReleaseVarDesc(pvardesc); 
	}
/*
Release the type attr
*/
	pTypeInfo->ReleaseTypeAttr (pTypeAttr) ;

}


void SetSelectedParameter(LPTYPEINFO pTypeInfo, DWORD dwFuncIndex, DWORD dwParamIndex, 
	HWND hParent)
{

	TCHAR out [256] ;

/*
Get the TYPEATTR structure from the type info
*/
	TYPEATTR *pTypeAttr	;

	pTypeInfo->GetTypeAttr(&pTypeAttr);

	if(dwFuncIndex < pTypeAttr->cFuncs)
	{
	  	FUNCDESC *pfuncdesc;

    
/*
Get the funcdesc of the function.
*/
    
		pTypeInfo->GetFuncDesc((unsigned int) dwFuncIndex, &pfuncdesc) ;

/*
If no params, just put void into text control
*/

		if (pfuncdesc->cParams == 0) 
		{
			SetDlgItemText (hParent, IDC_PARAMTYPE, TEXT("[void]")) ;
		}
		else
		{
/*
Otherwise, get the type of the specified paramter and place into the text
control
*/
			TYPEDESC td = ((pfuncdesc->lprgelemdescParam) + dwParamIndex)->tdesc ;
			GetVarTypeName (td, out) ;
			SetDlgItemText (hParent, IDC_PARAMTYPE, out );
	  	}
	  
		pTypeInfo->ReleaseFuncDesc(pfuncdesc);

	}
	else
	{
		MessageBeep (0) ;
	}
/*
Release the type attr
*/
	pTypeInfo->ReleaseTypeAttr (pTypeAttr) ;
}
