Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
Feature Files/VRPreferences.c
////////// |
// |
// File: VRPreferences.c |
// |
// Contains: Functions for VRScript preferences management. |
// |
// Written by: Tim Monroe |
// |
// Copyright: © 1999 by Apple Computer, Inc., all rights reserved. |
// |
// Change History (most recent first): |
// |
// <6> 03/17/00 rtm made changes to get things running under CarbonLib |
// <5> 06/06/99 rtm added kVRPrefs_PromptUser option |
// <4> 06/05/99 rtm tweaked VRPrefs_Init so that default values are identical with the |
// hard-coded values of earlier versions of VRScript |
// <3> 06/04/99 rtm added functions to read and write preferences on Windows and MacOS |
// <2> 06/03/99 rtm added dialog box handling code |
// <1> 06/02/99 rtm first file |
// |
// This file defines functions that we use to manage the VRScript preferences. Currently we support |
// preferences that indicate the name and location of the script file associated with a VR movie, but |
// it would be easy to add other preferences as well. |
// |
// A word about terminology: on the Macintosh, we store our preferences in a file (typically in the |
// Preferences folder inside the System folder), which we hereafter call the "preferences file". On |
// Windows, we store our preferences in the registry database. Therefore, on Windows, there is really |
// no single preferences file that contains our application preferences. Nonetheless, in the comments |
// below (and in the naming of some of the functions), we shall refer to a preferences file; in general, |
// you can interpret this to mean: the persistent collection of data that stores the application |
// preferences (whether that collection is an actual file or a chunk of data in some other file). |
// |
// A good discussion of Mac-based preference handling is contained in Gary Woodcock's article in develop, |
// issue 18. I have occasionally used an idea or two from the source code that accompanies that article, |
// but in general I had to start from scratch, largely because he assumes that all preferences should be |
// stored in resources (a tactic that may be correct for Macintosh applications but which does not easily |
// translate to Windows). |
// |
////////// |
////////// |
// |
// header files |
// |
////////// |
#include "VRPreferences.h" |
////////// |
// |
// global variables |
// |
////////// |
VRScriptPrefsHdl gPreferences; // a handle to the global preferences record |
static UserItemUPP gUserItemUPP; // UPP to our user-item drawing procedure |
extern ModalFilterUPP gModalFilterUPP; // UPP to our custom dialog event filter |
/////////////////////////////////////////////////////////////////////////////////////////////////////////// |
// |
// Start-up and shut-down utilities. |
// |
// Use these functions to initialize and deinitialize our preference handling. |
// |
/////////////////////////////////////////////////////////////////////////////////////////////////////////// |
////////// |
// |
// VRPrefs_Init |
// Initialize the application's global preferences. |
// |
////////// |
void VRPrefs_Init (void) |
{ |
Boolean myPrefsExist = false; |
// allocate a record to hold the application preferences information |
gPreferences = (VRScriptPrefsHdl)NewHandleClear(sizeof(VRScriptPrefsRec)); |
if (gPreferences == NULL) |
QTFrame_QuitFramework(); // this should never happen; if it does, we are REALLY in trouble... |
// look for a preferences file |
myPrefsExist = VRPrefs_PrefsFileExists(); |
if (myPrefsExist) { |
// if one exists, open it and read the existing preferences from it |
VRPrefs_ReadPrefsFile(); |
(**gPreferences).fPrefsFileExists = true; |
(**gPreferences).fPrefsDataDirty = false; |
} else { |
// if none exists, initialize the application preferences to a default state |
(**gPreferences).fScriptLocType = kVRPrefs_DirOfMovieFile; |
(**gPreferences).fScriptNameType = kVRPrefs_UserSpecifiedName; |
(**gPreferences).fTurboMode = false; |
(**gPreferences).fVerboseMode = false; |
(**gPreferences).fPrefsFileExists = false; |
(**gPreferences).fPrefsDataDirty = false; |
if ((**gPreferences).fScriptNameType == kVRPrefs_UserSpecifiedName) { |
// make sure there is a default user-specified name |
BlockMove(kDefaultScriptFileName, &((**gPreferences).fScriptBaseName[1]), strlen(kDefaultScriptFileName)); |
(**gPreferences).fScriptBaseName[0] = strlen(kDefaultScriptFileName); |
} |
} |
// allocate a routine descriptor for the user-item drawing procedure |
gUserItemUPP = NewUserItemUPP(VRPrefs_DrawPrefsDialogUserItem); |
} |
////////// |
// |
// VRPrefs_Stop |
// Close down the application's global preferences. |
// |
////////// |
void VRPrefs_Stop (void) |
{ |
if (gPreferences != NULL) { |
// if necessary, update the stored preferences data |
if ((**gPreferences).fPrefsDataDirty) |
VRPrefs_UpdatePrefsFile(); |
// get rid of the global preferences record |
DisposeHandle((Handle)gPreferences); |
gPreferences = NULL; |
} |
} |
/////////////////////////////////////////////////////////////////////////////////////////////////////////// |
// |
// Dialog box utilities. |
// |
// Use these functions to display the Preferences dialog box and get the user's preferences from it. |
// |
/////////////////////////////////////////////////////////////////////////////////////////////////////////// |
////////// |
// |
// VRPrefs_ShowPrefsDialog |
// Display the Preferences dialog box and handle events in it. |
// |
////////// |
void VRPrefs_ShowPrefsDialog (void) |
{ |
DialogPtr myDialog = NULL; |
DialogItemIndex myItem = 0; |
DialogItemType myItemType; |
Handle myItemHandle = NULL; |
Rect myItemRect; |
short myIndex; |
OSErr myErr = noErr; |
if (gPreferences == NULL) |
return; |
// open up the Preferences dialog box |
myDialog = GetNewDialog(kPreferencesDialogID, NULL, (WindowPtr)-1L); |
if (myDialog == NULL) |
return; |
// set the current values into the dialog box |
VRPrefs_FillPrefsDialogFromPrefs(myDialog); |
// set the OK and Cancel buttons |
SetDialogDefaultItem(myDialog, kPrefsButtonDone); |
SetDialogCancelItem(myDialog, kPrefsButtonCancel); |
// set the drawing procedure for the two user items |
GetDialogItem(myDialog, kPrefsFilePathUserItem, &myItemType, &myItemHandle, &myItemRect); |
SetDialogItem(myDialog, kPrefsFilePathUserItem, myItemType, (Handle)gUserItemUPP, &myItemRect); |
GetDialogItem(myDialog, kPrefsFileNameUserItem, &myItemType, &myItemHandle, &myItemRect); |
SetDialogItem(myDialog, kPrefsFileNameUserItem, myItemType, (Handle)gUserItemUPP, &myItemRect); |
// show the dialog |
MacShowWindow(GetDialogWindow(myDialog)); |
// handle dialog box events until the user selects OK or Cancel |
do { |
ModalDialog(gModalFilterUPP, &myItem); |
switch (myItem) { |
// the script-file-location set of radio buttons |
case kPrefsRadioPromptUser: |
case kPrefsRadioDirOfMovieFile: |
case kPrefsRadioDirOfApplication: |
case kPrefsRadioUserSpecifiedPath: |
for (myIndex = kPrefsRadioPromptUser; myIndex <= kPrefsRadioUserSpecifiedPath; myIndex++) { |
GetDialogItem(myDialog, myIndex, &myItemType, &myItemHandle, &myItemRect); |
SetControlValue((ControlHandle)myItemHandle, (myIndex == myItem)); |
} |
// enable script-file-name set of radio buttons, based on kPrefsRadioPromptUser |
for (myIndex = kPrefsRadioFileNamePlusVRS; myIndex <= kPrefsRadioUserSpecifiedName; myIndex++) { |
GetDialogItem(myDialog, myIndex, &myItemType, &myItemHandle, &myItemRect); |
HiliteControl((ControlHandle)myItemHandle, ((myItem == kPrefsRadioPromptUser) ? 255 : 0)); |
} |
break; |
// the script-file-name set of radio buttons |
case kPrefsRadioFileNamePlusVRS: |
case kPrefsRadioUserSpecifiedName: |
for (myIndex = kPrefsRadioFileNamePlusVRS; myIndex <= kPrefsRadioUserSpecifiedName; myIndex++) { |
GetDialogItem(myDialog, myIndex, &myItemType, &myItemHandle, &myItemRect); |
SetControlValue((ControlHandle)myItemHandle, (myIndex == myItem)); |
} |
break; |
} |
} while ((myItem != kPrefsButtonDone) && (myItem != kPrefsButtonCancel)); |
// if the user selected OK, then retrieve the values from the dialog box and remember them |
if (myItem == kPrefsButtonDone) { |
// the script-file-location set of radio buttons |
for (myIndex = kPrefsRadioPromptUser; myIndex <= kPrefsRadioUserSpecifiedPath; myIndex++) { |
GetDialogItem(myDialog, myIndex, &myItemType, &myItemHandle, &myItemRect); |
if (GetControlValue((ControlHandle)myItemHandle) == 1) { |
(**gPreferences).fScriptLocType = myIndex - kPrefsRadioPromptUser; |
break; |
} |
} |
// the script-file-name set of radio buttons |
for (myIndex = kPrefsRadioFileNamePlusVRS; myIndex <= kPrefsRadioUserSpecifiedName; myIndex++) { |
GetDialogItem(myDialog, myIndex, &myItemType, &myItemHandle, &myItemRect); |
if (GetControlValue((ControlHandle)myItemHandle) == 1) { |
(**gPreferences).fScriptNameType = myIndex - kPrefsRadioFileNamePlusVRS; |
break; |
} |
} |
// the script directory pathname |
GetDialogItem(myDialog, kPrefsTextEditFilePath, &myItemType, &myItemHandle, &myItemRect); |
GetDialogItemText(myItemHandle, (**gPreferences).fScriptPathName); |
// the script name |
GetDialogItem(myDialog, kPrefsTextEditFileName, &myItemType, &myItemHandle, &myItemRect); |
GetDialogItemText(myItemHandle, (**gPreferences).fScriptBaseName); |
// in theory, we should check that the user actually changed something; but for now |
// we'll just assume that something changed (mostly since it won't cost much to update |
// the stored preferences when we exit) |
(**gPreferences).fPrefsDataDirty = true; |
} |
DisposeDialog(myDialog); |
} |
////////// |
// |
// VRPrefs_FillPrefsDialogFromPrefs |
// Set the values of the Preferences dialog box controls based on the existing values in gPreferences. |
// |
////////// |
static void VRPrefs_FillPrefsDialogFromPrefs (DialogPtr theDialog) |
{ |
DialogItemType myItemType; |
Handle myItemHandle = NULL; |
Rect myItemRect; |
UInt16 myIndex; |
if (gPreferences == NULL) |
return; |
if (theDialog == NULL) |
return; |
// do some bounds-checking on the radio button values |
if (((**gPreferences).fScriptLocType < kVRPrefs_PromptUser) || ((**gPreferences).fScriptLocType > kVRPrefs_UserSpecifiedPath)) |
(**gPreferences).fScriptLocType = kVRPrefs_PromptUser; |
if (((**gPreferences).fScriptNameType < kVRPrefs_FileNamePlusTXT) || ((**gPreferences).fScriptNameType > kVRPrefs_UserSpecifiedName)) |
(**gPreferences).fScriptNameType = kVRPrefs_FileNamePlusTXT; |
// set up the current values of the radio button sets |
for (myIndex = kPrefsRadioPromptUser; myIndex <= kPrefsRadioUserSpecifiedPath; myIndex++) { |
GetDialogItem(theDialog, myIndex, &myItemType, &myItemHandle, &myItemRect); |
SetControlValue((ControlHandle)myItemHandle, (myIndex == (**gPreferences).fScriptLocType + kPrefsRadioPromptUser)); |
} |
// enable script-file-name set of radio buttons, based on kPrefsRadioPromptUser |
for (myIndex = kPrefsRadioFileNamePlusVRS; myIndex <= kPrefsRadioUserSpecifiedName; myIndex++) { |
GetDialogItem(theDialog, myIndex, &myItemType, &myItemHandle, &myItemRect); |
HiliteControl((ControlHandle)myItemHandle, (((**gPreferences).fScriptLocType + kPrefsRadioPromptUser == kPrefsRadioPromptUser) ? 255 : 0)); |
} |
for (myIndex = kPrefsRadioFileNamePlusVRS; myIndex <= kPrefsRadioUserSpecifiedName; myIndex++) { |
GetDialogItem(theDialog, myIndex, &myItemType, &myItemHandle, &myItemRect); |
SetControlValue((ControlHandle)myItemHandle, (myIndex == (**gPreferences).fScriptNameType + kPrefsRadioFileNamePlusVRS)); |
} |
// set the script directory pathname |
GetDialogItem(theDialog, kPrefsTextEditFilePath, &myItemType, &myItemHandle, &myItemRect); |
SetDialogItemText(myItemHandle, (**gPreferences).fScriptPathName); |
// set the script basename |
GetDialogItem(theDialog, kPrefsTextEditFileName, &myItemType, &myItemHandle, &myItemRect); |
SetDialogItemText(myItemHandle, (**gPreferences).fScriptBaseName); |
} |
////////// |
// |
// VRPrefs_DrawUserItem |
// Draw any user items in the Preferences dialog box. |
// |
////////// |
PASCAL_RTN void VRPrefs_DrawPrefsDialogUserItem (DialogPtr theDialog, DialogItemIndex theItem) |
{ |
DialogItemType myItemType; |
Handle myItemHandle = NULL; |
Rect myItemRect; |
if (theDialog == NULL) |
return; |
// draw a rectangle around the two user items |
if ((theItem == kPrefsFilePathUserItem) || (theItem == kPrefsFileNameUserItem)) { |
GetDialogItem(theDialog, theItem, &myItemType, &myItemHandle, &myItemRect); |
MacFrameRect(&myItemRect); |
} |
} |
/////////////////////////////////////////////////////////////////////////////////////////////////////////// |
// |
// Preferences file utilities. |
// |
// Use these functions to open the preferences file, read the data in it, and update that data. |
// |
/////////////////////////////////////////////////////////////////////////////////////////////////////////// |
////////// |
// |
// VRPrefs_PrefsFileExists |
// Does a preferences file for our application already exist on this machine? |
// |
////////// |
static Boolean VRPrefs_PrefsFileExists (void) |
{ |
Boolean myFileExists = false; |
#if TARGET_OS_WIN32 |
char mySubKeyName[] = kVRPrefs_PrefsKeyName; |
HKEY myKey; |
if (RegOpenKeyEx(HKEY_CURRENT_USER, mySubKeyName, 0L, KEY_ALL_ACCESS, &myKey) == ERROR_SUCCESS) { |
RegCloseKey(myKey); |
myFileExists = true; |
} |
#endif |
#if TARGET_OS_MAC |
FSSpec myFSSpec; |
OSErr myErr = noErr; |
//myErr = VRPrefs_GetPrefsFileFSSpec(kScriptFileCreator, kPrefsFileType, &myFSSpec); |
myErr = VRPrefs_GetPrefsFileFSSpec(kVRPrefs_PrefsFileName, &myFSSpec); |
myFileExists = (myErr == noErr); |
#endif |
return(myFileExists); |
} |
#if TARGET_OS_MAC |
////////// |
// |
// VRPrefs_GetPrefsFileFSSpec |
// Return, through theFSSpec, an FSSpec record for the preferences file for the specified application. |
// |
// If the returned OSErr is noErr, then the preferences file exists in the location specified by theFSSpec; |
// if it's fnfErr, the preferences file does not exist but you could use theFSSpec to create a new file in |
// the specified location. If the returned OSErr is neither noErr nor fnfErr, the preferences file does not |
// exist and you should not use theFSSpec to create a new preferences file. |
// |
////////// |
static OSErr VRPrefs_GetPrefsFileFSSpec (char *theFileName, FSSpecPtr theFSSpec) |
{ |
short myVRefNum; |
long myPrefsDirID; |
long mySystemDirID; |
Boolean myHasPrefsDir = false; |
Boolean myFoundFile = false; |
StringPtr myName = QTUtils_ConvertCToPascalString(theFileName); |
OSErr myErr = paramErr; |
if (theFSSpec == NULL) |
goto bail; |
// get the Preferences folder directory ID |
myErr = FindFolder(kOnSystemDisk, kPreferencesFolderType, kCreateFolder, &myVRefNum, &myPrefsDirID); |
myHasPrefsDir = (myErr == noErr); |
// get the System folder directory ID |
myErr = FindFolder(kOnSystemDisk, kSystemFolderType, kDontCreateFolder, &myVRefNum, &mySystemDirID); |
if (myErr != noErr) |
goto bail; // no use in continuing if we cannot find the System folder |
// see if the preferences file exists in the Preferences folder |
if (myHasPrefsDir) { |
myErr = FSMakeFSSpec(myVRefNum, myPrefsDirID, myName, theFSSpec); |
if (myErr == noErr) |
myFoundFile = true; |
} |
// if it's not in Preferences folder, see if the preferences file exists in the System folder |
if (!myFoundFile) { |
myErr = FSMakeFSSpec(myVRefNum, mySystemDirID, myName, theFSSpec); |
if (myErr == noErr) |
myFoundFile = true; |
} |
// if we still haven't found a preferences file and if the Preferences folder exists, |
// then that's where we want the caller to create one |
if ((!myFoundFile) && (myHasPrefsDir)) |
myErr = FSMakeFSSpec(myVRefNum, myPrefsDirID, myName, theFSSpec); |
bail: |
free(myName); |
return(myErr); |
} |
#endif |
////////// |
// |
// VRPrefs_ReadPrefsFile |
// Read the data from the preferences file. |
// |
////////// |
static void VRPrefs_ReadPrefsFile (void) |
{ |
#if TARGET_OS_WIN32 |
char mySubKeyName[] = kVRPrefs_PrefsKeyName; |
HKEY myKey; |
DWORD myType; |
DWORD myValue; |
DWORD mySize; |
char myBuffer[MAX_PATH]; |
if (RegOpenKeyEx(HKEY_CURRENT_USER, mySubKeyName, 0L, KEY_ALL_ACCESS, &myKey) == ERROR_SUCCESS) { |
mySize = sizeof(DWORD); |
if (RegQueryValueEx(myKey, kVRPrefs_ScriptLocTypeLabel, NULL, &myType, (BYTE *)&myValue, &mySize) == ERROR_SUCCESS) |
(**gPreferences).fScriptLocType = (UInt32)myValue; |
mySize = MAX_PATH; |
if (RegQueryValueEx(myKey, kVRPrefs_ScriptPathNameLabel, NULL, &myType, (BYTE *)myBuffer, &mySize) == ERROR_SUCCESS) { |
BlockMove(myBuffer, (void *)&((**gPreferences).fScriptPathName[1]), mySize); |
(**gPreferences).fScriptPathName[0] = mySize; |
} |
mySize = sizeof(DWORD); |
if (RegQueryValueEx(myKey, kVRPrefs_ScriptNameTypeLabel, NULL, &myType, (BYTE *)&myValue, &mySize) == ERROR_SUCCESS) |
(**gPreferences).fScriptNameType = (UInt32)myValue; |
mySize = MAX_PATH; |
if (RegQueryValueEx(myKey, kVRPrefs_ScriptBaseNameLabel, NULL, &myType, (BYTE *)myBuffer, &mySize) == ERROR_SUCCESS) { |
BlockMove(myBuffer, (void *)&((**gPreferences).fScriptBaseName[1]), mySize); |
(**gPreferences).fScriptBaseName[0] = mySize; |
} |
RegCloseKey(myKey); |
} |
#endif |
#if TARGET_OS_MAC |
FSSpec myFSSpec; |
short myRefNum = 0; |
long mySize = 0; |
OSErr myErr = noErr; |
// find the location of the preferences file |
myErr = VRPrefs_GetPrefsFileFSSpec(kVRPrefs_PrefsFileName, &myFSSpec); |
if (myErr != noErr) |
goto bail; |
// open the file |
myErr = FSpOpenDF(&myFSSpec, fsRdWrPerm, &myRefNum); |
if (myErr == noErr) |
myErr = SetFPos(myRefNum, fsFromStart, 0); |
// get the size of the file data |
if (myErr == noErr) |
myErr = GetEOF(myRefNum, &mySize); |
// make sure that the file is at least as large as what we're expecting |
if (mySize < GetHandleSize((Handle)gPreferences)) |
myErr = paramErr; |
HLock((Handle)gPreferences); |
// read the data from the file into the handle |
if (myErr == noErr) |
myErr = FSRead(myRefNum, &mySize, *gPreferences); |
bail: |
HUnlock((Handle)gPreferences); |
if (myRefNum != 0) |
FSClose(myRefNum); |
#endif |
} |
////////// |
// |
// VRPrefs_UpdatePrefsFile |
// Update the preferences file. |
// |
////////// |
static void VRPrefs_UpdatePrefsFile (void) |
{ |
#if TARGET_OS_WIN32 |
char mySubKeyName[] = kVRPrefs_PrefsKeyName; |
HKEY myKey; |
DWORD myAction; |
char *myPathName = QTUtils_ConvertPascalToCString((**gPreferences).fScriptPathName); |
char *myBaseName = QTUtils_ConvertPascalToCString((**gPreferences).fScriptBaseName); |
if (RegCreateKeyEx(HKEY_CURRENT_USER, mySubKeyName, 0L, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &myKey, &myAction) == ERROR_SUCCESS) { |
RegSetValueEx(myKey, kVRPrefs_ScriptLocTypeLabel, 0L, REG_DWORD, (BYTE *)&((**gPreferences).fScriptLocType), sizeof(DWORD)); |
RegSetValueEx(myKey, kVRPrefs_ScriptPathNameLabel, 0L, REG_SZ, (BYTE *)myPathName, strlen(myPathName)); |
RegSetValueEx(myKey, kVRPrefs_ScriptNameTypeLabel, 0L, REG_DWORD, (BYTE *)&((**gPreferences).fScriptNameType), sizeof(DWORD)); |
RegSetValueEx(myKey, kVRPrefs_ScriptBaseNameLabel, 0L, REG_SZ, (BYTE *)myBaseName, strlen(myBaseName)); |
RegCloseKey(myKey); |
} |
free(myPathName); |
free(myBaseName); |
#endif |
#if TARGET_OS_MAC |
FSSpec myFSSpec; |
short myRefNum = 0; |
short myVolNum; |
long mySize = 0; |
OSErr myErr = noErr; |
// find the location of the preferences file |
myErr = VRPrefs_GetPrefsFileFSSpec(kVRPrefs_PrefsFileName, &myFSSpec); |
if ((myErr != noErr) && (myErr != fnfErr)) |
goto bail; |
mySize = GetHandleSize((Handle)gPreferences); |
if (mySize == 0) |
goto bail; |
HLock((Handle)gPreferences); |
// if the preferences file doesn't exist yet, then create it |
if (!(**gPreferences).fPrefsFileExists) |
myErr = FSpCreate(&myFSSpec, kScriptFileCreator, kPrefsFileType, smSystemScript); |
// open the file |
if (myErr == noErr) |
myErr = FSpOpenDF(&myFSSpec, fsRdWrPerm, &myRefNum); |
// position the file mark to the beginning of the file and write the data |
if (myErr == noErr) |
myErr = SetFPos(myRefNum, fsFromStart, 0); |
if (myErr == noErr) |
myErr = FSWrite(myRefNum, &mySize, *gPreferences); |
if (myErr == noErr) |
myErr = SetFPos(myRefNum, fsFromStart, mySize); |
// resize the file to the number of bytes written |
if (myErr == noErr) |
myErr = SetEOF(myRefNum, mySize); |
// close the file |
if (myErr == noErr) |
myErr = FSClose(myRefNum); |
// flush the volume |
if (myErr == noErr) |
myErr = GetVRefNum(myRefNum, &myVolNum); |
if (myErr == noErr) |
myErr = FlushVol(NULL, myVolNum); |
bail: |
HUnlock((Handle)gPreferences); |
#endif |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14