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.
Files.c
/*------------------------------------------------------------------------------ |
* |
* Apple Developer Technical Support |
* |
* I/O handling routines |
* |
* Program: AEObject-Edition Sample |
* File: Files.c - C Source |
* |
* by: C.K. Haun <TR> |
* |
* Copyright © 1990-1992 Apple Computer, Inc. |
* All rights reserved. |
* |
*------------------------------------------------------------------------------ |
* This file handles saving and loadingg the documents created by this sample. |
* All the standard data load/save is taken care of in this file, while the |
* Edition Manager specific routines for handling sections are in their own files |
* (Publish.c or Subscribe.c) and are called from here. |
*----------------------------------------------------------------------------*/ |
/* File handling here */ |
#define __FILES__ |
#pragma segment Files |
#include "Sampdefines.h" |
static OSErr KillOldPrefs(void); |
/* SaveMe saves the passes window data, and all the associated sections. |
* It does NOT perform a 'safe' save, it kills the old data and recreates it. |
* Future versions of this sample will do a 'safe' save. Yeah, right, I wouldn't |
* beleive me on THAT one. |
*/ |
/* windowCHandle is locked on entry to this */ |
void SaveMe(windowCHandle theWind, WindowPtr theWindPtr) |
{ |
Boolean myWasChanged; /* for Alias Manager calls */ |
register qq; /* counter */ |
StandardFileReply saveReply; /* new System 7 standard file record */ |
short saveRefNum; |
FSSpec saveFileSpec; |
OSErr myErr; |
Str255 wName; |
Str63 savePrompt; |
Handle nameStr; |
long toWrite; /* generic long */ |
/* we need the window title for a prompt and also to change the name */ |
/* in the Window menu */ |
GetWTitle(theWindPtr, wName); |
/* if the filealias handle is 0 size, then this file has not been saved yet, so we */ |
/* need to call Standard File. I'm using the new StandardGetFile call, this */ |
/* call is better in (at least) two ways. First, you no longer pass a Point as */ |
/* a parameter, instead, the dialog is centered on the main screen for you. Secondly, */ |
/* StandardGetFile returns a FSSpec record in the reply record. This means that you */ |
/* can use the new FSp type calls, as well as using the FSSpec to generate an Alias */ |
/* easily. */ |
/* By the Way... if this is a 'Save As...' I have nulled out this handle so it */ |
/* looks like it's never been saved, look in Menus.c */ |
if (GetHandleSize((Handle)(*theWind)->fileAliasHandle) == 0) { |
/* get our prompt string */ |
GetIndString(savePrompt, kGeneralStrings, kSavePromptString); |
/* display the new dialog */ |
StandardPutFile(savePrompt, wName, &saveReply); |
if (!saveReply.sfGood) /* did the user cancel? */ |
return; |
/* get the returned file spec */ |
saveFileSpec = saveReply.sfFile; |
/* if they are replacing, destroy the old file now (aaaggggg) */ |
if (saveReply.sfReplacing) |
FSpDelete(&saveFileSpec); |
/* change the name of the window to this filename */ |
SetWTitle(theWindPtr, saveFileSpec.name); |
AddToWindowMenu(theWindPtr,wName); /* remove the old name and replace it with this */ |
} else { |
/* Resolve the old alias that was kept with the window */ |
/* in this case I don't care if the alias needed to be updated or not, this ain't */ |
/* a real time critical routine */ |
myErr = ResolveAlias(nil, ((*theWind)->fileAliasHandle), &saveFileSpec, &myWasChanged); |
if (myErr) { |
ShowMe("\pResolving Alias ", myErr, __LINE__); |
return; |
} |
/* kill current file, ignoring errors */ |
FSpDelete(&saveFileSpec); |
} |
SpinCursor(); |
/* create the new file */ |
myErr = FSpCreate(&saveFileSpec, kMySignature, kMyDocumentFileType, 1); |
if (myErr) { |
ShowMe("\pCreating file ", myErr, __LINE__); |
SetMyCursor(actsToIDs[(*theWind)->currentAction]); |
return; |
} |
/* replace the nil handle with the alias record please, in our window data struct */ |
DisposeHandle((Handle)(*theWind)->fileAliasHandle); |
if (myErr = NewAlias(nil, &saveFileSpec, &((*theWind)->fileAliasHandle))) { |
ShowMe("\pDuring New Alias ", myErr, __LINE__); |
SetMyCursor(actsToIDs[(*theWind)->currentAction]); |
return; |
} |
/* First save the drawing commands that make up this window */ |
myErr = FSpOpenDF(&saveFileSpec, fsRdWrPerm, &saveRefNum); |
if (myErr) { |
ShowMe("\pOpening file ", myErr, __LINE__); |
SetMyCursor(actsToIDs[(*theWind)->currentAction]); |
return; |
} |
/* save off lines, rects, ovals. If there is a selection currently, it's lost */ |
/* shapes */ |
toWrite = sizeof(short); |
SpinCursor(); |
myErr = FSWrite(saveRefNum, &toWrite, (Ptr)&(*theWind)->numShapes); |
if (myErr) { |
ShowMe("\pWriting file ", myErr, __LINE__); |
} |
if ((*theWind)->numShapes) { |
ShapesHandle theShape = (*theWind)->theShapes; |
do { |
toWrite = sizeof(Shapes); |
HLock((Handle)theShape); |
myErr = FSWrite(saveRefNum, &toWrite, (Ptr)*theShape); |
HUnlock((Handle)theShape); |
if (myErr) { |
ShowMe("\pWriting shapes ", myErr, __LINE__); |
break; |
} |
theShape = (*theShape)->nextShape; |
} |
while (theShape); |
} |
/* and pictures, I'm putting them in the data fork just because, OK? */ |
/* Actually, I'm doing it to prevent any conflict with resource for */ |
/* subscribers cached pictures. I could check for unique IDs and all that, but sometimes */ |
/* simplicity works well.... */ |
if(!myErr){ |
toWrite = sizeof(short); |
SpinCursor(); |
myErr = FSWrite(saveRefNum, &toWrite, (Ptr)&(*theWind)->numPicts); |
if(!myErr){ |
if ((*theWind)->numPicts != 0) { |
Handle * thePict; |
Handle *thePictRect; |
/* get my picture handles and my picture placement rectangles */ |
HLock((Handle)(*theWind)->pictHandle); |
HLock((Handle)(*theWind)->pictRects); |
thePict = (Handle *)*(*theWind)->pictHandle; |
thePictRect = (Handle *)*(*theWind)->pictRects; |
for (qq = 0; qq < (*theWind)->numPicts; qq++) { |
short writeSize; |
toWrite = sizeof(short); |
/* write everything about the picture out */ |
writeSize = GetHandleSize((Handle)*thePict); |
myErr = FSWrite(saveRefNum, &toWrite, (Ptr)&writeSize); |
toWrite = writeSize; |
HLock((Handle)*thePict); |
if(!myErr) myErr = FSWrite(saveRefNum, &toWrite, (Ptr)(*(*thePict))); |
HUnlock((Handle)*thePict); |
/* and the rect */ |
toWrite = sizeof(Rect); |
HLock((Handle)*thePictRect); |
if(!myErr) myErr = FSWrite(saveRefNum, &toWrite, (Ptr)(*(*thePictRect))); |
HUnlock((Handle)*thePictRect); |
thePictRect += 1; |
thePict += 1; |
SpinCursor(); |
} |
HUnlock((Handle)(*theWind)->pictHandle); |
HUnlock((Handle)(*theWind)->pictRects); |
} |
} |
} |
toWrite = sizeof(short); |
/* if there's any text in a TE record, write that out also */ |
if(!myErr){ |
if ((*theWind)->boxHandle != nil) { |
CharsHandle theText; |
short textLen; |
/* save the text and the rectangle */ |
theText = TEGetText((*theWind)->boxHandle); |
HLock((Handle)theText); |
textLen = GetHandleSize((Handle)theText); |
/* have to write it out the length of the text now */ |
toWrite = sizeof(short); |
SpinCursor(); |
myErr = FSWrite(saveRefNum, &toWrite, (Ptr)&textLen); |
/* and the text itself */ |
toWrite = textLen; |
if(!myErr) myErr = FSWrite(saveRefNum, &toWrite, (Ptr)*theText); |
/* and save out the rectangle */ |
toWrite = sizeof(Rect); |
if(!myErr) myErr = FSWrite(saveRefNum, &toWrite, (Ptr)&(*theWind)->textBox); |
} else { |
short nothing = 0; |
myErr = FSWrite(saveRefNum, &toWrite, (Ptr)¬hing); /* a pointer to nothing. Leads to the 'No Exit' sign in Sart */ |
} |
} |
if(myErr) |
ShowMe("\p Error writing data fork",myErr,__LINE__); |
if(saveRefNum)FSClose(saveRefNum); |
/* this takes care of the data fork of the file. Now we need to save |
* publisher and subcriber data in the resource fork */ |
HCreateResFile(saveFileSpec.vRefNum, saveFileSpec.parID, saveFileSpec.name); |
if (myErr = ResError()) { |
ShowMe("\pCreating Rez fork", myErr, __LINE__); |
SetMyCursor(actsToIDs[(*theWind)->currentAction]); |
return; |
} |
saveRefNum = HOpenResFile(saveFileSpec.vRefNum, saveFileSpec.parID, saveFileSpec.name, fsRdWrPerm); |
if (myErr = ResError()) { |
ShowMe("\pHOpening resource fork ", myErr, __LINE__); |
SetMyCursor(actsToIDs[(*theWind)->currentAction]); |
return; |
} |
/* add our 'name' string to this file (see 'The Finder Interface' chapter of IM VI) */ |
nameStr = GetResource('STR ', kMyAppNameString); |
DetachResource(nameStr); |
UseResFile(saveRefNum); |
AddResource(nameStr, 'STR ', -16396, ""); /* no constant for this number, should be */ |
/* HandleSectionSave saves off the 'sect' and 'alis' resources for all our */ |
/* publishers and subscribers */ |
HandleSectionSave(theWind, true, false, &saveFileSpec); |
CloseResFile(saveRefNum); |
FlushVol("", saveFileSpec.vRefNum); |
(*theWind)->windowDirty = false; |
SetMyCursor(actsToIDs[(*theWind)->currentAction]); |
} |
/* end SaveMe */ |
/* OpenFile reads in our drawing commands, and all the publisher and */ |
/* subscriber data, and registers all our sections */ |
WindowPtr OpenFile(FSSpec *inSpec) |
{ |
long numSections; |
long counter = 0; |
OSErr myErr; |
WindowPtr newWindow; |
windowCHandle newWinControl; |
Handle textFromFile; |
FSSpec readFileSpec; |
short readRefNum; |
StandardFileReply openReply; |
SFTypeList myList = { |
kMyDocumentFileType |
}; |
if (inSpec) { /* if it was called by an ODOC AppleEvent then our AppleEvent handler */ |
/* will pass the FSSpec that the AE contained */ |
readFileSpec = openReply.sfFile = *inSpec; |
} else { |
/* if the spec is nil, that means it's a menu selection, so we use StandardFile */ |
StandardGetFile(NULL, 1, myList, &openReply); |
if (!openReply.sfGood) |
return(nil); /* scat if they canceled */ |
readFileSpec = openReply.sfFile; |
} |
if ((openReply.sfType != kMyDocumentFileType) && (inSpec == nil)) { |
ShowMe("\pfilter not working", 0, __LINE__); |
return(nil); |
} |
if(CheckExisting(&readFileSpec)){ |
/* if it already eisists, bring it up */ |
WindowToFront(nil,readFileSpec.name); |
return(FrontWindow()); |
} |
SpinCursor(); |
newWindow = AddNewWindow(false); /* ask for a new window */ |
if (newWindow == nil) { |
InitCursor(); |
return(nil); |
} /* bail if it failed */ |
newWinControl = (windowCHandle)GetWRefCon(newWindow); |
HLock((Handle)newWinControl); |
/* window opened, set title to file name, and create an alias to store in the */ |
/* struct. */ |
SetWTitle(newWindow, readFileSpec.name); |
DisposeHandle((Handle)(*newWinControl)->fileAliasHandle); /* kill the null handle */ |
if (myErr = NewAlias(nil, &readFileSpec, &((*newWinControl)->fileAliasHandle))) { |
ShowMe("\pDuring New Alias ", myErr, __LINE__); |
return(nil); |
} |
/* now open the data fork of the file and read in our drawing commands */ |
if (myErr = FSpOpenDF(&openReply.sfFile, fsRdPerm, &readRefNum)) { |
ShowMe("\pOpening file ", myErr, __LINE__); |
return(nil); |
} |
SpinCursor(); |
ReadDocData(newWinControl, readRefNum); |
SpinCursor(); |
readRefNum = HOpenResFile(readFileSpec.vRefNum, readFileSpec.parID, readFileSpec.name, fsRdWrPerm); |
UseResFile(readRefNum); |
/* now load in the sections and aliases */ |
/* Load each section, and store it in the appropriate area (pub or sub) */ |
/* Then register the sections. */ |
/* ¥¥¥ NOTE: As soon as you register a section, the Edition Manager may generate an */ |
/* event for that section. All the subscribers may get a Section Read event, for */ |
/* example, and some of the publishers will probably get a section write. */ |
/* So, don't assume anything. Don't write sections or read sections yourself, wait for */ |
/* the Edition Manager to generate the right events, this will insure that you are always */ |
/* current and NOT fighting with the EM */ |
/* how many sections are there? */ |
numSections = Count1Resources(rSectionType); |
/* loop through them all */ |
if (numSections) { |
for (counter = 0; counter < numSections; counter++) { |
SectionHandle inSection; |
AliasHandle inAlias; |
Handle auxDataIn; |
short inID; |
ResType tempRT; |
Str255 tempRName; |
Boolean aliasUpdated; |
SpinCursor(); |
inSection = (SectionHandle)Get1IndResource(rSectionType, counter + 1); |
/* this GetResInfo call is here to give us the ResID of the section. Since the alias */ |
/* for this section was stored with the same ID, we can get it easily. */ |
GetResInfo((Handle)inSection, &inID, &tempRT, &tempRName); |
inAlias = (AliasHandle)Get1Resource(rAliasType, inID); |
myErr = ResError(); |
if ((myErr != 0) || (inAlias == nil)) |
ShowMe("\palias error", myErr, __LINE__); |
DetachResource((Handle)inSection); |
DetachResource((Handle)inAlias); |
/* depending on our type depends on what else we bring in */ |
/* text data or picture stuff */ |
switch ((*inSection)->refCon & 0xf) { |
case kPictType: |
auxDataIn = Get1Resource('RECT', inID); |
DetachResource(auxDataIn); |
break; |
case kTextType: |
/* I do need */ |
/* to get my textSection record back so I have my start-end offsets */ |
auxDataIn = Get1Resource(rMyTextRecordType, inID); |
DetachResource(auxDataIn); |
break; |
} |
/* Put the alias in the section, since the old handle stored there means nothing now */ |
(*inSection)->alias = inAlias; |
/* now we have to determine if this was a pub or sub, since we have to load the */ |
/* publish rectangle resource if it was a publisher */ |
/* Now tell the Edition Manager that this section is back on line and ready to */ |
/* receive events */ |
if (myErr = RegisterSection(&readFileSpec, inSection, &aliasUpdated)) { |
ShowMe("\pRegistering Section ", myErr, __LINE__); |
/* return; */ |
inSection = nil; |
} |
if (inSection) { |
if ((*inSection)->kind == stPublisher) { |
/* get the rectangle */ |
switch ((*inSection)->refCon & 0xf) { |
case kPictType: |
HLock(auxDataIn); |
StorePublisher(newWinControl, inSection, (Rect *)*auxDataIn, nil, 'PICT'); /* in Publish.c */ |
DisposeHandle(auxDataIn); |
/* mark all incoming sections as having been saved once, so we don't */ |
/* delete them accidentalllly when this window closes */ |
(*inSection)->refCon |= kSavedOnce; |
break; |
case kTextType: |
/* need to get the text contained in this thing */ |
textFromFile = Get1Resource(rMyTextBlock, inID); |
DetachResource(textFromFile); |
(*(mySectionDataHandle)auxDataIn)->additionalData = textFromFile; |
/* associate the section with the text section */ |
(*(mySectionDataHandle)auxDataIn)->theSection = inSection; |
/* and store it away */ |
StorePublisher(newWinControl, inSection, nil, (mySectionDataHandle)auxDataIn, 'TEXT'); |
/* mark all incoming sections as having been saved once, so we don't */ |
/* delete them accidentalllly when this window closes */ |
(*inSection)->refCon |= kSavedOnce; |
break; |
} |
} else { |
Handle picIn; |
switch ((*inSection)->refCon & 0xf) { |
case kPictType: |
picIn = (Handle)GetPicture(inID); |
DetachResource((Handle)picIn); |
if (ResError()) |
ShowMe("\ppicture get", 0, __LINE__); |
/* need to get the picture here */ |
StoreSubscriber(newWinControl, inSection, auxDataIn, picIn); /* in Subscribe.c */ |
break; |
case kTextType: |
/* need to get the text contained in this thing */ |
textFromFile = Get1Resource(rMyTextBlock, inID); |
DetachResource(textFromFile); |
(*(mySectionDataHandle)auxDataIn)->additionalData = textFromFile; |
/* associate the section with the text section */ |
(*(mySectionDataHandle)auxDataIn)->theSection = inSection; |
(*(mySectionDataHandle)auxDataIn)->nextSection = nil; |
/* and store it away */ |
/* I'll be using the auxDataIn field for the mySectionDataHandle */ |
StoreSubscriber(newWinControl, inSection, auxDataIn, nil); /* in Subscribe.c */ |
break; |
} |
} |
} |
} |
} |
CloseResFile(readRefNum); |
(*newWinControl)->windowDirty = false; /* can't be dirty if I just opend it */ |
HUnlock((Handle)newWinControl); |
ShowWindow(newWindow); |
AddToWindowMenu(newWindow, nil); |
ChangePlane(newWindow); |
InitCursor(); |
return(newWindow); |
} |
/* Reads the actual document data out of the file. This is not in the OpenFile function */ |
/* for secret reasons that will become apparent in a future release of this sample..... */ |
/* the window control structure in this window ptr is locked on entry */ |
/* I'm passing the window instaed of the window control handle because I may */ |
/* have to create a text edit record */ |
void ReadDocData(windowCHandle newWinControl, short readRefNum) |
{ |
long toRead; |
register qq; |
short aShort; |
OSErr myErr; |
short shapeCounter; |
GetEOF(readRefNum, &toRead); |
if (toRead) { /* Make sure that there is some data to read */ |
/* lines */ |
toRead = sizeof(short); |
FSRead(readRefNum, &toRead, (Ptr)&shapeCounter); |
if (shapeCounter) { |
ShapesHandle tempSH; |
for (qq = 0; qq < shapeCounter; qq++) { |
tempSH = NewShape(newWinControl); /* number of shapes is getting incremented in this call */ |
HLock((Handle)tempSH); |
toRead = sizeof(Shapes); |
myErr = FSRead(readRefNum, &toRead, (Ptr)*tempSH); |
if (myErr) |
ShowMe("\pReading shape", myErr, __LINE__); |
/* re-nul the nextShape field */ |
(*tempSH)->nextShape = nil; |
HUnlock((Handle)tempSH); |
} |
} |
toRead = sizeof(short); |
FSRead(readRefNum, &toRead, (Ptr)&(*newWinControl)->numPicts); |
if ((*newWinControl)->numPicts != 0) { |
Handle * tempPictHand; |
Handle *tempPictRects; |
HUnlock((*newWinControl)->pictHandle); |
HUnlock((*newWinControl)->pictRects); |
MySetHandleSize((*newWinControl)->pictHandle, (sizeof(Handle) * ((*newWinControl)->numPicts))); |
MySetHandleSize((*newWinControl)->pictRects, (sizeof(Handle) * ((*newWinControl)->numPicts))); |
HLock((*newWinControl)->pictHandle); |
HLock((*newWinControl)->pictRects); |
tempPictRects = (Handle *)*((*newWinControl)->pictRects); |
tempPictHand = (Handle *)*((*newWinControl)->pictHandle); |
/* read in picts please */ |
for (qq = 0; qq < (*newWinControl)->numPicts; qq++) { |
short sizeIn; |
/* read size of pict, pict, and pict rect for each */ |
toRead = sizeof(short); |
FSRead(readRefNum, &toRead, (Ptr)&sizeIn); |
*tempPictHand = NewHandle(sizeIn); |
HLock(*tempPictHand); |
toRead = sizeIn; |
FSRead(readRefNum, &toRead, (Ptr)(*(*tempPictHand))); |
HUnlock(*tempPictHand); |
*tempPictRects = NewHandle(sizeof(Rect)); |
HLock(*tempPictRects); |
toRead = sizeof(Rect); |
FSRead(readRefNum, &toRead, (Ptr)(*(*tempPictRects))); |
HUnlock(*tempPictRects); |
tempPictRects += 1; |
tempPictHand += 1; |
} |
HUnlock((*newWinControl)->pictHandle); |
HUnlock((*newWinControl)->pictRects); |
} |
/* get any text */ |
toRead = sizeof(short); |
FSRead(readRefNum, &toRead, (Ptr)&aShort); |
if (aShort) { /* if this has value (numerically, not ethically) then we need to make a TERecord */ |
CharsHandle theText; |
Rect innerRect; |
theText = (CharsHandle)NewHandle(aShort); |
HLock((Handle)theText); |
toRead = aShort; |
FSRead(readRefNum, &toRead, (Ptr)*theText); |
/* read in the rect */ |
toRead = sizeof(Rect); |
FSRead(readRefNum, &toRead, (Ptr)&(*newWinControl)->textBox); |
/* and create the TEControl */ |
innerRect = (*newWinControl)->textBox; |
InsetRect(&innerRect, 3, 3); |
(*newWinControl)->boxHandle = TENew(&innerRect, &(*newWinControl)->textBox); |
TESetText((Ptr)*theText, aShort, (*newWinControl)->boxHandle); |
DisposeHandle((Handle)theText); |
} |
} |
FSClose(readRefNum); |
} |
/* LoadPrefs gets my preferences record out of the prefs file */ |
void LoadPrefs(void) |
{ |
Handle prefs; |
short prefFileID = OpenPrefsFile(); |
if (prefFileID) { |
UseResFile(prefFileID); |
/* load my private prefs resource */ |
prefs = Get1Resource(kMyPrefsResType, 128); |
if (prefs) { |
/* it exsists */ |
HLock(prefs); |
BlockMove((Ptr)*prefs, (Ptr)&gPreferences, sizeof(prefStruct)); |
/* first check our version please */ |
if(gPreferences.version != kCurrentPrefsVersion){ |
ReleaseResource(prefs); |
CloseResFile(prefFileID); |
if(noErr == KillOldPrefs()) |
LoadPrefs(); /* a little recursion in the morning */ |
else |
return; |
} |
/* parse through and see if we need to xfer object definitions */ |
if(gPreferences.saveWindDef){ |
HLock((Handle)gWindObjSpecHandle); |
BlockMove((Ptr)&gPreferences.savedWOD,(Ptr)*gWindObjSpecHandle,sizeof(WindowObjectDef)); |
HUnlock((Handle)gWindObjSpecHandle); |
} |
if(gPreferences.saveTextDef){ |
HLock((Handle)gTextObjSpecHandle); |
BlockMove((Ptr)&gPreferences.savedTOD,(Ptr)*gTextObjSpecHandle,sizeof(TextObjectDef)); |
HUnlock((Handle)gTextObjSpecHandle); |
} |
if(gPreferences.saveShapeDef){ |
HLock((Handle)gShapeObjSpecHandle); |
BlockMove((Ptr)&gPreferences.savedSOD,(Ptr)*gShapeObjSpecHandle,sizeof(ShapeObjectDef)); |
HUnlock((Handle)gShapeObjSpecHandle); |
} |
if(gPreferences.saveInteract){ |
gLocalInteraction = gPreferences.localInteraction; |
gAESendInteraction= gPreferences.sendInteraction; |
gAESwitchLayer= gPreferences.layerSwitch; |
} |
if(gPreferences.saveTarget)gAddressMode=gPreferences.targetMode; |
if(gPreferences.saveReply)gReplyMode = gPreferences.replyMode; |
HUnlock(prefs); |
ReleaseResource(prefs); |
} else { |
/* some default prefs if the resource is missing */ |
gPreferences.bringAEUp=true; |
gPreferences.verboseAE=true; |
} |
CloseResFile(prefFileID); |
} |
} |
/* SavePrefs saves my preferences, and creates the prefs resource if none exisiststsists */ |
void SavePrefs(void) |
{ |
Handle prefs; |
short prefFileID; |
/* if no change, don't bother */ |
if(!gPreferences.prefsChanged)return; |
prefFileID = OpenPrefsFile(); |
/* did the file open ??? */ |
if (prefFileID) { |
/* yeah, get our resource */ |
prefs = Get1Resource(kMyPrefsResType, 128); |
if (prefs) { |
/* it exixsts. */ |
HLock(prefs); |
gPreferences.version = kCurrentPrefsVersion; |
gPreferences.localInteraction=gLocalInteraction; |
gPreferences.sendInteraction=gAESendInteraction; |
gPreferences.layerSwitch=gAESwitchLayer; |
gPreferences.targetMode=gAddressMode; |
gPreferences.replyMode=gReplyMode; |
/* move our object data into this thing here */ |
HLock((Handle)gWindObjSpecHandle); |
BlockMove((Ptr)*gWindObjSpecHandle,(Ptr)&gPreferences.savedWOD,sizeof(WindowObjectDef)); |
HLock((Handle)gTextObjSpecHandle); |
BlockMove((Ptr)*gTextObjSpecHandle,(Ptr)&gPreferences.savedTOD,sizeof(TextObjectDef)); |
HLock((Handle)gShapeObjSpecHandle); |
BlockMove((Ptr)*gShapeObjSpecHandle,(Ptr)&gPreferences.savedSOD,sizeof(ShapeObjectDef)); |
BlockMove((Ptr)&gPreferences, (Ptr)*prefs, sizeof(prefStruct)); |
HUnlock(prefs); |
ChangedResource(prefs); |
} else { |
/* could not load the prefs resource, must not be there. Create a new one */ |
prefs = NewHandle(sizeof(prefStruct)); |
HLock(prefs); |
HLock((Handle)gWindObjSpecHandle); |
BlockMove((Ptr)*gWindObjSpecHandle,(Ptr)&gPreferences.savedWOD,sizeof(WindowObjectDef)); |
HLock((Handle)gTextObjSpecHandle); |
BlockMove((Ptr)*gTextObjSpecHandle,(Ptr)&gPreferences.savedTOD,sizeof(TextObjectDef)); |
HLock((Handle)gShapeObjSpecHandle); |
BlockMove((Ptr)*gShapeObjSpecHandle,(Ptr)&gPreferences.savedSOD,sizeof(ShapeObjectDef)); |
gPreferences.version = kCurrentPrefsVersion; |
BlockMove((Ptr)&gPreferences, (Ptr)*prefs, sizeof(prefStruct)); |
AddResource(prefs, kMyPrefsResType, 128, ""); |
ChangedResource(prefs); |
} |
UpdateResFile(prefFileID); |
CloseResFile(prefFileID); |
} |
} |
/* OpenPrefsFile opens, or creates and opens, my preferences file and returns */ |
/* the file reference number for it */ |
short OpenPrefsFile(void) |
{ |
Handle prefsNameStr; |
FSSpec prefsSpec; |
short foundVREF; |
short prefsID; |
OSErr error; |
long foundDIR; |
/* Use FindFolder to get the dir and volume IDs for the preferences folder */ |
/* on the current system disko */ |
FindFolder(kOnSystemDisk, kPreferencesFolderType, true, &foundVREF, &foundDIR); |
/* get the name of my prefs file (resource, so it can be localized */ |
prefsNameStr = GetResource('STR ', kPrefsFileString); |
HLock(prefsNameStr); |
FSMakeFSSpec(foundVREF, foundDIR, (Str255)*prefsNameStr, &prefsSpec); |
prefsID = FSpOpenResFile(&prefsSpec, fsRdWrPerm); |
/* ¥¥¥¥ Note: FSpOpenResFile returnd the file system error in ResError! */ |
/* read the Resource Manager chapter of IM VI for more details */ |
error = ResError(); |
if (prefsID == -1) { |
/* this means the prefs file couldn't be opened (IM VI chapter 13). find out why */ |
prefsID = 0; /* so later testing works better */ |
error = ResError(); |
if (error == fnfErr) { |
/* create the file, then reopen it */ |
FSpCreateResFile(&prefsSpec, kMySignature, kMyPrefsFileType, 0); |
if (ResError()) |
return(nil); /* bail */ |
prefsID = FSpOpenResFile(&prefsSpec, fsRdWrPerm); |
error = ResError(); |
if (error) |
return(nil); |
} |
} |
ReleaseResource(prefsNameStr); |
return(prefsID); |
} |
/* allows you to save the contents of the AEStatus window to disk. Can be handy */ |
void SaveAES(windowCHandle theWind, WindowPtr theWindPtr) |
{ |
#pragma unused (theWindPtr) |
OSErr myErr; |
Str255 savePrompt; |
Str63 defaultName; |
StandardFileReply saveReply; |
FSSpec saveFileSpec; |
Handle theText; |
long toWrite; |
long textSize = 0; |
long currentOffset = 0; |
char carrageRet = 0x0d; |
long oneByte = 1; |
short fileRef; |
Boolean myWasChanged; |
if (GetHandleSize((Handle)(*theWind)->fileAliasHandle) == 0) { |
GetIndString(savePrompt, kGeneralStrings, kAESSavePrompt); |
GetIndString(defaultName,kGeneralStrings,kAESDefaultName); |
StandardPutFile(savePrompt, defaultName, &saveReply); |
if (!saveReply.sfGood) |
return; |
saveFileSpec = saveReply.sfFile; |
if (saveReply.sfReplacing) |
FSpDelete(&saveFileSpec); |
} else { |
/* Resolve the old alias that was kept with the window */ |
/* in this case I don't care if the alias needed to be updated or not, this ain't */ |
/* a real time critical routine */ |
myErr = ResolveAlias(nil, ((*theWind)->fileAliasHandle), &saveFileSpec, &myWasChanged); |
if (myErr) { |
ShowMe("\pResolving Alias ", myErr, __LINE__); |
return; |
} |
/* kill current file, ignoring errors */ |
FSpDelete(&saveFileSpec); |
} |
SpinCursor(); |
/* I'm saving this as MPW TEXT */ |
myErr = FSpCreate(&saveFileSpec, kMPWSignature, 'TEXT', 1); |
if (myErr) { |
ShowMe("\pCreating AES file, Do you have it open in MPW? ", myErr, __LINE__); |
InitCursor(); |
return; |
} |
/* replace the nil handle with the alias record please, in our window data struct */ |
DisposeHandle((Handle)(*theWind)->fileAliasHandle); |
if (myErr = NewAlias(nil, &saveFileSpec, &((*theWind)->fileAliasHandle))) { |
ShowMe("\pDuring New Alias ", myErr, __LINE__); |
InitCursor(); |
return; |
} |
myErr = FSpOpenDF(&saveFileSpec, fsRdWrPerm, &fileRef); |
if (myErr) { |
ShowMe("\pOpening AES file Do you have it open in MPW?", myErr, __LINE__); |
SetMyCursor(actsToIDs[(*theWind)->currentAction]); |
return; |
} |
theText = (Handle)TEGetText((*theWind)->boxHandle); |
textSize = GetHandleSize(theText); |
HLock(theText); |
/* going to write 80 chars, carrage return, 80 chars, etc. */ |
do{ |
if(textSize > 80) |
toWrite = 80; |
else |
toWrite = textSize; |
myErr = FSWrite(fileRef, &toWrite, (Ptr)(*theText + currentOffset)); |
if(myErr){ |
ShowMe("\pWriting to AES file ", myErr, __LINE__); |
break; |
} |
if(textSize < 80){ |
break; |
} else { |
SpinCursor(); |
FSWrite(fileRef, &oneByte, (Ptr)&carrageRet); |
textSize -= 80; |
currentOffset +=80; |
} |
}while(true); |
HUnlock(theText); |
FSClose(fileRef); |
/* make sure it gets updated now. */ |
FlushVol("", saveFileSpec.vRefNum); |
InitCursor(); |
} |
OSErr KillOldPrefs(void) |
{ |
Handle prefsNameStr; |
FSSpec prefsSpec; |
short foundVREF; |
OSErr error; |
long foundDIR; |
FindFolder(kOnSystemDisk, kPreferencesFolderType, true, &foundVREF, &foundDIR); |
prefsNameStr = GetResource('STR ', kPrefsFileString); |
HLock(prefsNameStr); |
FSMakeFSSpec(foundVREF, foundDIR, (Str255)*prefsNameStr, &prefsSpec); |
error = FSpDelete(&prefsSpec); |
HUnlock(prefsNameStr); |
ReleaseResource(prefsNameStr); |
return(error); |
} |
#undef __FILES__ |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14