Demonstration Program Files
// *******************************************************************************************
// Files.h CARBON EVENT MODEL
// *******************************************************************************************
//
// This program demonstrates:
//
// o File operations associated with:
//
// o The user invoking the Open., Close, Save, Save As., Revert, and Quit commands of a
// typical application.
//
// o Handling of the required Apple events Open Application, Re-open Application, Open
// Documents, Print Documents, and Quit Application.
//
// o File synchronisation.
//
// o The creation, display, and handling of Open, Save Location, Choose a Folder, Save
// Changes, Discard Changes, and Review Unsaved dialogs and alerts using the new model
// introduced with Navigation Services 3.0.
//
// To keep the code not specifically related to files and file-handling to a minimum, an item
// is included in the Demonstration menu which allows the user to simulate "touching" a window
// (that is, modifying the contents of the associated document). Choosing the first menu item
// in this menu sets the window-touched flag in the window's document structure to true and
// draws the text "WINDOW TOUCHED" in the window in a large font size, this latter so that the
// user can keep track of which windows have been "touched".
//
// This program is also, in part, an extension of the demonstration program Windows2 in that
// it also demonstrates certain file-related Window Manager features introduced with the Mac
// OS 8.5 Window Manager. These features are:
//
// o Window proxy icons.
//
// o Window path pop-up menus.
//
// Those sections of the source code relating to these features are identified with ///// at
// the right of each line.
//
// The program utilises the following resources:
//
// o A 'plst' resource containing an information property list which provides information
// to the Mac OS X Finder.
//
// o An 'MBAR' resource, and 'MENU' and 'xmnu' resources for Apple, File, Edit and
// Demonstration menus (preload, non-purgeable).
//
// o A 'STR ' resource containing the "missing application name" string, which is copied to
// all document files created by the program.
//
// o 'STR#' resources (purgeable) containing error strings, the application's name (for
// certain Navigation Services functions), and a message string for the Choose a Folder
// dialog.
//
// o An 'open' resource (purgeable) containing the file type list for the Open dialog.
//
// o A 'kind' resource (purgeable) describing file types, which is used by Navigation
// Services to build the native file types section of the Show pop-up menu in the Open
// dialog.
//
// o Two 'pnot' resources (purgeable) which, together with an associated 'PICT' resource
// (purgeable) and a 'TEXT' resource created by the program, provide the previews for
// the PICT and, on Mac OS 8/9, TEXT files.
//
// o The 'BNDL' resource (non-purgeable), 'FREF' resources (non-purgeable), signature
// resource (non-purgeable), and icon family resources (purgeable), required to support the
// built application on Mac OS 8/9.
//
// o A 'SIZE' resource with the acceptSuspendResumeEvents, canBackground,
// doesActivateOnFGSwitch, and isHighLevelEventAware flags set.
//
// *******************************************************************************************
// .................................................................................. includes
#include <Carbon.h>
// ................................................................................... defines
#define rMenubar 128
#define mAppleApplication 128
#define Apple_About 'abou'
#define mFile 129
#define File_New 'new '
#define File_Open 'open'
#define File_Close 'clos'
#define File_Save 'save'
#define File_SaveAs 'sava'
#define File_Revert 'reve'
#define File_Quit 'quit'
#define iQuit 12
#define mDemonstration 131
#define Demo_TouchWindow 'touc'
#define Demo_ChooseAFolderDialog 'choo'
#define rErrorStrings 128
#define eInstallHandler 1000
#define eMaxWindows 1001
#define eCantFindFinderProcess 1002 /////
#define rMiscStrings 129
#define sApplicationName 1
#define sChooseAFolder 2
#define rOpenResource 128
#define kMaxWindows 10
#define kFileCreator 'Kjbb'
#define kFileTypeTEXT 'TEXT'
#define kFileTypePICT 'PICT'
#define kOpen 0
#define kPrint 1
#define MIN(a,b) ((a) < (b) ? (a) : (b))
// .................................................................................. typedefs
typedef struct
{
TEHandle editStrucHdl;
PicHandle pictureHdl;
SInt16 fileRefNum;
FSSpec fileFSSpec;
AliasHandle aliasHdl;
Boolean windowTouched;
NavDialogRef modalToWindowNavDialogRef;
NavEventUPP askSaveDiscardEventFunctionUPP;
Boolean isAskSaveChangesDialog;
} docStructure, *docStructurePointer, **docStructureHandle;
// ....................................................................... function prototypes
void main (void);
void eventLoop (void);
void doPreliminaries (void);
void doInstallAEHandlers (void);
OSStatus appEventHandler (EventHandlerCallRef,EventRef,void *);
OSStatus windowEventHandler (EventHandlerCallRef,EventRef,void *);
void doIdle (void);
void doDrawContent (WindowRef);
void doMenuChoice (MenuCommand);
void doAdjustMenus (void);
void doErrorAlert (SInt16);
void doCopyPString (Str255,Str255);
void doConcatPStrings (Str255,Str255);
void doTouchWindow (void);
OSErr openAppEventHandler (AppleEvent *,AppleEvent *,SInt32);
OSErr reopenAppEventHandler (AppleEvent *,AppleEvent *,SInt32);
OSErr openAndPrintDocsEventHandler (AppleEvent *,AppleEvent *,SInt32);
OSErr quitAppEventHandler (AppleEvent *,AppleEvent *,SInt32);
OSErr doHasGotRequiredParams (AppleEvent *);
SInt16 doReviewChangesAlert (SInt16);
OSErr doNewCommand (void);
OSErr doOpenCommand (void);
OSErr doCloseCommand (NavAskSaveChangesAction);
OSErr doSaveCommand (void);
OSErr doSaveAsCommand (void);
OSErr doRevertCommand (void);
OSErr doNewDocWindow (Boolean,OSType,WindowRef *);
EventHandlerUPP doGetHandlerUPP (void);
OSErr doCloseDocWindow (WindowRef);
OSErr doOpenFile (FSSpec,OSType);
OSErr doReadTextFile (WindowRef);
OSErr doReadPictFile (WindowRef);
OSErr doCreateAskSaveChangesDialog (WindowRef,docStructureHandle,NavAskSaveChangesAction);
OSErr doSaveUsingFSSpec (WindowRef,NavReplyRecord *);
OSErr doSaveUsingFSRef (WindowRef,NavReplyRecord *);
OSErr doWriteFile (WindowRef);
OSErr doWriteTextData (WindowRef,SInt16);
OSErr doWritePictData (WindowRef,SInt16);
void getFilePutFileEventFunction (NavEventCallbackMessage,NavCBRecPtr,NavCallBackUserData);
void askSaveDiscardEventFunction (NavEventCallbackMessage,NavCBRecPtr,NavCallBackUserData);
OSErr doCopyResources (WindowRef);
OSErr doCopyAResource (ResType,SInt16,SInt16,SInt16);
void doSynchroniseFiles (void);
OSErr doChooseAFolderDialog (void);
// *******************************************************************************************
// Files.c
// *******************************************************************************************
// .................................................................................. includes
#include "Files.h"
// .......................................................................... global variables
Boolean gRunningOnX = false;
SInt16 gAppResFileRefNum;
NavEventUPP gGetFilePutFileEventFunctionUPP ;
Boolean gQuittingApplication = false;
extern SInt16 gCurrentNumberOfWindows;
extern Rect gDestRect,gViewRect;
// ************************************************************************************** main
void main(void)
{
MenuBarHandle menubarHdl;
SInt32 response;
MenuRef menuRef;
EventTypeSpec applicationEvents[] = { { kEventClassApplication, kEventAppActivated },
{ kEventClassCommand, kEventProcessCommand },
{ kEventClassMenu, kEventMenuEnableItems } };
EventLoopTimerRef timerRef;
// ........................................................................ do preliminaries
doPreliminaries();
// .................................. save application's resource file file reference number
gAppResFileRefNum = CurResFile();
// ............................................................... set up menu bar and menus
menubarHdl = GetNewMBar(rMenubar);
if(menubarHdl == NULL)
doErrorAlert(MemError());
SetMenuBar(menubarHdl);
DrawMenuBar();
Gestalt(gestaltMenuMgrAttr,&response);
if(response & gestaltMenuMgrAquaLayoutMask)
{
menuRef = GetMenuRef(mFile);
if(menuRef != NULL)
{
DeleteMenuItem(menuRef,iQuit);
DeleteMenuItem(menuRef,iQuit - 1);
}
gRunningOnX = true;
}
else
{
menuRef = GetMenuRef(mFile);
if(menuRef != NULL)
SetMenuItemCommandID(menuRef,iQuit,kHICommandQuit);
}
// ................................................... install required Apple event handlers
doInstallAEHandlers();
// ....................................................... install application event handler
InstallApplicationEventHandler(NewEventHandlerUPP((EventHandlerProcPtr) appEventHandler),
GetEventTypeCount(applicationEvents),applicationEvents,
0,NULL);
// .............................................. install a timer (for file synchronisation)
InstallEventLoopTimer(GetCurrentEventLoop(),0,TicksToEventTime(15),
NewEventLoopTimerUPP((EventLoopTimerProcPtr) doIdle),NULL,
&timerRef);
// ..... get universal procedure pointer to main Navigation Services services event function
gGetFilePutFileEventFunctionUPP =
NewNavEventUPP((NavEventProcPtr) getFilePutFileEventFunction);
// .............................................................. run application event loop
RunApplicationEventLoop();
}
// *************************************************************************** doPreliminaries
void doPreliminaries(void)
{
MoreMasterPointers(448);
InitCursor();
}
// *********************************************************************** doInstallAEHandlers
void doInstallAEHandlers(void)
{
OSErr osError;
osError = AEInstallEventHandler(kCoreEventClass,kAEOpenApplication,
NewAEEventHandlerUPP((AEEventHandlerProcPtr) openAppEventHandler),
0L,false);
if(osError != noErr) doErrorAlert(eInstallHandler);
osError = AEInstallEventHandler(kCoreEventClass,kAEReopenApplication,
NewAEEventHandlerUPP((AEEventHandlerProcPtr) reopenAppEventHandler),
0L,false);
if(osError != noErr) doErrorAlert(eInstallHandler);
osError = AEInstallEventHandler(kCoreEventClass,kAEOpenDocuments,
NewAEEventHandlerUPP((AEEventHandlerProcPtr) openAndPrintDocsEventHandler),
kOpen,false);
if(osError != noErr) doErrorAlert(eInstallHandler);
osError = AEInstallEventHandler(kCoreEventClass,kAEPrintDocuments,
NewAEEventHandlerUPP((AEEventHandlerProcPtr) openAndPrintDocsEventHandler),
kPrint,false);
if(osError != noErr) doErrorAlert(eInstallHandler);
osError = AEInstallEventHandler(kCoreEventClass,kAEQuitApplication,
NewAEEventHandlerUPP((AEEventHandlerProcPtr) quitAppEventHandler),
0L,false);
if(osError != noErr) doErrorAlert(eInstallHandler);
}
// *************************************************************************** appEventHandler
OSStatus appEventHandler(EventHandlerCallRef eventHandlerCallRef,EventRef eventRef,
void * userData)
{
OSStatus result = eventNotHandledErr;
UInt32 eventClass;
UInt32 eventKind;
HICommand hiCommand;
MenuID menuID;
MenuItemIndex menuItem;
eventClass = GetEventClass(eventRef);
eventKind = GetEventKind(eventRef);
switch(eventClass)
{
case kEventClassApplication:
if(eventKind == kEventAppActivated)
SetThemeCursor(kThemeArrowCursor);
break;
case kEventClassCommand:
if(eventKind == kEventProcessCommand)
{
GetEventParameter(eventRef,kEventParamDirectObject,typeHICommand,NULL,
sizeof(HICommand),NULL,&hiCommand);
menuID = GetMenuID(hiCommand.menu.menuRef);
menuItem = hiCommand.menu.menuItemIndex;
if((hiCommand.commandID != kHICommandQuit) &&
(menuID >= mAppleApplication && menuID <= mDemonstration))
{
doMenuChoice(hiCommand.commandID);
result = noErr;
}
}
break;
case kEventClassMenu:
if(eventKind == kEventMenuEnableItems)
{
doAdjustMenus();
result = noErr;
}
break;
}
return result;
}
// ************************************************************************ windowEventHandler
OSStatus windowEventHandler(EventHandlerCallRef eventHandlerCallRef,EventRef eventRef,
void* userData)
{
OSStatus result = eventNotHandledErr;
UInt32 eventClass;
UInt32 eventKind;
WindowRef windowRef;
eventClass = GetEventClass(eventRef);
eventKind = GetEventKind(eventRef);
switch(eventClass)
{
case kEventClassWindow:
GetEventParameter(eventRef,kEventParamDirectObject,typeWindowRef,NULL,sizeof(windowRef),
NULL,&windowRef);
switch(eventKind)
{
case kEventWindowDrawContent:
doDrawContent(windowRef);
result = noErr;
break;
case kEventWindowClose:
if(gQuittingApplication)
doCloseCommand(kNavSaveChangesQuittingApplication);
else
doCloseCommand(kNavSaveChangesClosingDocument);
result = noErr;
break;
}
break;
}
return result;
}
// ************************************************************************************ doIdle
void doIdle(void)
{
if(GetWindowKind(FrontWindow()) == kApplicationWindowKind)
doSynchroniseFiles();
}
// ********************************************************************************** doUpdate
void doDrawContent(WindowRef windowRef)
{
docStructureHandle docStrucHdl;
GrafPtr oldPort;
Rect destRect;
docStrucHdl = (docStructureHandle) GetWRefCon(windowRef);
GetPort(&oldPort);
SetPortWindowPort(windowRef);
if((*docStrucHdl)->pictureHdl)
{
destRect = (*(*docStrucHdl)->pictureHdl)->picFrame;
OffsetRect(&destRect,170,54);
HLock((Handle) (*docStrucHdl)->pictureHdl);
DrawPicture((*docStrucHdl)->pictureHdl,&destRect);
HUnlock((Handle) (*docStrucHdl)->pictureHdl);
}
else if((*docStrucHdl)->editStrucHdl)
{
HLock((Handle) (*docStrucHdl)->editStrucHdl);
TEUpdate(&gDestRect,(*docStrucHdl)->editStrucHdl);
HUnlock((Handle) (*docStrucHdl)->editStrucHdl);
}
if((*docStrucHdl)->windowTouched)
{
TextSize(48);
MoveTo(30,170);
DrawString("\pWINDOW TOUCHED");
TextSize(12);
}
SetPort(oldPort);
}
// ****************************************************************************** doMenuChoice
void doMenuChoice(MenuCommand commandID)
{
OSErr osError = noErr;
switch(commandID)
{
// ................................................................ Apple/Application menu
case Apple_About:
SysBeep(10);
break;
// ............................................................................. File menu
case File_New:
if(osError = doNewCommand())
doErrorAlert(osError);
break;
case File_Open:
if(osError = doOpenCommand() && osError == opWrErr)
doErrorAlert(osError);
break;
case File_Close:
if(osError = doCloseCommand(kNavSaveChangesClosingDocument))
doErrorAlert(osError);
break;
case File_Save:
if(osError = doSaveCommand())
doErrorAlert(osError);
break;
case File_SaveAs:
if(osError = doSaveAsCommand())
doErrorAlert(osError);
break;
case File_Revert:
if(osError = doRevertCommand())
doErrorAlert(osError);
break;
// .................................................................... Demonstration menu
case Demo_TouchWindow:
doTouchWindow();
break;
case Demo_ChooseAFolderDialog:
if(osError = doChooseAFolderDialog())
doErrorAlert(osError);
break;
}
}
// ***************************************************************************** doAdjustMenus
void doAdjustMenus(void)
{
OSErr osError;
MenuRef menuRef;
WindowRef windowRef;
docStructureHandle docStrucHdl;
if(gCurrentNumberOfWindows > 0)
{
if(gRunningOnX)
{
if((osError = GetSheetWindowParent(FrontWindow(),&windowRef)) == noErr)
{
menuRef = GetMenuRef(mFile);
DisableMenuCommand(menuRef,File_Close);
DisableMenuCommand(menuRef,File_Save);
DisableMenuCommand(menuRef,File_SaveAs);
DisableMenuCommand(menuRef,File_Revert);
menuRef = GetMenuRef(mDemonstration);
DisableMenuCommand(menuRef,Demo_TouchWindow);
return;
}
else
windowRef = FrontWindow();
}
else
windowRef = FrontWindow();
if(GetWindowKind(windowRef) == kApplicationWindowKind)
{
docStrucHdl = (docStructureHandle) GetWRefCon(windowRef);
menuRef = GetMenuRef(mFile);
EnableMenuCommand(menuRef,File_Close);
if((*docStrucHdl)->windowTouched)
{
EnableMenuCommand(menuRef,File_Save);
EnableMenuCommand(menuRef,File_Revert);
}
else
{
DisableMenuCommand(menuRef,File_Save);
DisableMenuCommand(menuRef,File_Revert);
}
if(((*docStrucHdl)->pictureHdl != NULL) ||
((*(*docStrucHdl)->editStrucHdl)->teLength > 0))
EnableMenuCommand(menuRef,File_SaveAs);
else
DisableMenuCommand(menuRef,File_SaveAs);
menuRef = GetMenuRef(mDemonstration);
if(((*docStrucHdl)->pictureHdl != NULL) ||
((*(*docStrucHdl)->editStrucHdl)->teLength > 0))
{
if((*docStrucHdl)->windowTouched == false)
EnableMenuCommand(menuRef,Demo_TouchWindow);
else
DisableMenuCommand(menuRef,Demo_TouchWindow);
}
else
DisableMenuCommand(menuRef,Demo_TouchWindow);
}
}
else
{
menuRef = GetMenuRef(mFile);
DisableMenuCommand(menuRef,File_Close);
DisableMenuCommand(menuRef,File_Save);
DisableMenuCommand(menuRef,File_SaveAs);
DisableMenuCommand(menuRef,File_Revert);
menuRef = GetMenuRef(mDemonstration);
DisableMenuCommand(menuRef,Demo_TouchWindow);
}
DrawMenuBar();
}
// ****************************************************************************** doErrorAlert
void doErrorAlert(SInt16 errorCode)
{
Str255 errorString, theString;
SInt16 itemHit;
if(errorCode == eInstallHandler)
GetIndString(errorString,rErrorStrings,1);
else if(errorCode == eMaxWindows)
GetIndString(errorString,rErrorStrings,2);
else if(errorCode == eCantFindFinderProcess)
GetIndString(errorString,rErrorStrings,3);
else if(errorCode == opWrErr)
GetIndString(errorString,rErrorStrings,4);
else
{
GetIndString(errorString,rErrorStrings,5);
NumToString((SInt32) errorCode,theString);
doConcatPStrings(errorString,theString);
}
if(errorCode != memFullErr)
{
StandardAlert(kAlertCautionAlert,errorString,NULL,NULL,&itemHit);
}
else
{
StandardAlert(kAlertStopAlert,errorString,NULL,NULL,&itemHit);
ExitToShell();
}
}
// ***************************************************************************** doCopyPString
void doCopyPString(Str255 sourceString,Str255 destinationString)
{
SInt16 stringLength;
stringLength = sourceString[0];
BlockMove(sourceString + 1,destinationString + 1,stringLength);
destinationString[0] = stringLength;
}
// ************************************************************************** doConcatPStrings
void doConcatPStrings(Str255 targetString,Str255 appendString)
{
SInt16 appendLength;
appendLength = MIN(appendString[0],255 - targetString[0]);
if(appendLength > 0)
{
BlockMoveData(appendString+1,targetString+targetString[0]+1,(SInt32) appendLength);
targetString[0] += appendLength;
}
}
// ***************************************************************************** doTouchWindow
void doTouchWindow(void)
{
WindowRef windowRef;
docStructureHandle docStrucHdl;
windowRef = FrontWindow();
docStrucHdl = (docStructureHandle) GetWRefCon(windowRef);
SetPortWindowPort(windowRef);
TextSize(48);
MoveTo(30,170);
DrawString("\pWINDOW TOUCHED");
TextSize(12);
(*docStrucHdl)->windowTouched = true;
SetWindowModified(windowRef,true); /////
}
// *********************************************************************** openAppEventHandler
OSErr openAppEventHandler(AppleEvent *appEvent,AppleEvent *reply,SInt32 handlerRefCon)
{
OSErr osError;
osError = doHasGotRequiredParams(appEvent);
if(osError == noErr)
osError = doNewCommand();
return osError;
}
// ********************************************************************* reopenAppEventHandler
OSErr reopenAppEventHandler(AppleEvent *appEvent,AppleEvent *reply,
SInt32 handlerRefCon)
{
OSErr osError;
osError = doHasGotRequiredParams(appEvent);
if(osError == noErr)
if(!FrontWindow())
osError = doNewCommand();
return osError;
}
// ************************************************************** openAndPrintDocsEventHandler
OSErr openAndPrintDocsEventHandler(AppleEvent *appEvent,AppleEvent *reply,
SInt32 handlerRefcon)
{
FSSpec fileSpec;
AEDescList docList;
OSErr osError, ignoreErr;
SInt32 index, numberOfItems;
Size actualSize;
AEKeyword keyWord;
DescType returnedType;
FInfo fileInfo;
osError = AEGetParamDesc(appEvent,keyDirectObject,typeAEList,&docList);
if(osError == noErr)
{
osError = doHasGotRequiredParams(appEvent);
if(osError == noErr)
{
osError = AECountItems(&docList,&numberOfItems);
if(osError == noErr)
{
for(index=1;index<=numberOfItems;index++)
{
osError = AEGetNthPtr(&docList,index,typeFSS,&keyWord,&returnedType,
&fileSpec,sizeof(fileSpec),&actualSize);
if(osError == noErr)
{
osError = FSpGetFInfo(&fileSpec,&fileInfo);
if(osError == noErr)
{
if(osError = doOpenFile(fileSpec,fileInfo.fdType))
doErrorAlert(osError);
if(osError == noErr && handlerRefcon == kPrint)
{
// Call printing function here
}
}
}
else
doErrorAlert(osError);
}
}
}
else
doErrorAlert(osError);
ignoreErr = AEDisposeDesc(&docList);
}
else
doErrorAlert(osError);
return osError;
}
// *********************************************************************** quitAppEventHandler
OSErr quitAppEventHandler(AppleEvent *appEvent,AppleEvent *reply,SInt32 handlerRefcon)
{
OSErr osError;
WindowRef windowRef, previousWindowRef;
docStructureHandle docStrucHdl;
SInt16 touchedWindowsCount = 0;
EventRef eventRef;
EventTargetRef eventTargetRef;
SInt16 itemHit;
osError = doHasGotRequiredParams(appEvent);
if(osError == noErr)
{
if(FrontWindow())
{
// ...... if any window has a sheet, bring to front, play system alert sound, and return
windowRef = GetFrontWindowOfClass(kSheetWindowClass,true);
if(windowRef)
{
SelectWindow(windowRef);
SysBeep(10);
return noErr;
}
// ............................................................... count touched windows
windowRef = FrontWindow();
do
{
docStrucHdl = (docStructureHandle) GetWRefCon(windowRef);
if((*docStrucHdl)->windowTouched == true)
touchedWindowsCount++;
previousWindowRef = windowRef;
} while(windowRef = GetNextWindowOfClass(previousWindowRef,kDocumentWindowClass,true));
// ............................................ if no touched windows, simply close down
if(touchedWindowsCount == 0)
QuitApplicationEventLoop();
// .............................. if touched windows are present, and if running on OS X
if(gRunningOnX)
{
// .. if one touched window, cause Save Changes alert on that window, close all others
if(touchedWindowsCount == 1)
{
gQuittingApplication = true;
CreateEvent(NULL,kEventClassWindow,kEventWindowClose,0,kEventAttributeNone,
&eventRef);
eventTargetRef = GetWindowEventTarget(FrontWindow());
SendEventToEventTarget(eventRef,eventTargetRef);
}
// .. if more than one touched window, create Review Changes alert, handle button clicks
else if(touchedWindowsCount > 1)
{
itemHit = doReviewChangesAlert(touchedWindowsCount);
if(itemHit == kAlertStdAlertOKButton)
{
gQuittingApplication = true;
CreateEvent(NULL,kEventClassWindow,kEventWindowClose,0,kEventAttributeNone,
&eventRef);
eventTargetRef = GetWindowEventTarget(FrontWindow());
SendEventToEventTarget(eventRef,eventTargetRef);
}
else if(itemHit == kAlertStdAlertCancelButton)
gQuittingApplication = false;
else if(itemHit == kAlertStdAlertOtherButton)
QuitApplicationEventLoop();
}
}
// ............................ if touched windows are present, and if running on OS 8/9
else
{
gQuittingApplication = true;
CreateEvent(NULL,kEventClassWindow,kEventWindowClose,0,kEventAttributeNone,
&eventRef);
eventTargetRef = GetWindowEventTarget(FrontWindow());
SendEventToEventTarget(eventRef,eventTargetRef);
}
}
else
QuitApplicationEventLoop();
}
return osError;
}
// ******************************************************************** doHasGotRequiredParams
OSErr doHasGotRequiredParams(AppleEvent *appEvent)
{
DescType returnedType;
Size actualSize;
OSErr osError;
osError = AEGetAttributePtr(appEvent,keyMissedKeywordAttr,typeWildCard,&returnedType,
NULL,0,&actualSize);
if(osError == errAEDescNotFound)
osError = noErr;
else if(osError == noErr)
osError = errAEParamMissed;
return osError;
}
// ********************************************************************** doReviewChangesAlert
SInt16 doReviewChangesAlert(SInt16 touchedWindowsCount)
{
AlertStdCFStringAlertParamRec paramRec;
Str255 messageText1 = "\pYou have ";
Str255 messageText2 = "\p Files documents with unsaved changes. ";
Str255 messageText3 = "\pDo you want to review these changes before quitting?";
Str255 countString;
CFStringRef messageText;
CFStringRef informativeText =
CFSTR("If you don't review your documents, all your changes will be lost.");
DialogRef dialogRef;
DialogItemIndex itemHit;
NumToString(touchedWindowsCount,countString);
doConcatPStrings(messageText1,countString);
doConcatPStrings(messageText1,messageText2);
doConcatPStrings(messageText1,messageText3);
messageText = CFStringCreateWithPascalString(NULL,messageText1,CFStringGetSystemEncoding());
GetStandardAlertDefaultParams(¶mRec,kStdCFStringAlertVersionOne);
paramRec.movable = true;
paramRec.defaultText = CFSTR("Review Changes.");
paramRec.cancelText = CFSTR("Cancel");
paramRec.otherText = CFSTR("Discard Changes");
CreateStandardAlert(kAlertStopAlert,messageText,informativeText,¶mRec,&dialogRef);
RunStandardAlert(dialogRef,NULL,&itemHit);
if(messageText != NULL)
CFRelease(messageText);
return itemHit;
}
// *******************************************************************************************
// NewOpenCloseSave.c
// *******************************************************************************************
// .................................................................................. includes
#include "Files.h"
// .......................................................................... global variables
NavDialogRef gModalToApplicationNavDialogRef;
SInt16 gCurrentNumberOfWindows = 0;
Rect gDestRect, gViewRect;
Boolean gCloseDocWindow = false;
extern NavEventUPP gGetFilePutFileEventFunctionUPP;
extern SInt16 gAppResFileRefNum;
extern Boolean gQuittingApplication;
extern Boolean gRunningOnX;
// ****************************************************************************** doNewCommand
OSErr doNewCommand(void)
{
WindowRef windowRef;
OSErr osError;
OSType documentType = kFileTypeTEXT;
osError = doNewDocWindow(true,documentType,&windowRef);
if(osError == noErr)
SetWindowProxyCreatorAndType(windowRef,kFileCreator,documentType,kUserDomain); /////
return osError;
}
// ***************************************************************************** doOpenCommand
OSErr doOpenCommand(void)
{
OSErr osError = noErr;
NavDialogCreationOptions dialogOptions;
Str255 applicationName;
NavTypeListHandle fileTypeListHdl = NULL;
// .................................................... create application-modal Open dialog
osError = NavGetDefaultDialogCreationOptions(&dialogOptions);
if(osError == noErr)
{
GetIndString(applicationName,rMiscStrings,sApplicationName);
dialogOptions.clientName = CFStringCreateWithPascalString(NULL,applicationName,
CFStringGetSystemEncoding());
dialogOptions.modality = kWindowModalityAppModal;
fileTypeListHdl = (NavTypeListHandle) GetResource('open',rOpenResource);
osError = NavCreateGetFileDialog(&dialogOptions,fileTypeListHdl,
gGetFilePutFileEventFunctionUPP,NULL,NULL,NULL,
&gModalToApplicationNavDialogRef);
if(osError == noErr && gModalToApplicationNavDialogRef != NULL)
{
osError = NavDialogRun(gModalToApplicationNavDialogRef);
if(osError != noErr)
{
NavDialogDispose(gModalToApplicationNavDialogRef);
gModalToApplicationNavDialogRef = NULL;
}
}
if(dialogOptions.clientName != NULL)
CFRelease(dialogOptions.clientName);
if(fileTypeListHdl != NULL)
ReleaseResource((Handle) fileTypeListHdl);
}
return osError;
}
// **************************************************************************** doCloseCommand
OSErr doCloseCommand(NavAskSaveChangesAction action)
{
WindowRef windowRef;
SInt16 windowKind;
docStructureHandle docStrucHdl;
OSErr osError = noErr;
windowRef = FrontWindow();
windowKind = GetWindowKind(windowRef);
switch(windowKind)
{
case kApplicationWindowKind:
docStrucHdl = (docStructureHandle) GetWRefCon(windowRef);
// ............................ if window has unsaved changes, create Save Changes alert
if((*docStrucHdl)->windowTouched == true)
{
if(IsWindowCollapsed(windowRef))
CollapseWindow(windowRef,false);
osError = doCreateAskSaveChangesDialog(windowRef,docStrucHdl,action);
}
// ................................................... otherwise close file and clean up
else
osError = doCloseDocWindow(windowRef);
break;
case kDialogWindowKind:
// Hide or close modeless dialog, as required.
break;
}
return osError;
}
// ***************************************************************************** doSaveCommand
OSErr doSaveCommand(void)
{
WindowRef windowRef;
docStructureHandle docStrucHdl;
OSErr osError = noErr;
Rect portRect;
windowRef = FrontWindow();
docStrucHdl = (docStructureHandle) GetWRefCon(windowRef);
// ... if the document has a file ref number, write the file, otherwise call doSaveAsCommand
if((*docStrucHdl)->fileRefNum)
{
osError = doWriteFile(windowRef);
SetPortWindowPort(windowRef);
GetWindowPortBounds(windowRef,&portRect);
EraseRect(&portRect);
InvalWindowRect(windowRef,&portRect);
}
else
osError = doSaveAsCommand();
if(osError == noErr) /////
SetWindowModified(windowRef,false); /////
return osError;
}
// *************************************************************************** doSaveAsCommand
OSErr doSaveAsCommand(void)
{
OSErr osError = noErr;
NavDialogCreationOptions dialogOptions;
WindowRef windowRef;
Str255 windowTitle, applicationName;
docStructureHandle docStrucHdl;
OSType fileType;
// ................................................ create window-modal Save Location dialog
osError = NavGetDefaultDialogCreationOptions(&dialogOptions);
if(osError == noErr)
{
dialogOptions.optionFlags |= kNavNoTypePopup;
windowRef = FrontWindow();
GetWTitle(windowRef,windowTitle);
dialogOptions.saveFileName = CFStringCreateWithPascalString(NULL,windowTitle,
CFStringGetSystemEncoding());
GetIndString(applicationName,rMiscStrings,sApplicationName);
dialogOptions.clientName = CFStringCreateWithPascalString(NULL,applicationName,
CFStringGetSystemEncoding());
dialogOptions.parentWindow = windowRef;
dialogOptions.modality = kWindowModalityWindowModal;
docStrucHdl = (docStructureHandle) GetWRefCon(windowRef);
if((*docStrucHdl)->editStrucHdl != NULL)
fileType = kFileTypeTEXT;
else if((*docStrucHdl)->pictureHdl != NULL)
fileType = kFileTypePICT;
HLock((Handle) docStrucHdl);
osError = NavCreatePutFileDialog(&dialogOptions,fileType,kFileCreator,
gGetFilePutFileEventFunctionUPP ,
windowRef,&(*docStrucHdl)->modalToWindowNavDialogRef);
HUnlock((Handle) docStrucHdl);
if(osError == noErr && (*docStrucHdl)->modalToWindowNavDialogRef != NULL)
{
osError = NavDialogRun((*docStrucHdl)->modalToWindowNavDialogRef);
if(osError != noErr)
{
NavDialogDispose((*docStrucHdl)->modalToWindowNavDialogRef);
(*docStrucHdl)->modalToWindowNavDialogRef = NULL;
}
}
if(dialogOptions.saveFileName != NULL)
CFRelease(dialogOptions.saveFileName);
if(dialogOptions.clientName != NULL)
CFRelease(dialogOptions.clientName);
}
return osError;
}
// *************************************************************************** doRevertCommand
OSErr doRevertCommand(void)
{
OSErr osError = noErr;
NavDialogCreationOptions dialogOptions;
WindowRef windowRef;
Str255 windowTitle;
docStructureHandle docStrucHdl;
// ............................................... create window-modal Discard Changes alert
osError = NavGetDefaultDialogCreationOptions(&dialogOptions);
if(osError == noErr)
{
windowRef = FrontWindow();
GetWTitle(windowRef,windowTitle);
dialogOptions.saveFileName = CFStringCreateWithPascalString(NULL,windowTitle,
CFStringGetSystemEncoding());
dialogOptions.parentWindow = windowRef;
dialogOptions.modality = kWindowModalityWindowModal;
docStrucHdl = (docStructureHandle) GetWRefCon(windowRef);
if((*docStrucHdl)->askSaveDiscardEventFunctionUPP != NULL)
{
DisposeNavEventUPP((*docStrucHdl)->askSaveDiscardEventFunctionUPP);
(*docStrucHdl)->askSaveDiscardEventFunctionUPP = NULL;
}
(*docStrucHdl)->askSaveDiscardEventFunctionUPP =
NewNavEventUPP((NavEventProcPtr) askSaveDiscardEventFunction);
HLock((Handle) docStrucHdl);
osError = NavCreateAskDiscardChangesDialog(&dialogOptions,
(*docStrucHdl)->askSaveDiscardEventFunctionUPP,
windowRef,
&(*docStrucHdl)->modalToWindowNavDialogRef);
HUnlock((Handle) docStrucHdl);
if(osError == noErr && (*docStrucHdl)->modalToWindowNavDialogRef != NULL)
{
osError = NavDialogRun((*docStrucHdl)->modalToWindowNavDialogRef);
if(osError != noErr)
{
NavDialogDispose((*docStrucHdl)->modalToWindowNavDialogRef);
(*docStrucHdl)->modalToWindowNavDialogRef = NULL;
}
}
if(dialogOptions.saveFileName != NULL)
CFRelease(dialogOptions.saveFileName);
}
return osError;
}
// **************************************************************************** doNewDocWindow
OSErr doNewDocWindow(Boolean showWindow,OSType documentType,WindowRef * windowRef)
{
OSStatus osError;
WindowAttributes attributes = kWindowStandardHandlerAttribute |
kWindowStandardDocumentAttributes;
Rect portRect, contentRect = { 0,0,300,500 };
docStructureHandle docStrucHdl;
EventTypeSpec windowEvents[] = { { kEventClassWindow, kEventWindowDrawContent },
{ kEventClassWindow, kEventWindowClose },
{ kEventClassWindow, kEventWindowClickDragRgn },
{ kEventClassWindow, kEventWindowPathSelect } };
if(gCurrentNumberOfWindows == kMaxWindows)
return eMaxWindows;
// ..................... create window, change attributes, reposition, install event handler
osError = CreateNewWindow(kDocumentWindowClass,attributes,&contentRect,windowRef);
if(osError != noErr)
return osError;
SetWTitle(*windowRef,"\puntitled");
ChangeWindowAttributes(*windowRef,0,kWindowFullZoomAttribute | kWindowResizableAttribute);
RepositionWindow(*windowRef,NULL,kWindowCascadeOnMainScreen);
SetPortWindowPort(*windowRef);
InstallWindowEventHandler(*windowRef,doGetHandlerUPP(),GetEventTypeCount(windowEvents),
windowEvents,0,NULL);
// ..................................................... attach document structure to window
if(!(docStrucHdl = (docStructureHandle) NewHandle(sizeof(docStructure))))
{
DisposeWindow(*windowRef);
return MemError();
}
SetWRefCon(*windowRef,(SInt32) docStrucHdl);
(*docStrucHdl)->editStrucHdl = NULL;
(*docStrucHdl)->pictureHdl = NULL;
(*docStrucHdl)->fileRefNum = 0;
(*docStrucHdl)->aliasHdl = NULL; /////
(*docStrucHdl)->windowTouched = false;
(*docStrucHdl)->modalToWindowNavDialogRef = NULL;
(*docStrucHdl)->askSaveDiscardEventFunctionUPP = NULL;
(*docStrucHdl)->isAskSaveChangesDialog = false;
// ............................................. if text document, create TextEdit structure
if(documentType == kFileTypeTEXT)
{
UseThemeFont(kThemeSmallSystemFont,smSystemScript);
GetWindowPortBounds(*windowRef,&portRect);
gDestRect = portRect;
InsetRect(&gDestRect,6,6);
gViewRect = gDestRect;
MoveHHi((Handle) docStrucHdl);
HLock((Handle) docStrucHdl);
if(!((*docStrucHdl)->editStrucHdl = TENew(&gDestRect,&gViewRect)))
{
DisposeWindow(*windowRef);
DisposeHandle((Handle) docStrucHdl);
return MemError();
}
HUnlock((Handle) docStrucHdl);
}
// ............................................ show window and increment open windows count
if(showWindow)
ShowWindow(*windowRef);
gCurrentNumberOfWindows ++;
return noErr;
}
// *************************************************************************** doGetHandlerUPP
EventHandlerUPP doGetHandlerUPP(void)
{
static EventHandlerUPP windowEventHandlerUPP;
if(windowEventHandlerUPP == NULL)
windowEventHandlerUPP = NewEventHandlerUPP((EventHandlerProcPtr) windowEventHandler);
return windowEventHandlerUPP;
}
// ************************************************************************** doCloseDocWindow
OSErr doCloseDocWindow(WindowRef windowRef)
{
docStructureHandle docStrucHdl;
OSErr osError = noErr;
EventRef eventRef;
EventTargetRef eventTargetRef;
docStrucHdl = (docStructureHandle) GetWRefCon(windowRef);
// ....................... close file, flush volume, dispose of window and associated memory
if((*docStrucHdl)->fileRefNum != 0)
{
if(!(osError = FSClose((*docStrucHdl)->fileRefNum)))
{
osError = FlushVol(NULL,(*docStrucHdl)->fileFSSpec.vRefNum);
(*docStrucHdl)->fileRefNum = 0;
}
}
if((*docStrucHdl)->editStrucHdl != NULL)
TEDispose((*docStrucHdl)->editStrucHdl);
if((*docStrucHdl)->pictureHdl != NULL)
KillPicture((*docStrucHdl)->pictureHdl);
DisposeHandle((Handle) docStrucHdl);
DisposeWindow(windowRef);
gCurrentNumberOfWindows --;
// ................................................................. if quitting application
if(gQuittingApplication)
{
if(FrontWindow() == NULL)
QuitApplicationEventLoop();
else
{
CreateEvent(NULL,kEventClassWindow,kEventWindowClose,0,kEventAttributeNone,
&eventRef);
eventTargetRef = GetWindowEventTarget(FrontWindow());
SendEventToEventTarget(eventRef,eventTargetRef);
}
}
return osError;
}
// ******************************************************************************** doOpenFile
OSErr doOpenFile(FSSpec fileSpec,OSType documentType)
{
WindowRef windowRef;
OSErr osError = noErr;
SInt16 fileRefNum;
docStructureHandle docStrucHdl;
// ....................................................................... create new window
if(osError = doNewDocWindow(false,documentType,&windowRef))
return osError;
SetWTitle(windowRef,fileSpec.name);
// ................................................................... open file's data fork
if(osError = FSpOpenDF(&fileSpec,fsRdWrPerm,&fileRefNum))
{
DisposeWindow(windowRef);
gCurrentNumberOfWindows --;
return osError;
}
// ................... store file reference number and FSSpec in window's document structure
docStrucHdl = (docStructureHandle) GetWRefCon(windowRef);
(*docStrucHdl)->fileRefNum = fileRefNum;
(*docStrucHdl)->fileFSSpec = fileSpec;
// ........................................................................ read in the file
if(documentType == kFileTypeTEXT)
{
if(osError = doReadTextFile(windowRef))
return osError;
}
else if(documentType == kFileTypePICT)
{
if(osError = doReadPictFile(windowRef))
return osError;
}
// ............................................. set up window's proxy icon, and show window
SetWindowProxyFSSpec(windowRef,&fileSpec); /////
GetWindowProxyAlias(windowRef,&((*docStrucHdl)->aliasHdl)); /////
SetWindowModified(windowRef,false); /////
ShowWindow(windowRef);
return noErr;
}
// ************************************************************** doCreateAskSaveChangesDialog
OSErr doCreateAskSaveChangesDialog(WindowRef windowRef,docStructureHandle docStrucHdl,
NavAskSaveChangesAction action)
{
OSErr osError = noErr;
NavDialogCreationOptions dialogOptions;
Str255 windowTitle, applicationName;
// ......................................... create window-modal Save Changes Changes dialog
osError = NavGetDefaultDialogCreationOptions(&dialogOptions);
if(osError == noErr)
{
GetWTitle(windowRef,windowTitle);
dialogOptions.saveFileName = CFStringCreateWithPascalString(NULL,windowTitle,
CFStringGetSystemEncoding());
GetIndString(applicationName,rMiscStrings,sApplicationName);
dialogOptions.clientName = CFStringCreateWithPascalString(NULL,applicationName,
CFStringGetSystemEncoding());
dialogOptions.parentWindow = windowRef;
dialogOptions.modality = kWindowModalityWindowModal;
if((*docStrucHdl)->askSaveDiscardEventFunctionUPP != NULL)
{
DisposeNavEventUPP((*docStrucHdl)->askSaveDiscardEventFunctionUPP);
(*docStrucHdl)->askSaveDiscardEventFunctionUPP = NULL;
}
(*docStrucHdl)->askSaveDiscardEventFunctionUPP =
NewNavEventUPP((NavEventProcPtr) askSaveDiscardEventFunction);
HLock((Handle) docStrucHdl);
osError = NavCreateAskSaveChangesDialog(&dialogOptions,action,
(*docStrucHdl)->askSaveDiscardEventFunctionUPP,
windowRef,
&(*docStrucHdl)->modalToWindowNavDialogRef);
HUnlock((Handle) docStrucHdl);
if(osError == noErr && (*docStrucHdl)->modalToWindowNavDialogRef != NULL)
{
(*docStrucHdl)->isAskSaveChangesDialog = true;
osError = NavDialogRun((*docStrucHdl)->modalToWindowNavDialogRef);
if(osError != noErr)
{
NavDialogDispose((*docStrucHdl)->modalToWindowNavDialogRef);
(*docStrucHdl)->modalToWindowNavDialogRef = NULL;
(*docStrucHdl)->isAskSaveChangesDialog = false;
}
if(!gRunningOnX)
{
if(gCloseDocWindow)
{
osError = doCloseDocWindow(windowRef);
if(osError != noErr)
doErrorAlert(osError);
gCloseDocWindow = false;
}
}
}
if(dialogOptions.saveFileName != NULL)
CFRelease(dialogOptions.saveFileName);
if(dialogOptions.clientName != NULL)
CFRelease(dialogOptions.clientName);
}
return osError;
}
// ************************************************************************* doSaveUsingFSSpec
OSErr doSaveUsingFSSpec(WindowRef windowRef,NavReplyRecord *navReplyStruc)
{
OSErr osError = noErr;
AEKeyword theKeyword;
DescType actualType;
FSSpec fileSpec;
Size actualSize;
docStructureHandle docStrucHdl;
OSType fileType;
CFStringRef fileName;
SInt16 fileRefNum;
Rect portRect;
if((*navReplyStruc).validRecord)
{
// ............................................................................ get FSSpec
if((osError = AEGetNthPtr(&(*navReplyStruc).selection,1,typeFSS,&theKeyword,
&actualType,&fileSpec,sizeof(fileSpec),&actualSize)) == noErr)
{
docStrucHdl = (docStructureHandle) GetWRefCon(windowRef);
// ............. get file name, convert to Pascal string, assign to name field of FSSpec
fileName = NavDialogGetSaveFileName((*docStrucHdl)->modalToWindowNavDialogRef);
if(fileName != NULL)
osError = CFStringGetPascalString(fileName,&fileSpec.name[0],sizeof(FSSpec),
CFStringGetSystemEncoding());
// ........................................... if not replacing, first create a new file
if(!((*navReplyStruc).replacing))
{
if((*docStrucHdl)->editStrucHdl != NULL)
fileType = kFileTypeTEXT;
else if((*docStrucHdl)->pictureHdl != NULL)
fileType = kFileTypePICT;
osError = FSpCreate(&fileSpec,kFileCreator,fileType,(*navReplyStruc).keyScript);
if(osError != noErr)
{
NavDisposeReply(&(*navReplyStruc));
return osError;
}
}
// .................... assign FSSpec to fileFSSpec field of window's document structure
(*docStrucHdl)->fileFSSpec = fileSpec;
// ..................................... if file currently exists for document, close it
if((*docStrucHdl)->fileRefNum != 0)
{
osError = FSClose((*docStrucHdl)->fileRefNum);
(*docStrucHdl)->fileRefNum = 0;
}
// ................................................ open file's data fork and write file
if(osError == noErr)
osError = FSpOpenDF(&(*docStrucHdl)->fileFSSpec,fsRdWrPerm,&fileRefNum);
if(osError == noErr)
{
(*docStrucHdl)->fileRefNum = fileRefNum;
SetWTitle(windowRef,fileSpec.name);
// . . . . . . . . . . . . . . . . . . . . . proxy icon and file synchronisation stuff
SetPortWindowPort(windowRef); /////
SetWindowProxyFSSpec(windowRef,&fileSpec); /////
GetWindowProxyAlias(windowRef,&((*docStrucHdl)->aliasHdl)); /////
SetWindowModified(windowRef,false); /////
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . write file using safe save
osError = doWriteFile(windowRef);
NavCompleteSave(&(*navReplyStruc),kNavTranslateInPlace);
}
}
}
SetPortWindowPort(windowRef);
GetWindowPortBounds(windowRef,&portRect);
EraseRect(&portRect);
InvalWindowRect(windowRef,&portRect);
return osError;
}
// ************************************************************************** doSaveUsingFSRef
OSErr doSaveUsingFSRef(WindowRef windowRef,NavReplyRecord *navReplyStruc)
{
OSErr osError = noErr;
AEDesc aeDesc;
Size dataSize;
FSRef fsRefParent, fsRefDelete;
UniCharCount nameLength;
UniChar *nameBuffer;
FSSpec fileSpec;
docStructureHandle docStrucHdl;
FInfo fileInfo;
SInt16 fileRefNum;
Rect portRect;
osError = AECoerceDesc(&(*navReplyStruc).selection,typeFSRef,&aeDesc);
if(osError == noErr)
{
// ............................................................................. get FSRef
dataSize = AEGetDescDataSize(&aeDesc);
if(dataSize > 0)
osError = AEGetDescData(&aeDesc,&fsRefParent,sizeof(FSRef));
if(osError == noErr)
{
// ............................. get file name from saveFileName field of NavReplyRecord
nameLength = (UniCharCount) CFStringGetLength((*navReplyStruc).saveFileName);
nameBuffer = (UniChar *) NewPtr(nameLength);
CFStringGetCharacters((*navReplyStruc).saveFileName,CFRangeMake(0,nameLength),
&nameBuffer[0]);
if(nameBuffer != NULL)
{
// ...................................... if replacing, delete the file being replaced
if((*navReplyStruc).replacing)
{
osError = FSMakeFSRefUnicode(&fsRefParent,nameLength,nameBuffer,
kTextEncodingUnicodeDefault,&fsRefDelete);
{
if(osError == noErr)
osError = FSDeleteObject(&fsRefDelete);
if(osError == fBsyErr)
{
DisposePtr((Ptr) nameBuffer);
return osError;
}
}
}
// .............. create file with Unicode name (but it can be written with an FSSpec)
if(osError == noErr)
{
osError = FSCreateFileUnicode(&fsRefParent,nameLength,nameBuffer,kFSCatInfoNone,
NULL,NULL,&fileSpec);
if(osError == noErr)
{
docStrucHdl = (docStructureHandle) GetWRefCon(windowRef);
osError = FSpGetFInfo(&fileSpec,&fileInfo);
if((*docStrucHdl)->editStrucHdl != NULL)
fileInfo.fdType = kFileTypeTEXT;
else if((*docStrucHdl)->pictureHdl != NULL)
fileInfo.fdType = kFileTypePICT;
fileInfo.fdCreator = kFileCreator;
if(osError == noErr)
osError = FSpSetFInfo(&fileSpec,&fileInfo);
(*docStrucHdl)->fileFSSpec = fileSpec;
// .......................................... open file's data fork and write file
if(osError == noErr)
osError = FSpOpenDF(&fileSpec,fsRdWrPerm,&fileRefNum);
if(osError == noErr)
{
(*docStrucHdl)->fileRefNum = fileRefNum;
SetWTitle(windowRef,fileSpec.name);
// . . . . . . . . . . . . . . . . . . proxy icon and file synchronisation stuff
SetPortWindowPort(windowRef); /////
SetWindowProxyFSSpec(windowRef,&fileSpec); /////
GetWindowProxyAlias(windowRef,&((*docStrucHdl)->aliasHdl)); /////
SetWindowModified(windowRef,false); /////
// . . . . . . . . . . . . . . . . . . . . . . . . . write file using safe save
osError = doWriteFile(windowRef);
NavCompleteSave(&(*navReplyStruc),kNavTranslateInPlace);
}
}
}
}
DisposePtr((Ptr) nameBuffer);
}
AEDisposeDesc(&aeDesc);
}
SetPortWindowPort(windowRef);
GetWindowPortBounds(windowRef,&portRect);
EraseRect(&portRect);
InvalWindowRect(windowRef,&portRect);
return osError;
}
// ******************************************************************************* doWriteFile
OSErr doWriteFile(WindowRef windowRef)
{
docStructureHandle docStrucHdl;
FSSpec fileSpecActual, fileSpecTemp;
UInt32 currentTime;
Str255 tempFileName;
SInt16 tempFileVolNum, tempFileRefNum;
SInt32 tempFileDirID;
OSErr osError = noErr;
docStrucHdl = (docStructureHandle) GetWRefCon(windowRef);
fileSpecActual = (*docStrucHdl)->fileFSSpec;
GetDateTime(¤tTime);
NumToString((SInt32) currentTime,tempFileName);
osError = FindFolder(fileSpecActual.vRefNum,kTemporaryFolderType,kCreateFolder,
&tempFileVolNum,&tempFileDirID);
if(osError == noErr)
osError = FSMakeFSSpec(tempFileVolNum,tempFileDirID,tempFileName,&fileSpecTemp);
if(osError == noErr || osError == fnfErr)
osError = FSpCreate(&fileSpecTemp,'trsh','trsh',smSystemScript);
if(osError == noErr)
osError = FSpOpenDF(&fileSpecTemp,fsRdWrPerm,&tempFileRefNum);
if(osError == noErr)
{
if((*docStrucHdl)->editStrucHdl)
osError = doWriteTextData(windowRef,tempFileRefNum);
else if((*docStrucHdl)->pictureHdl)
osError = doWritePictData(windowRef,tempFileRefNum);
}
if(osError == noErr)
osError = FSClose(tempFileRefNum);
if(osError == noErr)
osError = FSClose((*docStrucHdl)->fileRefNum);
if(osError == noErr)
osError = FSpExchangeFiles(&fileSpecTemp,&fileSpecActual);
if(osError == noErr)
osError = FSpDelete(&fileSpecTemp);
if(osError == noErr)
osError = FSpOpenDF(&fileSpecActual,fsRdWrPerm,&(*docStrucHdl)->fileRefNum);
if(osError == noErr)
osError = doCopyResources(windowRef);
return osError;
}
// **************************************************************************** doReadTextFile
OSErr doReadTextFile(WindowRef windowRef)
{
docStructureHandle docStrucHdl;
SInt16 fileRefNum;
TEHandle textEditHdl;
SInt32 numberOfBytes;
Handle textBuffer;
OSErr osError = noErr;
docStrucHdl = (docStructureHandle) GetWRefCon(windowRef);
fileRefNum = (*docStrucHdl)->fileRefNum;
textEditHdl = (*docStrucHdl)->editStrucHdl;
(*textEditHdl)->txSize = 10;
(*textEditHdl)->lineHeight = 15;
SetFPos(fileRefNum,fsFromStart,0);
GetEOF(fileRefNum,&numberOfBytes);
if(numberOfBytes > 32767)
numberOfBytes = 32767;
if(!(textBuffer = NewHandle((Size) numberOfBytes)))
return MemError();
osError = FSRead(fileRefNum,&numberOfBytes,*textBuffer);
if(osError == noErr || osError == eofErr)
{
HLockHi(textBuffer);
TESetText(*textBuffer,numberOfBytes,(*docStrucHdl)->editStrucHdl);
HUnlock(textBuffer);
DisposeHandle(textBuffer);
}
else
return osError;
return noErr;
}
// **************************************************************************** doReadPictFile
OSErr doReadPictFile(WindowRef windowRef)
{
docStructureHandle docStrucHdl;
SInt16 fileRefNum;
SInt32 numberOfBytes;
OSErr osError = noErr;
docStrucHdl = (docStructureHandle) GetWRefCon(windowRef);
fileRefNum = (*docStrucHdl)->fileRefNum;
GetEOF(fileRefNum,&numberOfBytes);
SetFPos(fileRefNum,fsFromStart,512);
numberOfBytes -= 512;
if(!((*docStrucHdl)->pictureHdl = (PicHandle) NewHandle(numberOfBytes)))
return MemError();
osError = FSRead(fileRefNum,&numberOfBytes,*(*docStrucHdl)->pictureHdl);
if(osError == noErr || osError == eofErr)
return(noErr);
else
return osError;
}
// *************************************************************************** doWriteTextData
OSErr doWriteTextData(WindowRef windowRef,SInt16 tempFileRefNum)
{
docStructureHandle docStrucHdl;
TEHandle textEditHdl;
Handle editText;
SInt32 numberOfBytes;
SInt16 volRefNum;
OSErr osError = noErr;
docStrucHdl = (docStructureHandle) GetWRefCon(windowRef);
textEditHdl = (*docStrucHdl)->editStrucHdl;
editText = (*textEditHdl)->hText;
numberOfBytes = (*textEditHdl)->teLength;
osError = SetFPos(tempFileRefNum,fsFromStart,0);
if(osError == noErr)
osError = FSWrite(tempFileRefNum,&numberOfBytes,*editText);
if(osError == noErr)
osError = SetEOF(tempFileRefNum,numberOfBytes);
if(osError == noErr)
osError = GetVRefNum(tempFileRefNum,&volRefNum);
if(osError == noErr)
osError = FlushVol(NULL,volRefNum);
if(osError == noErr)
(*docStrucHdl)->windowTouched = false;
return osError;
}
// *************************************************************************** doWritePictData
OSErr doWritePictData(WindowRef windowRef,SInt16 tempFileRefNum)
{
docStructureHandle docStrucHdl;
PicHandle pictureHdl;
SInt32 numberOfBytes, dummyData;
SInt16 volRefNum;
OSErr osError = noErr;
docStrucHdl = (docStructureHandle) GetWRefCon(windowRef);
pictureHdl = (*docStrucHdl)->pictureHdl;
numberOfBytes = 512;
dummyData = 0;
osError = SetFPos(tempFileRefNum,fsFromStart,0);
if(osError == noErr)
osError = FSWrite(tempFileRefNum,&numberOfBytes,&dummyData);
numberOfBytes = GetHandleSize((Handle) (*docStrucHdl)->pictureHdl);
if(osError == noErr)
{
HLock((Handle) (*docStrucHdl)->pictureHdl);
osError = FSWrite(tempFileRefNum,&numberOfBytes,*(*docStrucHdl)->pictureHdl);
HUnlock((Handle) (*docStrucHdl)->pictureHdl);
}
if(osError == noErr)
osError = SetEOF(tempFileRefNum,512 + numberOfBytes);
if(osError == noErr)
osError = GetVRefNum(tempFileRefNum,&volRefNum);
if(osError == noErr)
osError = FlushVol(NULL,volRefNum);
if(osError == noErr)
(*docStrucHdl)->windowTouched = false;
return osError;
}
// *************************************************************** getFilePutFileEventFunction
void getFilePutFileEventFunction(NavEventCallbackMessage callBackSelector,
NavCBRecPtr callBackParms,NavCallBackUserData callBackUD)
{
OSErr osError = noErr;
NavReplyRecord navReplyStruc;
NavUserAction navUserAction;
SInt32 count, index;
AEKeyword theKeyword;
DescType actualType;
FSSpec fileSpec;
Size actualSize;
FInfo fileInfo;
OSType documentType;
WindowRef windowRef;
AEDesc aeDesc;
AEKeyword keyWord;
DescType typeCode;
Rect theRect;
Str255 theString, numberString;
docStructureHandle docStrucHdl;
switch(callBackSelector)
{
case kNavCBUserAction:
osError = NavDialogGetReply(callBackParms->context,&navReplyStruc);
if(osError == noErr && navReplyStruc.validRecord)
{
navUserAction = NavDialogGetUserAction(callBackParms->context);
switch(navUserAction)
{
// ............................................. click on Open button in Open dialog
case kNavUserActionOpen:
if(gModalToApplicationNavDialogRef != NULL)
{
osError = AECountItems(&(navReplyStruc.selection),&count);
if(osError == noErr)
{
for(index=1;index<=count;index++)
{
osError = AEGetNthPtr(&(navReplyStruc.selection),index,typeFSS,
&theKeyword,&actualType,&fileSpec,sizeof(fileSpec),
&actualSize);
if((osError = FSpGetFInfo(&fileSpec,&fileInfo)) == noErr)
{
documentType = fileInfo.fdType;
osError = doOpenFile(fileSpec,documentType);
if(osError != noErr)
doErrorAlert(osError);
}
}
}
}
break;
// .................................... click on Save button in Save Location dialog
case kNavUserActionSaveAs:
windowRef = callBackUD;
osError = AECoerceDesc(&navReplyStruc.selection,typeFSRef,&aeDesc);
if(osError == noErr)
{
osError = doSaveUsingFSRef(windowRef,&navReplyStruc);
if(osError != noErr)
doErrorAlert(osError);
AEDisposeDesc(&aeDesc);
}
else
{
osError = doSaveUsingFSSpec(windowRef,&navReplyStruc);
if(osError != noErr)
doErrorAlert(osError);
}
break;
// ................................ click on Choose button in Choose a Folder dialog
case kNavUserActionChoose:
if((osError = AEGetNthPtr(&(navReplyStruc.selection),1,typeFSS,&keyWord,&typeCode,
&fileSpec,sizeof(FSSpec),&actualSize)) == noErr)
{
FSMakeFSSpec(fileSpec.vRefNum,fileSpec.parID,fileSpec.name,&fileSpec);
}
windowRef = callBackUD;
SetPortWindowPort(windowRef);
TextSize(10);
SetRect(&theRect,0,271,600,300);
EraseRect(&theRect);
doCopyPString(fileSpec.name,theString);
doConcatPStrings(theString, "\p Volume Reference Number: ");
NumToString((SInt32) fileSpec.vRefNum,numberString);
doConcatPStrings(theString,numberString);
doConcatPStrings(theString, "\p Parent Directory ID: ");
NumToString((SInt32) fileSpec.parID,numberString);
doConcatPStrings(theString,numberString);
MoveTo(10,290);
DrawString(theString);
break;
}
osError = NavDisposeReply(&navReplyStruc);
}
break;
case kNavCBTerminate:
if(gModalToApplicationNavDialogRef != NULL)
{
NavDialogDispose(gModalToApplicationNavDialogRef);
gModalToApplicationNavDialogRef = NULL;
}
else
{
windowRef = callBackUD;
docStrucHdl = (docStructureHandle) GetWRefCon(windowRef);
if((*docStrucHdl)->modalToWindowNavDialogRef != NULL)
{
NavDialogDispose((*docStrucHdl)->modalToWindowNavDialogRef);
(*docStrucHdl)->modalToWindowNavDialogRef = NULL;
}
}
break;
}
}
// *************************************************************** askSaveDiscardEventFunction
void askSaveDiscardEventFunction(NavEventCallbackMessage callBackSelector,
NavCBRecPtr callBackParms,NavCallBackUserData callBackUD)
{
WindowRef windowRef;
docStructureHandle docStrucHdl;
NavUserAction navUserAction;
OSErr osError = noErr;
Rect portRect;
switch(callBackSelector)
{
case kNavCBUserAction:
windowRef = callBackUD;
docStrucHdl = (docStructureHandle) GetWRefCon(windowRef);
if((*docStrucHdl)->modalToWindowNavDialogRef != NULL)
{
navUserAction = NavDialogGetUserAction(callBackParms->context);
switch(navUserAction)
{
// ...................................... click on Save button in Save Changes alert
case kNavUserActionSaveChanges:
osError = doSaveCommand();
if(osError != noErr)
doErrorAlert(osError);
// ................................ click on Don't Save button in Save Changes alert
case kNavUserActionDontSaveChanges:
NavDialogDispose((*docStrucHdl)->modalToWindowNavDialogRef);
if(gRunningOnX)
{
osError = doCloseDocWindow(windowRef);
if(osError != noErr)
doErrorAlert(osError);
}
else
gCloseDocWindow = true;
break;
// ..................................... click on OK button in Discard Changes alert
case kNavUserActionDiscardChanges:
GetWindowPortBounds(windowRef,&portRect);
SetPortWindowPort(windowRef);
EraseRect(&portRect);
if((*docStrucHdl)->editStrucHdl != NULL && (*docStrucHdl)->fileRefNum != 0)
{
osError = doReadTextFile(windowRef);
if(osError != noErr)
doErrorAlert(osError);
}
else if((*docStrucHdl)->pictureHdl != NULL)
{
KillPicture((*docStrucHdl)->pictureHdl);
(*docStrucHdl)->pictureHdl = NULL;
osError = doReadPictFile(windowRef);
if(osError != noErr)
doErrorAlert(osError);
}
(*docStrucHdl)->windowTouched = false;
SetWindowModified(windowRef,false); /////
InvalWindowRect(windowRef,&portRect);
NavDialogDispose((*docStrucHdl)->modalToWindowNavDialogRef);
(*docStrucHdl)->modalToWindowNavDialogRef = NULL;
break;
// ................. click on Cancel button in Save Changes or Discard Changes alert
case kNavUserActionCancel:
if((*docStrucHdl)->isAskSaveChangesDialog == true)
{
gQuittingApplication = false;
(*docStrucHdl)->isAskSaveChangesDialog = false;
}
NavDialogDispose((*docStrucHdl)->modalToWindowNavDialogRef);
(*docStrucHdl)->modalToWindowNavDialogRef = NULL;
break;
}
}
break;
}
}
// *************************************************************************** doCopyResources
OSErr doCopyResources(WindowRef windowRef)
{
docStructureHandle docStrucHdl;
OSType fileType;
OSErr osError = noErr;
SInt16 fileRefNum;
Handle editTextHdl, textResourceHdl;
docStrucHdl = (docStructureHandle) GetWRefCon(windowRef);
if((*docStrucHdl)->editStrucHdl)
fileType = kFileTypeTEXT;
else if((*docStrucHdl)->pictureHdl)
fileType = kFileTypePICT;
FSpCreateResFile(&(*docStrucHdl)->fileFSSpec,kFileCreator,fileType,smSystemScript);
osError = ResError();
if(osError == noErr)
fileRefNum = FSpOpenResFile(&(*docStrucHdl)->fileFSSpec,fsRdWrPerm);
if(fileRefNum > 0)
{
osError = doCopyAResource('STR ',-16396,gAppResFileRefNum,fileRefNum);
if(fileType == kFileTypePICT)
{
doCopyAResource('pnot',128,gAppResFileRefNum,fileRefNum);
doCopyAResource('PICT',128,gAppResFileRefNum,fileRefNum);
}
if(!gRunningOnX && fileType == kFileTypeTEXT)
{
doCopyAResource('pnot',129,gAppResFileRefNum,fileRefNum);
editTextHdl = (*(*docStrucHdl)->editStrucHdl)->hText;
textResourceHdl = NewHandleClear(1024);
BlockMoveData(*editTextHdl,*textResourceHdl,1024);
UseResFile(fileRefNum);
AddResource(textResourceHdl,'TEXT',129,"\p");
if(ResError() == noErr)
UpdateResFile(fileRefNum);
ReleaseResource(textResourceHdl);
}
}
else
osError = ResError();
if(osError == noErr)
CloseResFile(fileRefNum);
osError = ResError();
return osError;
}
// *************************************************************************** doCopyAResource
OSErr doCopyAResource(ResType resourceType,SInt16 resourceID,SInt16 sourceFileRefNum,
SInt16 destFileRefNum)
{
Handle sourceResourceHdl;
Str255 sourceResourceName;
ResType ignoredType;
SInt16 ignoredID;
UseResFile(sourceFileRefNum);
sourceResourceHdl = GetResource(resourceType,resourceID);
if(sourceResourceHdl != NULL)
{
GetResInfo(sourceResourceHdl,&ignoredID,&ignoredType,sourceResourceName);
DetachResource(sourceResourceHdl);
UseResFile(destFileRefNum);
AddResource(sourceResourceHdl,resourceType,resourceID,sourceResourceName);
if(ResError() == noErr)
UpdateResFile(destFileRefNum);
}
ReleaseResource(sourceResourceHdl);
return ResError();
}
// *******************************************************************************************
// SynchroniseFiles.c
// *******************************************************************************************
// .................................................................................. includes
#include "Files.h"
// .......................................................................... global variables
extern SInt16 gCurrentNumberOfWindows;
// ************************************************************************ doSynchroniseFiles
void doSynchroniseFiles(void)
{
WindowRef windowRef;
SInt16 trashVRefNum;
SInt32 trashDirID;
docStructureHandle docStrucHdl;
Boolean aliasChanged;
AliasHandle aliasHdl;
FSSpec newFSSpec;
OSErr osError;
windowRef = FrontNonFloatingWindow();
while(windowRef != NULL)
{
docStrucHdl = (docStructureHandle) GetWRefCon(windowRef);
if(docStrucHdl != NULL)
{
if((*docStrucHdl)->aliasHdl == NULL)
break;
aliasChanged = false;
aliasHdl = (*docStrucHdl)->aliasHdl;
ResolveAlias(NULL,aliasHdl,&newFSSpec,&aliasChanged);
if(aliasChanged)
{
(*docStrucHdl)->fileFSSpec = newFSSpec;
SetWTitle(windowRef,newFSSpec.name);
}
osError = FindFolder(kUserDomain,kTrashFolderType,kDontCreateFolder,&trashVRefNum,
&trashDirID);
if(osError == noErr)
{
do
{
if(newFSSpec.parID == fsRtParID)
break;
if((newFSSpec.vRefNum == trashVRefNum) && (newFSSpec.parID == trashDirID))
{
FSClose((*docStrucHdl)->fileRefNum);
if((*docStrucHdl)->editStrucHdl)
TEDispose((*docStrucHdl)->editStrucHdl);
if((*docStrucHdl)->pictureHdl)
KillPicture((*docStrucHdl)->pictureHdl);
DisposeHandle((Handle) docStrucHdl);
DisposeWindow(windowRef);
gCurrentNumberOfWindows --;
break;
}
} while(FSMakeFSSpec(newFSSpec.vRefNum,newFSSpec.parID,"\p",&newFSSpec) == noErr);
}
}
windowRef = GetNextWindow(windowRef);
}
}
// *******************************************************************************************
// ChooseAFolderDialog.c
// *******************************************************************************************
// .................................................................................. includes
#include "Files.h"
// .......................................................................... global variables
extern NavEventUPP gGetFilePutFileEventFunctionUPP ;
extern NavDialogRef gModalToApplicationNavDialogRef;
// ********************************************************************* doChooseAFolderDialog
OSErr doChooseAFolderDialog(void)
{
OSErr osError = noErr;
NavDialogCreationOptions dialogOptions;
WindowRef windowRef, parentWindowRef;
Str255 message;
osError = NavGetDefaultDialogCreationOptions(&dialogOptions);
if(osError == noErr)
{
if((osError = GetSheetWindowParent(FrontWindow(),&parentWindowRef)) == noErr)
windowRef = parentWindowRef;
else
windowRef = FrontWindow();
GetIndString(message,rMiscStrings,sChooseAFolder);
dialogOptions.message = CFStringCreateWithPascalString(NULL,message,
CFStringGetSystemEncoding());
dialogOptions.modality = kWindowModalityAppModal;
osError = NavCreateChooseFolderDialog(&dialogOptions,gGetFilePutFileEventFunctionUPP ,
NULL,windowRef,&gModalToApplicationNavDialogRef);
if(osError == noErr && gModalToApplicationNavDialogRef != NULL)
{
osError = NavDialogRun(gModalToApplicationNavDialogRef);
if(osError != noErr)
{
NavDialogDispose(gModalToApplicationNavDialogRef);
gModalToApplicationNavDialogRef = NULL;
}
}
}
return osError;
}
// *******************************************************************************************
Demonstration Program Files Comments
When the program is run, the user should:
o Exercise the File menu by opening the supplied TEXT and PICT files, saving those files,
saving those files under new names, closing files, opening the new files, attempting to open
files that are already open, attempting to save files to new files with existing names,
making open windows "touched" by choosing the first item in the Demonstration menu, reverting
to the saved versions of files associated with "touched" windows, choosing Quit when one
"touched" window is open, choosing Quit when two or more "touched" windows are open, and so
on.
o Choose, via the Show pop-up menu button, the file types required to be displayed in the Open
dialog.
o Choose the Choose a Folder item from the Demonstration menu to display the Choose a Folder
dialog, and choose a folder using the Choose button at the bottom of the dialog. (The name
of the chosen folder will be drawn in the bottom-left corner of the front window.)
o With either the PICT Document or the TEXT Document open:
o With the document's Finder icon visible, drag the window proxy icon to the desktop or to
another open folder, noting that the Finder icon moves to the latter. Then choose Touch
Window from the Demonstration menu to simulate unsaved changes to the document. Note that
the proxy icon changes to the disabled state. Then save the file, proving the correct
operation of the file synchronisation function. Note that, after the save, the window
proxy icon changes back to the enabled state.
o Command-click the window's title to display the window path pop-up menu, choose a folder
from the menu, and note that the Finder is brought to the foreground and the chosen folder
opens.
The program may be run from within CodeWarrior to demonstrate responses to the File menu
commands and the Choose a Folder dialog.
The built application, together with the supplied 'TEXT' and 'PICT' files, may be used to
demonstrate the additional aspect of integrating the receipt of required Apple events with the
overall file handling mechanism. To prove the correct handling of the required Apple events,
the user should:
o Open the application by double-clicking the application icon, noting that a new document
window is opened after the application is launched and the Open Application event is
received.
o Double click on a document icon, or select one or more document icons and either drag those
icons to the application icon or choose Open from the Finder's File menu, noting that the
application is launched and the selected files are opened when the Open Documents event is
received.
o Close all windows and double-click the application icon, noting that the application responds
to the Re-open Application event by opening a new window.
o With the PICT Document and the TEXT Document open and "touched", and several other windows
open, choose Restart or Shut Down from the Mac OS 8/9 Finder's Special menu or the Mac OS X
Apple menu (thus invoking a Quit Application event), noting that, for "touched" windows, the
Save Changes alert is presented asking the user whether the file should be saved before the
shutdown process proceeds. (On Mac OS X, a Review Unsaved alert will be presented at first.)
Note, however, that no printing functions are included. Thus, selecting one or more document
icons and choosing Print from the Finder's File menu (Mac OS 8/9) will result in the file/s
opening but not printing.
Files.h
defines
Constants are established for a 'STR#' resource containing error strings for three specific
error conditions, a 'STR#' resource containing the application's name and the message string
for the Choose a Folder dialog, and the 'open' resource containing the file types list.
KFileCreator represents the application's signature and the next two constants represent the
file types that are readable and writeable by the application.
typedefs
Each window created by the program will have an associated document structure. The
docStructure data type will be used for document structures.
The editStrucHdl field will be assigned a handle to a TextEdit structure ('TEXT' files). The
pictureHdl field will be assigned a handle to a Picture structure ('PICT' files). The
fileRefNum and fileFSSpec fields will be assigned the file reference number and the file system
specification structure of the file associated with the window. When a file is opened, the
aliasHdl field will be assigned a handle to a structure of type AliasRecord, which contains the
alias data for the file. The windowTouched field will be set to true when a window has been
made "touched".
When modal-to-the-window Navigation Services dialogs (Save Location, Save Changes, and Discard
Changes alerts) are created, the dialog reference will be assigned to the
modalToWindowNavDialogRef field. When Save Changes and Discard Changes alerts are created, a
universal procedure pointer to the associated event (callback) function will be assigned to the
askSaveDiscardChangesDialog field. When a Save Changes alert is created, the
isAskSaveChangesDialog field will be set to true to enable the associated event (callback)
function to re-set a "quitting application" flag if the user clicks the Cancel button in a Save
Changes alert (but not if the user clicks the Cancel button in a Discard Changes alert).
Files.c
Global Variables
gAppResFileRefNum will be assigned the file reference number of the application's resource
fork. gGetFilePutFileEventFunctionUPP will be assigned a universal procedure pointer to the
event (callback) function associated with the Open, Save Location, and Choose a Folder dialogs.
gQuittingApplication is set to true in certain circumstances within quitAppEventHandler and to
false if the Cancel button is clicked in a Save Changes or Review Unsaved alert.
main
The file reference number of the application's resource fork (which is opened automatically at
application launch) is assigned to the global variable gAppResFileRefNum.
After the required Apple event handlers are installed, the program's applicat |