From: [email protected] (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: [email protected]
*                               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