/***********************************************************************
*
*   DrvConfig.c
*
*   Macintosh drivers configuration subsystem implementation.
*
*   Copyright (c) 1994-1997, Willows Software Inc.  All rights reserved.  
*
************************************************************************/


/* Includes */
#include <string.h>

#include "DrvGlobals.h"
#include "DrvHook.h"
#include "WinConfig.h"
#include "DrvSystem.h"
#include "StringUtils.h"

#define NO_POSIX_REDIRECT		TRUE
#include "UnixCompatibility.h"


/* Local prototypes */
static char *DrvGetTwinPrefsFName(void);
static void GetPrefsDir(char *windir, int maxlen);
static void GetWindowsDir(char *windir, int maxlen);
static void GetTempDir(char *windir, int maxlen);
static OSErr FindSubFolder(char *name, short vRefNum, long parID, Boolean create, long *foundDirID);
static void InitConfiguration(void);

#define MAX_LINE 256


/* Now add the default twin preferencs */

/* Twin RC file default table format: */
/* Parameter, Opcode, Section, Keyname, Default, Env, lParam, string */
TWINRC  gTwinDefaults[] = {
/* [boot] */
	WCP_DISPLAY, 	2, WCS_BOOT, "display",			":0.0",	"DISPLAY",0,0,
	WCP_HEIGHT,  		1, WCS_BOOT, "screenheight", 0,	0,0,0,
	WCP_WIDTH,   		1, WCS_BOOT, "screenwidth", 	0,	0,0,0,
	WCP_WINDOWS, 	1, WCS_BOOT, "windows",		0, "WINDOWS",0,0,
	WCP_TEMP,    		2, WCS_BOOT, "temp",				"/tmp", "TMP",0,0,
	WCP_OPENPATH,	1, WCS_BOOT, "path",				0, "OPENPATH",0,0,
	WCP_TASKING, 	1, WCS_BOOT, "tasking",			"1", 0,0,0,
	WCP_LOGFILE, 		1, WCS_BOOT, "logfile",			"-", "LOGFILE",0,0,
	WCP_LOGMASK, 	1, WCS_BOOT, "logmask",		"-1", 0,0,0,
	WCP_PRINTER, 		1, WCS_BOOT, "printer",	 		"0", 0,0,0,
	WCP_LIBRARY, 	5, WCS_BOOT, 0,						"", 0,0,0,
	WCP_SETUP,   		2, WCS_BOOT, "setup",			"", "HOME",0,0,
	WCP_FATAL,   		4, WCS_BOOT, "fatal",				0,	0,0,0,
	WCP_VERIFY,  		4, WCS_BOOT, "syncronous",	0,	0,0,0,
	WCP_COLORMAP,	4, WCS_BOOT, "colormap",		0,	0,0,0,
	WCP_DITHER,  		4, WCS_BOOT, "dither",			0,	0,0,0,
       WCP_SIZEGRIP,    1, WCS_BOOT, "SizeGrip",                 "1", 0,0,0,


/* [windows] */
	WCP_DEBUGGER,	4, WCS_WINDOWS, "debugger", 			0,	0, 0, 0,
	WCP_NOPAGING,	4, WCS_WINDOWS, "nopaging", 			0,	0, 0, 0,
	WCP_VERBOSE, 	4, WCS_WINDOWS, "verbose", 				0,	0, 1, 0,
	WCP_CONTROL, 	4, WCS_WINDOWS, "control", 				0, 0, 0, 0,
	WCP_DBLCLICK, 	1, WCS_WINDOWS, "DoubleClickRate", 	"250", 0, 0, 0,
	WCP_CURBLINK, 	1, WCS_WINDOWS, "CursorBlinkRate",	"500", 0, 0, 0,
	WCP_FONTFACE, 	1, WCS_WINDOWS, "FontFace", 			"Chicago", 0, 0, 0,
	WCP_FONTSIZE, 	1, WCS_WINDOWS, "FontSize", 			"-12", 0, 0, 0,
	WCP_FONTBOLD, 	1, WCS_WINDOWS, "FontWeight",   		"400", 0, 0, 0,
	WCP_FONTMAP,  	1, WCS_WINDOWS, "fontmapper", 		"0", 0, 0, 0,
	WCP_HELPPROG, 	1, WCS_WINDOWS, "HelpProgram", 		"twinhelp", 0, 0, 0,
	WCP_ICONFACE, 	1, WCS_WINDOWS, "IconFontFace", 		"Geneva", 0, 0, 0,
	WCP_ICONSIZE, 	1, WCS_WINDOWS, "IconFontSize", 		"-9", 0, 0, 0,
	WCP_OUTPUT,   	1, WCS_WINDOWS, "OutputDebug", 		"-", 0, 0, 0,
	WCP_WINFLAG,  	4, WCS_WINDOWS, "WinFlags", 			0, 0, 0xc289, 0,


/* [PortAliases] */
	WCP_PORTNAME, 3, WCS_PORTALIAS, "",			0,		0,0,0,

/* [FontSubstitutes] */
	WCP_FONTALIAS,	3, WCS_FONTSUB, "",				0,		0,0,0,

/* [colors] */
	WCP_COLORS,   	3, WCS_COLORS, "", 				0,		0,0,0,

/* [Devices] */
	WCP_DEVICES,  	3, WCS_DEVICES, "", 				0,		0,0,0,

/* [XDOS] */
	WCP_DOSMODE,  	4, WCS_XDOS, "mode",				0, 0, 0, 0,
	WCP_MEMORY,   	4, WCS_XDOS, "memory",		0,	0, 640, 0,
	WCP_EXTENDED, 	4, WCS_XDOS, "extended",		0,	0, 15*1024, 0,
	WCP_HARDWARE, 4, WCS_XDOS, "equipment",		0,	0, 0, 0,
	WCP_NFILES,   		4, WCS_XDOS, "files",				0,	0, 100, 0,
	WCP_NOMAPDIR, 	4, WCS_XDOS, "nomap",			0,	0, 0, 0,

/* [COMMDLG] */
	WCP_DOSDRIVES,			2, WCS_COMMDLG, "DosDrives",		"yes", 0, 0, 0,
	WCP_DRIVELETTERS,		2, WCS_COMMDLG, "DriveLetters", 	"yes", 0, 0, 0,
	WCP_PATHSASDRIVES,	2, WCS_COMMDLG, "PathAsDrives",	"yes", 0, 0, 0,

	0,0,0,0,0,0,0,
};

/* Some local variables */
static Boolean gInitialized = FALSE;


/********************************************************************
*   PrivateConfigurationHook
*
********************************************************************/
DWORD PrivateConfigurationHook(WORD dwCode, LPARAM /*dwParam1*/, LPARAM dwParam2, LPVOID /*lpStruct*/)
{
    switch(dwCode) {
	/* dwParam1 - compatibility mask */
	/* dwParam2 - init/exit flag */
	case DSUBSYSTEM_INIT:
		if (dwParam2)
			InitConfiguration();
		break;

	case DSUBSYSTEM_GETCAPS:
	case DSUBSYSTEM_EVENTS:
	    return 1L;

	case PCFGH_GETDEFAULTS:
		if (!gInitialized)
			InitConfiguration();
		return (DWORD) gTwinDefaults;

	case PCFGH_GETFILENAME:
		return (DWORD) DrvGetTwinPrefsFName();
		
	default:
		break;
	}

	return(0L);
}


/********************************************************************
*   InitConfiguration
*
*	Perform any initializations and run time setups.
********************************************************************/
static void InitConfiguration(void)
{
LPTWINRC tp;
char buf[MAX_LINE];

	if (gInitialized)
		return;

	/* Perform an necessary run-time settings of the default table */
	for(tp = gTwinDefaults; tp->parameter > 0; tp++) {
		/* Add the run-time windows directory */
		if (tp->parameter == WCP_WINDOWS) {
			GetWindowsDir(buf, MAX_LINE);					/* Get the current win directory (mac path) */
			MacToUnixPath(buf, strlen(buf));					/* Make it into a unix path */
			tp->lpszdefault = DrvMalloc(strlen(buf));		/* Add it to the table */
			strcpy(tp->lpszdefault, buf);
		}
		if (tp->parameter == WCP_TEMP) {
			GetTempDir(buf, MAX_LINE);
			MacToUnixPath(buf, strlen(buf));
			tp->lpszdefault = DrvMalloc(strlen(buf));
			strcpy(tp->lpszdefault, buf);
		}

		/* Add any additional overrides later */
	}
	
	gInitialized = TRUE;
}

/********************************************************************
*   GetWindowsDir
*
*	Get the full path name of the "Windows" directory.
********************************************************************/
static void GetWindowsDir(char *windir, int maxlen)
{
OSErr err;
Str255 fullPathName;
static char driverSpecName[MAX_LINE];
FSSpec spec;
char wname[] = "Windows";
long windowsDirID;

	/* We want the driver's parent directory's parent */
	PathNameFromDirID(gMyFileSpec.parID, gMyFileSpec.vRefNum, fullPathName);
	err = FSMakeFSSpec(0, 0, fullPathName, &spec);
	if (!err) {
		FindSubFolder(wname, spec.vRefNum, spec.parID, kCreateFolder, &windowsDirID);
		PathNameFromDirID(windowsDirID, spec.vRefNum, fullPathName);
		p2cstr(fullPathName);
		strncpy(windir, (char*)fullPathName, maxlen);
	}
}

/********************************************************************
*   DrvGetTwinPrefsFName
*
*	Get the full path name of the "Twin Preferences" file.
********************************************************************/
static char *DrvGetTwinPrefsFName(void)
{
static char fname[MAX_LINE];

	/* Get the current preferences directory (mac path) */
	GetPrefsDir(fname, MAX_LINE);

	/* Add the rest of the file name to the string. */
	strcat(fname, "Twin Preferences");

	/* Convert the value into a unix pathname */
	MacToUnixPath(fname, strlen(fname) + 1);	/* add 1 to the string length for the leading slash */

	return (fname);
}


/********************************************************************
*	GetPrefsDir
*
*	Gets the default preferences directory.
* It should be the boot volume:System Folder:Preferences:
********************************************************************/
static void GetPrefsDir(char *windir, int maxlen)
{
OSErr err;
short foundVRefNum;
long prefsDirID;
Str255 fullPathName;
	
	/* We haven't found it yet, so do so now */
	/* First find the booted system folder's Preferences folder */	
	err = FindFolder (kOnSystemDisk, kPreferencesFolderType, kCreateFolder, &foundVRefNum, &prefsDirID);

	/* Now, finally set the path since we are sure everything is in place */	
	if (!err) {
		PathNameFromDirID(prefsDirID, foundVRefNum, fullPathName);
		p2cstr(fullPathName);
		strncpy(windir, (char*)fullPathName, maxlen);
	}
		
}

/********************************************************************
*	GetTempDir
*
*	Gets the default directory for temporary files.
* It should be the boot volume:Temporary Items:
********************************************************************/
static void GetTempDir(char *windir, int maxlen)
{
OSErr err;
short foundVRefNum;
long tempDirID;
Str255 fullPathName;
	
	/* We haven't found it yet, so do so now */
	/* First find the booted system folder's Temporary folder */	
	err = FindFolder (kOnSystemDisk, kTemporaryFolderType, kCreateFolder, &foundVRefNum, &tempDirID);
	
	/* Now, finally set the path since we are sure everything is in place */	
	if (!err) {
		PathNameFromDirID(tempDirID, foundVRefNum, fullPathName);
		p2cstr(fullPathName);
		strncpy(windir, (char*)fullPathName, maxlen);
	}
		
}

/********************************************************************
*	FindSubFolder
*
*	Our version of FindFolder, which allows us to look and optionally create
*   a folder given it's parent and volume ID's.
********************************************************************/
static OSErr FindSubFolder(char *name, short vRefNum, long parID, Boolean create, long *foundDirID)
{
OSErr err;
CInfoPBRec pb;
Str255 pName;

	c2pstrcpy(pName, name);					/* Toolbox calls want pascal strings */
	
	/* See if it exists */
	/* Use the PB calls as they allow more control */
	/* The FspGetFInfo will not distinguish between a directory and a file */	
	pb.dirInfo.ioCompletion = NULL;
	pb.dirInfo.ioNamePtr = pName;
	pb.dirInfo.ioVRefNum = vRefNum;
	pb.dirInfo.ioFDirIndex = 0;					/* 0=query 1 itm, -1=query dir in ioDrDirID */
	pb.dirInfo.ioDrDirID = parID;
	
	err = PBGetCatInfo(&pb, false);	

	if (create && err)	
		err = PBDirCreate((HParmBlkPtr)&pb, false);	/* Create the directory */

	if (!err)
		*foundDirID = pb.dirInfo.ioDrDirID;					/* We found or created it! */

	return err;
}




