From: Sproul@sproul.sproul.com (Mark Sproul)
Subject: Prefs file source code (C - long)
Date: 2 Oct 92 09:05:30 GMT


Several people asked for this source code.  As explained in the comments,
it came from Inside Mac Comm Toolbox and there is a lot of code dealing
just with the Comm Tool box setup.  It now handles the PREFERENCES
folder in the system folder properly.

I have done some additions to the code to make it more general and
usable as far as dealing with preferences.  Such as GET pref and SET
pref.  This code was all written and runs correctly with Think C 5.0.

Its been several months since I wrote this and was looking at it.
I may have forgotten to mention something, if you have any problems
let me know and I will post updates.

You need to define some things such as this:

#define	creatorType		'abcd'
#define	fileType		'PREF'
#define	prefsFileName	"\pMyPreferences"






/******************************************************************************
* adapted from
*  Inside the Macintosh Communications Toolbox
* Page  333
* After initialization, the code shown first checks if a
* preferences folder, which contains tool settings written in preference
* files, already exists. If so, the application uses the settings in this file.
* Otherwise, the code generates a new preferences file.
******************************************************************************
* Modifications
******************************************************************************
* Nov 27, 1991	Original version had a bug in it.
*				If the "Preferences" directory already existed, the preferences file
*				was placed in the system folder, not in the "Preferences" directory.
*				If the directory did NOT exist, everything worked fine.
*				I also changed it to check for the existance of the "Preferences" folder
*				first instead of trying to create one and letting an duplicate file error
*				indicate that it already existed.
*				by Mark Sproul
*				Internet: sproul@sproul.com
*				AppleLink: Sproul.M
* Jan 16, 1992	Working on a general purpose prefs file manipulator
* Jan 25, 1992	Prefs file resources working great
******************************************************************************/

#include	<Connections.h>
#include	<CommResources.h>

/*
** Global Variables used by all of the prefs routines
*/
long			prefDirID;			/* Prefs Dir ID number */
long			sysfDirID;			/* System folder Dir ID number */
short			prefVRefNum;		/* Prefs Volume Ref number */
short			prefFileOKFlag = 0;	/* prefs file OK indicator */

/*************************************************************
* This makes sure there is a prefs file in the PREFERENCES directory
* if not, it creates it.
*
* getPrefsFile MUST be called before any atempt at getting the prefs values
*
*************************************************************/

void getPrefsFile(prefsFileName, creatorType, fileType)
Str255		prefsFileName;
OSType		creatorType;
OSType		fileType;
{
OSErr			osErr		= noErr;
SysEnvRec		theWorld;
CInfoPBPtr		infoPB;
WDPBPtr			wdPB;
HParmBlkPtr		dirPB;

short			prefRefNum;
Point			where	= { 75, 75 };
Str63			toolName;
short			procID;
Handle			h;
Ptr				p;


ConnHandle		prefConn;

ConnHandle		docConn;
CMBufferSizes	sizes	= { 0, 0, 0, 0, 0, 0, 0, 0 };



	infoPB		= (CInfoPBPtr)NewPtrClear(sizeof(*infoPB));
	wdPB		= (WDPBPtr)NewPtrClear(sizeof(*wdPB));
	dirPB		= (HParmBlkPtr)NewPtrClear(sizeof(*dirPB));


	/* find the system folder's volume reference number and directory ID */
	osErr = SysEnvirons(curSysEnvVers, &theWorld);
	(*wdPB).ioVRefNum = theWorld.sysVRefNum;

	if (noErr == (osErr = PBGetWDInfo(wdPB, false)))
	{
		/*********************************************************
		* 11-27-91 Modified by Mark Sproul
		**********************************************************/
		/* get the Volume Reference Number and save it */
		prefVRefNum	= (*wdPB).ioWDVRefNum;
		/* get the System directir ID and save it */
		sysfDirID	= (*wdPB).ioWDDirID;
		
		/* check for the preferences folder */
		(*infoPB).hFileInfo.ioFDirIndex	= 0;
		(*infoPB).hFileInfo.ioVRefNum	= prefVRefNum;
		(*infoPB).hFileInfo.ioDirID		= sysfDirID;
		(*infoPB).hFileInfo.ioNamePtr	= "\pPreferences";
		osErr = PBGetCatInfo(infoPB, false);
		/* save the "Preferecnces" dir number */ 
		prefDirID	= (*infoPB).hFileInfo.ioDirID;
		
		if (osErr == fnfErr)
		{
			/* Create "Preferences" folder */
			(*dirPB).fileParam.ioVRefNum	= prefVRefNum;
			(*dirPB).fileParam.ioDirID		= sysfDirID;
			(*dirPB).fileParam.ioNamePtr	= "\pPreferences";
			osErr = PBDirCreate(dirPB, false);
			prefDirID	= (*dirPB).fileParam.ioDirID;
		}

		/*********************************************************
		* end of modifications
		**********************************************************/
		if (osErr == noErr)
		{
			/* does the preference file exist? */
			(*infoPB).hFileInfo.ioFDirIndex	= 0;
			(*infoPB).hFileInfo.ioVRefNum	= prefVRefNum;
			(*infoPB).hFileInfo.ioDirID		= prefDirID;
			(*infoPB).hFileInfo.ioNamePtr	= prefsFileName;
			osErr = PBGetCatInfo(infoPB, false);
			if (osErr == noErr)
			{
				/* set flag saying the prefs file is OK */
				prefFileOKFlag = 0xAA;
			}
			if (osErr == fnfErr)
			{
				/* no, so create a new preference file */
				if (noErr == (osErr = HCreate(prefVRefNum, prefDirID, prefsFileName, creatorType, fileType)))
				{
					HCreateResFile(prefVRefNum, prefDirID, prefsFileName);
					if (noErr == (osErr = ResError()))
					{
						/* open the preference file */
						prefRefNum = HOpenResFile(prefVRefNum, prefDirID, prefsFileName, fsRdWrPerm);
						if (prefRefNum == -1)
						{
							osErr = ResError();
						}
						else
						{
							/* create a default connection */
							osErr = CRMGetIndToolName(classCM, 1,toolName);
							if (noErr == osErr)
							{
								prefConn = CMNew(CMGetProcID(toolName), cmData, sizes, 0, 0);
								/* leave the default setting as the preferance */
								
								/************************************************************
								* ORIGINALLY, the code let the user select setup at this point
								* I do not want it asking for serial port prefs on startup
								* if they are not set.
								* ---allow the user to select a prefered tool and configuration
								* ---osErr = CMChoose(&prefConn, where, nil);
								************************************************************/
							
								/* write the prefered tool name to the preference file */
								HLock((Handle) prefConn);
								CMGetToolName((**prefConn).procID, toolName);
								HUnlock((Handle) prefConn);
								h = NewHandle(1 + toolName[0]);
								HLock(h);
								BlockMove(toolName, *h, GetHandleSize(h));
								HUnlock(h);
								AddResource(h, 'pTXT', 0, "");
								ReleaseResource(h);
								/* write the prefered configuration to the preference file */
								p = CMGetConfig(prefConn);
								h = NewHandle(GetPtrSize(p));
								HLock(h);
								BlockMove(p, *h, GetHandleSize(h));
								HUnlock(h);
								AddResource(h, 'cTXT', 0, "");
								ReleaseResource(h);
								DisposPtr(p);
								
								/* dispose of the connection */
								CMDispose(prefConn);
							}
							/* close the file so that it can be used in a shared environment */
							CloseResFile(prefRefNum);
							/* set flag saying the prefs file is OK */
							prefFileOKFlag = 0xAA;
						}
					}
				}
			}
		}
	}
}

//*****************************************************************
//*
//* The following code was written by Mark Sproul
//* This code allows easy access to prefs file
//*
//*
//*
//*
//*****************************************************************

/**************************************
* get resource from Prefs file
*
****************************************/
getPrefsResourceStr(prefsFileName, perfsResType, returnString)
Str255		prefsFileName;
OSType		perfsResType;
Str255		returnString;
{
short			prefRefNum;
Handle			h;
int				i;
Size			hSize;

	h = nil;
	/* did the prefs file get opened or created OK */
	if (prefFileOKFlag == 0xAA)
	{
		/* focus on the preference file */
		prefRefNum = HOpenResFile(prefVRefNum, prefDirID, prefsFileName, fsRdWrPerm);
		if (prefRefNum != -1)
		{
			h = Get1Resource(perfsResType, 0);
			hSize = GetHandleSize(h);			/* get the size of the handle */
			if (hSize > 255) hSize = 255;
			HLock(h);
			/* had to have this to make it compile under THINK C 5.0 */
			for (i=0; i< hSize; i++)
			{
				returnString[i] = *(*h+i);
			}
			HUnlock(h);
			ReleaseResource(h);
			CloseResFile(prefRefNum);
		}
	}
}


/**************************************
* set Comm Tool Box connection preference
*
****************************************/
setCTBpref(prefsFileName)
Str255		prefsFileName;
{
short			prefRefNum;
OSErr			osErr, cmChooseReturnCode;
int				i;
Str255			prefStr;
short			procID;
Str63			toolName;
Handle			h;
Ptr				p;
short			iErr;
Size			hSize, newSize;

ConnHandle		docConn;
CMBufferSizes	sizes	= { 0, 0, 0, 0, 0, 0, 0, 0 };
Point			where	= { 75, 75 };

	if (isCTBavailable())
	{
		/* did the prefs file get opened or created OK */
		if (prefFileOKFlag == 0xAA)
		{
			getPrefsResourceStr(prefsFileName,'pTXT', prefStr);
	
			procID = CMGetProcID(prefStr);
			if (procID != -1)
			{
				/* create a new connection */
				docConn	= CMNew(procID, cmData, sizes, 0, 0);
				
				if (docConn != nil)
				{
					/* set the prefered configuration */
		
					getPrefsResourceStr(prefsFileName,'cTXT', prefStr);
					osErr	= CMSetConfig(docConn, (char *)prefStr);
	
					cmChooseReturnCode	= CMChoose(&docConn, where, nil);
				}
			}
			else
			{
				/* the prefered tool could not be found so I */
				osErr	= CRMGetIndToolName(classCM, 1, toolName);
				docConn	= CMNew(CMGetProcID(toolName), cmData, sizes, 0, 0);
				if (docConn != nil)
				{
					cmChooseReturnCode	= CMChoose(&docConn, where, nil);
				}
			}
			
			if ((cmChooseReturnCode == chooseOKMinor) || (cmChooseReturnCode == chooseOKMajor))
			{
				/* change the prefs file */
				
				if (prefFileOKFlag == 0xAA)
				{
					/* open the preference file */
					prefRefNum = HOpenResFile(prefVRefNum, prefDirID, prefsFileName, fsRdWrPerm);
					if (prefRefNum != -1)
					{
						/* write the prefered tool name to the preference file */
						HLock((Handle) docConn);
						CMGetToolName((**docConn).procID, toolName);
						HUnlock((Handle) docConn);
						
						/* get the port TeXT resource */
						h = Get1Resource('pTXT', 0);
						if (h == nil)
						{
							/* resource did not exist, add it to resource file */
							h = NewHandle(1 + toolName[0]);
							HLock(h);
							BlockMove(toolName, *h, GetHandleSize(h));
							HUnlock(h);
							AddResource(h, 'pTXT', 0, "");
						}
						else
						{
							/* resoure DOES exist, change it */
							hSize = GetHandleSize(h);			/* get the size of the handle */
							/* check for size of handle */
							if (hSize != (1 + toolName[0]))
							{
								newSize = 1 + toolName[0];
								SetHandleSize(h, newSize);
							}
							HLock(h);
							BlockMove(toolName, *h, GetHandleSize(h));
							HUnlock(h);
							ChangedResource(h);
						}
						ReleaseResource(h);
						
						/* write the prefered configuration to the preference file */
						p = CMGetConfig(docConn);
	
	
						/* get the configuration TeXT resource */
						h = Get1Resource('cTXT', 0);
						if (h == nil)
						{
							/* resource did not exist, add it to resource file */
							h = NewHandle(GetPtrSize(p));
							HLock(h);
							BlockMove(p, *h, GetHandleSize(h));
							HUnlock(h);
						
							AddResource(h, 'cTXT', 0, "");
							iErr = ResError();
						}
						else
						{
							/* resoure DOES exist, change it */
							hSize = GetHandleSize(h);			/* get the size of the handle */
							/* check for size of handle */
							if (hSize != GetPtrSize(p))
							{
								newSize = GetPtrSize(p);
								SetHandleSize(h, newSize);
							}
							HLock(h);
							BlockMove(p, *h, GetHandleSize(h));
							HUnlock(h);
							ChangedResource(h);
						}
						ReleaseResource(h);
	
						CloseResFile(prefRefNum);
						iErr = ResError();
						DisposPtr(p);
					}
				}
			}
			
			if (docConn != nil)
			{
				/* dispose of the connection */
				CMDispose(docConn);
			}
	
		}
	}
}


DoCommPortSetup(prefsFileName)
Str255	prefsFileName;
{
	setCTBpref(prefsFileName);

}


-------------------------------------
Mark Sproul - KB2ICI