/********************************************************************************************
	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.
********************************************************************************************/
#define WINVER 0x0500
#define _WIN32_WINNT 0x0500

#include "cCrossCallFileSelectors_121.h"
#include "util_121.h"
#include "cCrossCall_121.h"

#ifdef _WIN64
static UINT_PTR APIENTRY FileSelectorHook (HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
#else
static UINT APIENTRY FileSelectorHook (HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
#endif
{
	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, TRUE, (size_t)s);
		/* and have the calling Clean function deallocate the directory name buffer. */
	}
	else
	{
		CoUninitialize ();		// Uninitialise the COM library
		MakeReturn2Cci (pcci, FALSE, (size_t)NULL);
	}
}

#define MAXBUF 300
#define MAXFILTERS     10
static LPTSTR lpszFilterString ;
static TCHAR szFilterString[MAXBUF] ;
static TCHAR szFilterInits[MAXFILTERS][30] ;

void InitFilterString(void)
{
  int i ;
  int nInc = 0 ;
  LPTSTR lpStr = szFilterString ;


  /* First, zero out this memory just for the sake of sanity */

  for (i=0; i<MAXBUF; i++)
    szFilterString[i] = 0 ;


  /* Now, for each string in the szFilterInits array, concatenate it to
     the last one right after the last one's null terminator */

  i = 0 ;

  while (szFilterInits[i][0] != (TCHAR) 0)
  {
    lstrcpy(lpStr, &szFilterInits[i][0]) ;
    nInc+=lstrlen(&szFilterInits[i][0]) + 1 ;   //1 past null term...
    lpStr = &szFilterString[nInc] ;
    i++ ;
  }

  szFilterString[nInc] = (TCHAR) 0 ;  //double terminator


  /* Set the lpszFilterString to point to the memory we just filled in
     with the filters because lpszFilterString is what is in
     OPENFILENAME->lpstrFilter */

  lpszFilterString = szFilterString ;

  return ;
}

BOOL IsModernPlatform()
{ 
    OSVERSIONINFOA osvi = {0};
    osvi.dwOSVersionInfoSize = sizeof(osvi);
    GetVersionExA((OSVERSIONINFOA*)&osvi);
    return (5 <= osvi.dwMajorVersion);    
}

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

   recent = IsModernPlatform();

   lstrcpy(&szFilterInits[0][0], TEXT("All Files (*.*)")) ;
   lstrcpy(&szFilterInits[1][0], TEXT("*.*")) ;
//   lstrcpy(&szFilterInits[2][0], TEXT("Fat Files (*.fat)")) ;
//   lstrcpy(&szFilterInits[3][0], TEXT("*.fat")) ;
//   szFilterInits[4][0] = (TCHAR) 0 ;
   szFilterInits[2][0] = (TCHAR) 0 ;

   InitFilterString();
   if (recent)
   {
	   ofn.lStructSize       = sizeof (OPENFILENAME);
   } 
   else
   {
	   ofn.lStructSize       = OPENFILENAME_SIZE_VERSION_400;
   } 
   
	ofn.hwndOwner         = GetActiveWindow ();
	ofn.hInstance         = NULL;
	ofn.lpstrFilter       = lpszFilterString;//(LPSTR) rmalloc (MAX_PATH);// NULL;
//	ofn.lpstrFilter[0] = '\0';
//	ofn.lpstrFilter[1] = '\0';
	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             = 0x81c24;
		//OFN_EXPLORER
		//				  | OFN_FILEMUSTEXIST
		//				  |	OFN_HIDEREADONLY
		//				  | OFN_PATHMUSTEXIST;
//						  | OFN_NODEREFERENCELINKS;
						   
//						  | 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;
#if (_WIN32_WINNT >= 0x0500)
	ofn.pvReserved		  = NULL;
	ofn.dwReserved		  = 0;
	ofn.FlagsEx			  = 0;
#endif // (_WIN32_WINNT >= 0x0500)

	success = GetOpenFileName (&ofn);

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

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

	recent = IsModernPlatform();

	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 */

	if (recent)
	{
	   ofn.lStructSize       = sizeof (OPENFILENAME);
	} 
	else
	{
	   ofn.lStructSize       = OPENFILENAME_SIZE_VERSION_400;
	} 
	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;
#if (_WIN32_WINNT >= 0x0500)
	ofn.pvReserved		  = NULL;
	ofn.dwReserved		  = 0;
	ofn.FlagsEx			  = 0;
#endif

	success = GetSaveFileName (&ofn);

	if (success)
	{
		MakeReturn2Cci (pcci, success, (size_t) ofn.lpstrFile);
		/* and have the calling clean function deallocate the filename buffer */
	}
	else
	{
		MakeReturn2Cci (pcci, success, (size_t) 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;
}
