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)&nothing);       /* 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__