/********************************************************************************************
	Clean OS Windows library module version 1.2.1.
	This module is part of the Clean Object I/O library, version 1.2.1, 
	for the Windows platform.
********************************************************************************************/

/********************************************************************************************
	About this module:
	Routines related to standard file selector dialogues.
********************************************************************************************/
#include "cCrossCallFileSelectors_121.h"
#include "util_121.h"
#include "cCrossCall_121.h"

static UINT APIENTRY FileSelectorHook (HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
	if (uiMsg == WM_INITDIALOG)
	{
		RECT	rect;
		int		x, y;
		GetWindowRect (hdlg, &rect);
		
		x	= (GetSystemMetrics (SM_CXSCREEN)>>1) - ((rect.right-rect.left)>>1);
		y	= (GetSystemMetrics (SM_CYSCREEN)>>1) - ((rect.bottom-rect.top)>>1);
		SetWindowPos (hdlg, NULL, x, y, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
	}

	return 0;
}


/*	Cross call procedure implementations.
	Eval<nr> corresponds with a CrossCallEntry generated by NewCrossCallEntry (nr,Eval<nr>).
*/
/*	Create the specialised directory selector dialog from Windows.
	By courtesy of Martijn Vervoort.
*/
void EvalCcRqDIRECTORYDIALOG (CrossCallInfo *pcci)		/* no params;  bool, textptr result; */
{
	char buffer[MAX_PATH];
	LPITEMIDLIST pidlReturn;
	BROWSEINFO bi;
	char *s;
	char title[17] = "Select Directory\0";

	bi.hwndOwner      = GetActiveWindow ();
	bi.pidlRoot       = NULL;
	bi.pszDisplayName = buffer;
	bi.lpszTitle      = title;
	bi.ulFlags        = BIF_RETURNONLYFSDIRS;
	bi.lpfn           = NULL;
	bi.lParam         = 0;

	CoInitialize (NULL);		// Initialise the COM library; must be balanced by CoUninitialize()

	pidlReturn = SHBrowseForFolder (&bi);
	if (pidlReturn)
	{
		s = (char *) rmalloc (MAX_PATH+1);
		SHGetPathFromIDList (pidlReturn,s);
		CoTaskMemFree (pidlReturn);
		CoUninitialize ();		// Uninitialise the COM library

		MakeReturn2Cci (pcci, (int)TRUE, (int)s);
		/* and have the calling Clean function deallocate the directory name buffer. */
	}
	else
	{
		CoUninitialize ();		// Uninitialise the COM library
		MakeReturn2Cci (pcci, (int)FALSE, (int)NULL);
	}
}

void EvalCcRqFILEOPENDIALOG (CrossCallInfo *pcci)		/* no params;  bool, textptr result; */
{
	OPENFILENAME ofn;
	BOOL success;

	ofn.lStructSize       = sizeof (OPENFILENAME);

	ofn.hwndOwner         = GetActiveWindow ();
	ofn.hInstance         = NULL;
	ofn.lpstrFilter       = NULL;
	ofn.lpstrCustomFilter = NULL;
	ofn.nMaxCustFilter    = 0;
	ofn.nFilterIndex      = 0;
	ofn.lpstrFile         = (LPSTR) rmalloc (MAX_PATH);
	ofn.lpstrFile[0]      = '\0';
	ofn.nMaxFile          = MAX_PATH;
	ofn.lpstrFileTitle    = NULL;
	ofn.nMaxFileTitle     = 0;
	ofn.lpstrInitialDir   = NULL;
	ofn.lpstrTitle        = NULL;
	ofn.Flags             = OFN_EXPLORER
						  | OFN_FILEMUSTEXIST
						  |	OFN_HIDEREADONLY
						  | OFN_PATHMUSTEXIST
						  | OFN_ENABLEHOOK;		// PA: OFN_ENABLEHOOK added from Ronny
	ofn.lpstrDefExt       = NULL;
	ofn.lCustData         = 0;
	ofn.lpfnHook          = &FileSelectorHook;	// PA: &FileSelectorHook instead of NULL from Ronny
	ofn.lpTemplateName    = NULL;

	success = GetOpenFileName (&ofn);

	if (success)
	{
		MakeReturn2Cci (pcci, success, (int) ofn.lpstrFile);
		/* and have the calling clean function deallocate the filename buffer */
	}
	else
	{
		MakeReturn2Cci (pcci, success, (int) NULL);
		rfree (ofn.lpstrFile);
	}
}

void EvalCcRqFILESAVEDIALOG (CrossCallInfo *pcci)		/* promptptr, nameptr; bool, textptr result; */
{
	OPENFILENAME ofn;
	BOOL success;
	char *promptptr;
	char *nameptr;

	promptptr = (char *) pcci->p1;
	nameptr   = (char *) pcci->p2;

	if (rstrlen (promptptr) == 0)
		promptptr = NULL;	/* the calling clean function will
							   deallocate the memory allocated
							   for this empty string */

	ofn.lStructSize       = sizeof (OPENFILENAME);
	ofn.hwndOwner         = GetActiveWindow ();
	ofn.lpstrFilter       = NULL;
	ofn.lpstrCustomFilter = NULL;
	ofn.nMaxCustFilter    = 0;
	ofn.nFilterIndex      = 0;
	ofn.lpstrFile         = (LPSTR) rmalloc (MAX_PATH);
	if (rstrlen (nameptr) < MAX_PATH)
	{
		rscopy (ofn.lpstrFile, nameptr);
	}
	else
	{
		rsncopy (ofn.lpstrFile, nameptr, MAX_PATH - 1);
		ofn.lpstrFile[MAX_PATH - 1] = '\0';
	}
	ofn.nMaxFile        = MAX_PATH;
	ofn.lpstrFileTitle  = NULL;
	ofn.nMaxFileTitle   = 0;
	ofn.lpstrInitialDir = NULL;
	ofn.lpstrTitle      = promptptr;
	ofn.Flags           = OFN_EXPLORER
						| OFN_OVERWRITEPROMPT
						| OFN_HIDEREADONLY
						| OFN_ENABLEHOOK;			// PA: OFN_ENABLEHOOK added from Ronny
	ofn.lpstrDefExt     = NULL;
	ofn.lCustData       = 0;
	ofn.lpfnHook        = &FileSelectorHook;		// PA: &FileSelectorHook instead of NULL from Ronny
	ofn.lpTemplateName  = NULL;

	success = GetSaveFileName (&ofn);

	if (success)
	{
		MakeReturn2Cci (pcci, success, (int) ofn.lpstrFile);
		/* and have the calling clean function deallocate the filename buffer */
	}
	else
	{
		MakeReturn2Cci (pcci, success, (int) NULL);
		rfree (ofn.lpstrFile);
	}
}


/*	Install the cross call procedures in the gCrossCallProcedureTable of cCrossCall_121.
*/
int InstallCrossCallFileSelectors (int ios)
{
	CrossCallProcedureTable newTable;

	newTable = EmptyCrossCallProcedureTable ();
	AddCrossCallEntry (newTable, CcRqDIRECTORYDIALOG,EvalCcRqDIRECTORYDIALOG);
	AddCrossCallEntry (newTable, CcRqFILEOPENDIALOG, EvalCcRqFILEOPENDIALOG);
	AddCrossCallEntry (newTable, CcRqFILESAVEDIALOG, EvalCcRqFILESAVEDIALOG);
	AddCrossCallEntries (gCrossCallProcedureTable, newTable);

	return ios;
}
