Publish.c

/*------------------------------------------------------------------------------
 *
 *  Apple Developer Technical Support
 *
 *  Edition publishing routines
 *
 *  Program:    AEObject-Edition Sample
 *  File:       Publish.c - C Source
 *
 *  by:         C.K. Haun <TR>
 *
 *  Copyright © 1990-1992 Apple Computer, Inc.
 *  All rights reserved.
 *
 *------------------------------------------------------------------------------
 * Publish handles most of the publishing housekeeping.  There is (are,am,be,whatever) 
 * some routines that are common to both publishing and subscribing, they 
 * are located in Subscribe.c 
 *----------------------------------------------------------------------------*/
#define __PUBLISH__
 
#pragma segment Publish
 
 
#include "Sampdefines.h"
 
 
/*  CreatePublisher takes the currently selected area in the current window 
*       and creates an edition.  It starts by setting up some default data 
*       structures and creating a preview picture.  
*       Then the user is prompted for a location and name for the publisher
*       with the NewPublisherDialog.  If the user clicks OK, then the edition
*       is created and the section handle and rectangle for this edition is
*       stored in my data structure for this window, and the first edition
*       is written out.
*/
 
OSErr CreatePublisher(OSType typeToMake,Boolean fromEvent,FSSpecPtr theSpec)
{
 
    NewPublisherReply myreply;
    Handle theData;
    Rect currentRect;
    mySectionDataHandle pubText;
    Str31 addPub;
    static pubCounter;
    OSErr myErr;
    FSSpecPtr theOwningDoc = nil;
    FSSpec tempSpec;
    windowCHandle shortName;
    extern Point expPoint;
    extern Boolean gExpanded;
    Boolean myWasChanged;
    /* we're publishing from the current, topmost window */
    shortName = (windowCHandle)GetWRefCon(FrontWindow());
    HLock((Handle)shortName);
    switch (typeToMake) {
        case kGenericPICTWord:
            currentRect = (*shortName)->selectionRect;
            /* take the rectangle we currently have selected, and make it a picture */
            theData = (Handle)MyMakePicture(&currentRect);      /* my function to make a PICT */
            /* Set up the reply record for the publisher dialog.  */
            myreply.usePart = false;                        /* must be false */
            myreply.previewFormat = kGenericPICTWord;                 /* type of data we're publishing */
            myreply.preview = theData;                      /* handle to the pict data */
            break;
        case kGenericTEXTWord:
            /* make text preview */
            myreply.usePart = false;                        /* must be false */
            myreply.previewFormat = kGenericTEXTWord;                 /* type of data we're publishing */
            pubText = GetTextSection(shortName, stPublisher);
            HLock((Handle)pubText);
            theData = (*pubText)->additionalData;                  /* duplicate the text for our preview */
            HandToHand(&theData);
            if (GetHandleSize(theData) > kMaxTextPreview)
                SetHandleSize(theData, kMaxTextPreview);
            
            myreply.preview = theData;
            break;
        case kCustomType:
            break;
    }
    GetLastEditionContainerUsed(&gEdSpec);                  /* get a new edition containter.  */
    /* this call gives us a duplicate of the last used, or if none used last, gives */
    /* us a default container */
    /* BY THE WAY - the 'last used' means the last used by the Edition Manager, not */
    /* by your application, so if you don't specify a default name then the */
    /* name that comes up as the default for the edition may be the last */
    /* name used by another application, or from the last time your */
    /* application was run.  So if you are concerned about this (like you */
    /* think it may confuse the user) set your own default */
    /* As a sidelight (and not guarenteed) an alias to the last edition container used */
    /* is stored in the 'Preferences' folder in the system folder */
    myreply.container = gEdSpec;                            /* put our file spec in the container to be filled */
    /* now set the default name to be the same as the window plus a count */
    GetWTitle(FrontWindow(), &myreply.container.theFile.name);
    GetIndString(addPub, kGeneralStrings, kDotPub);
    AppendString(myreply.container.theFile.name, addPub);
    NumToString((long)((*shortName)->numPubs) + 1, addPub);
    AppendString(myreply.container.theFile.name, addPub);
    if(!fromEvent){
    if (!gExpanded)
        myErr = NewPublisherDialog(&myreply);               /* run the dialog */
    else
    {
        ExpDlgHookUPP dhUPP = NewExpDlgHookProc(ExpOptHook);
        ExpModalFilterUPP mfUPP = NewExpModalFilterProc(ExpOptFilter);
        myErr = NewPublisherExpDialog(&myreply, expPoint, kExpandedDITL, dhUPP, mfUPP, nil);
        DisposeRoutineDescriptor(dhUPP);
        DisposeRoutineDescriptor(mfUPP);
    }
    
    if (myErr) {
        ShowMe("\pPubisher dialog", myErr,__LINE__);
        return(myErr);
    }
    if (myreply.canceled) {                                 /* they canceled.  release memory, reset our */
        /* menus and cursors, and go away */
        switch (typeToMake) {
            case kGenericPICTWord:
                KillPicture((PicHandle)theData);
                InvalRect(&(*shortName)->selectionRect);
                gShowPub = false;
                (*shortName)->hasSelection = false;
                SetMyCursor(0);
                SwitchChecks(kSelectStuff);
                
                break;
            case kGenericTEXTWord:
                DisposeHandle((*pubText)->additionalData);
                DisposeHandle((Handle)pubText);
                DisposeHandle(theData);
                break;
            case kCustomType:
                break;
        }
        return(userCanceledErr);
    }}
    /* They clicked Publish.  First create the container (file) to hold the data */
    /* See if thye are replacing a file */
    if (!myreply.replacing) {
        /* If we were given a spec by the event, the put that file in */
        if(theSpec)myreply.container.theFile=*theSpec;
        if (myErr = CreateEditionContainerFile(&myreply.container.theFile, kMySignature, myreply.container.theFileScript)) {
            ShowMe("\pCreateEditionContainerFIle", myErr,__LINE__);
            return(myErr);
        } 
        } else {
        /* they agreed to delete an existing file.  Kill it. */
        FSpDelete(&myreply.container.theFile);
        if (myErr = CreateEditionContainerFile(&myreply.container.theFile, kMySignature, myreply.container.theFileScript)) {
            ShowMe("\pCreateEditionContainerFIle", myErr,__LINE__);
            return(myErr);
 
        }
    }
    /* now create the section record to describe this data to the edition manager */
    /*  The section handle that is returned by this function will be the */
    /* way that you will reference this edition for as long as the edition is */
    /* active. */
    /* The main way you'll keep track is through the section ID number. */
    /* In this case, I have a base ID number for the window, and I just increment */
    /* my general ID (gSectionID) every time I create an edition, and add it to the window ID.  */
    if (GetHandleSize((Handle)(*shortName)->fileAliasHandle) == 0) {
        myErr = NewSection(&myreply.container, nil, stPublisher, (*shortName)->windowID + gSectionID, pumOnSave, &gSecHandle);
        /* nil for sectionDocument if it's never been saved */
    } else {
        /* if the file has been saved once, then we can store a reference to the 'parent' file */
        /* in the edition */
 
 
        myErr = ResolveAlias(nil, ((*shortName)->fileAliasHandle), &tempSpec, &myWasChanged);
        myErr = NewSection(&myreply.container, &tempSpec, stPublisher, (*shortName)->windowID + gSectionID, pumOnSave,
                           &gSecHandle);
        theOwningDoc=&tempSpec;
    }
        if (!myErr) {
        /* put the section handle into our window structure */
        (*gSecHandle)->refCon = kNeverSaved;                /*            meaning that this _document_ has not been saved */
        /* put what type of thing this is in the refcon of the section handle */
        switch (typeToMake) {
            /* This is a little kludgy because I want to */
            case kGenericPICTWord:
                (*gSecHandle)->refCon = kPictType;
                break;
            case kGenericTEXTWord:
                (*gSecHandle)->refCon = kTextType;
                break;
        }
        StorePublisher(shortName, gSecHandle, &(*shortName)->selectionRect, pubText, typeToMake);
    
    /* now write the data to the container */
    /* first make a spec from the saved alias, if there is one */
    MyWriteSection(gSecHandle, theData, typeToMake,theOwningDoc);
     } else {
        /* error creating the section */
        ShowMe("\p Couldn't create section", myErr,__LINE__);   
    }
    HUnlock(theData);
    switch (typeToMake) {
        case kGenericPICTWord:
            KillPicture((PicHandle)theData);
            break;
        case kGenericTEXTWord:
            break;
        case kCustomType:
            break;
    }
   
    (*shortName)->hasSelection = false;
    InvalRect(&(*shortName)->selectionRect);                /* get rid of border once publish has happened */
    gShowPub = false;
    (*shortName)->hasSelection = false;
    SetMyCursor(0);
    SwitchChecks(kSelectStuff);
    HUnlock((Handle)shortName);
}
 
/* end CreatePublisher */
 
/* MyUpdateEdition publishes the latest data for this edition.  This will
* be called when the user selects 'Send Edition Now' from the options
* dialog, or when the document is saved (if automatic saving is 
* enabled), or if a section write AppleEvent happens
*/
OSErr MyUpdateEdition(SectionHandle theSection)
{
    WindowPtr tempWindow;
    Boolean tempSub, tempPub;
    Boolean wasChanged;
    windowCHandle shortName;
    SectionHandle *tempPtr;
    FSSpecPtr theOwningDoc=nil;
    FSSpec owner;
    register qq;
    Rect *tempRectPtr;
    extern Rect gShowPubRect;
    extern Rect gShowSubRect;
    WindowPtr owningWindow = FindSection(theSection);
 
    GetPort(&tempWindow);
    shortName = (windowCHandle)GetWRefCon(owningWindow);
    HLock((Handle)shortName);
    if(GetHandleSize((Handle)(*shortName)->fileAliasHandle)){
    ResolveAlias(nil,(*shortName)->fileAliasHandle,&owner,&wasChanged);
    theOwningDoc=&owner;
    }
    if (((*theSection)->refCon & 0xf) == kPictType) {
        HLock((Handle)theSection);
        /* kill the borders, if any are showing right now */
        tempSub = gShowSub;
        tempPub = gShowPub;
        if (gShowSub)
            InvalRect(&gShowSubRect);
        if (gShowPub)
            InvalRect(&gShowPubRect);
        gShowSub = gShowPub = false;
        SetPort(owningWindow);
        (ProcPtr)((*shortName)->drawMe)(shortName, owningWindow);     /* draw without borders */
        /* 
        /* search this window for the section asked for */
        HLock((*shortName)->pubs);
        tempPtr = (SectionHandle *)*(*shortName)->pubs;
        for (qq = 0; qq < (*shortName)->numPubs; qq++) {
            HLock((Handle)*tempPtr);
            if ((*theSection)->sectionID == (*(*tempPtr))->sectionID) {
                PicHandle tempPic;
                /* it's this one, grab the rect, pic it, publish it, and go away */
                HLock((*shortName)->pubRects);
                tempRectPtr = (Rect *)*(*shortName)->pubRects;
                tempRectPtr += qq;
                tempPic = MyMakePicture(tempRectPtr);
                HUnlock((*shortName)->pubRects);
                MyWriteSection(*tempPtr, (Handle)tempPic, kGenericPICTWord,theOwningDoc);
                KillPicture(tempPic);
                HUnlock((Handle)*tempPtr);
                break;
            }
        }
        HUnlock((Handle)theSection);
        HUnlock((Handle)shortName);
    } else {
        mySectionDataHandle theTS = TextSectionFromSecHandle(theSection);
        /* it's a text pub */
        MyWriteSection(theSection, (*theTS)->additionalData, kGenericTEXTWord,theOwningDoc);
        
    }
    InvalRect(&owningWindow->portRect);
    SetPort(tempWindow);
    return(noErr);
}
 
/* end MyUpdateEdition */
 
/* MyMakePicture is a handy place to create our PICT demo data item.
* It's called to create the actual edition data as well as the 'preview'
* picture.
*/
PicHandle MyMakePicture(Rect *thisRect)
{
    PicHandle thepic;
    windowCHandle drawers;
    Boolean tempPub, tempSub;
    RgnHandle tempClip;
    /* make sure borders aren't included in the picture */
    tempPub = gShowPub;
    tempSub = gShowSub;
    gShowPub = false;
    gShowSub = false;
    tempClip = NewRgn();
    GetClip(tempClip);
    ClipRect(thisRect);
    thepic = OpenPicture(thisRect);
    drawers = (windowCHandle)GetWRefCon(FrontWindow() );
    HLock((Handle)drawers);
    (ProcPtr)((*drawers)->drawMe)(drawers, FrontWindow() );
    HUnlock((Handle)drawers);
    ClosePicture();
    SetClip(tempClip);
    DisposeRgn(tempClip);
    /* restore old border states */
    gShowPub = tempPub;
    gShowSub = tempSub;
    return(thepic);
}
 
/* end MyMakePicture */
 
/* AEWriteSectionHandler is the AppleEvent handler for section write
* events.   It first pulls the SectionHandle out of the AppleEvent record,
* then verifies that this is a registered section (still active, not canceled)
* and then calls MyUpdateEdition to write the edition
*/
pascal OSErr AEWriteSectionHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
{
#pragma unused (reply,refIn)
    SectionHandle theSection;
    OSErr myErr;
    myErr = GetSectionHandleFromEvent(messagein, &theSection);
 
    if (myErr = IsRegisteredSection((SectionHandle)theSection)) {
        ShowMe("\p Write IsRegisteredSection", myErr,__LINE__);
        return(myErr);
    }
    MyUpdateEdition(theSection);
    
}
 
/* end AEWriteSectionHandler */
/* ¥¥¥¥¥ REVISED!  This event has been revised since it's initial release */
/* to reflect the final definition of this event, and the object that it accepts  */
/* as a parameter */
/* ¥¥¥¥ NEW EVENT ¥¥¥¥ */
/* ¥¥ Please read the description and code in the Inside Mac vol VI chapters on */
/* the Edition Manager and APpleEvents for a full description */
/* AECreatePubHandler handles the new create publisher event */
 
pascal OSErr AECreatePubHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
{
#pragma unused (reply,refIn)
 
windowCHandle tempWC;
OSErr myErr = noErr;
Size returnedSize;
long savedStart,savedEnd;
Rect savedRect;
DescType returnedType = typeNull;
OSType theType;
AEDesc returnedToken;
AEDesc theObject;
FSSpec theFSSpec;
FSSpecPtr theFSS = nil;
CTextObjHandle cTextBack;
CWordObjHandle cWordBack;
CShapeObjHandle cShapeback;
 
WindowPtr containingWindow;
WindowPtr oldFront=nil;
theObject.descriptorType = typeNull;
returnedToken.descriptorType = typeNull;
oldFront = FrontWindow();
/* this event has two parameters, a object specifier and an alias handle. */
/* Both parameters are optional. */
/* if the object doesn't exsist, then we publish the current selection */
/* if the alias doesn't exsist, then we put up the options dialog */
AEGetParamDesc(messagein,keyDirectObject,typeObjectSpecifier,&theObject);
/* the AEM has a built-in coercion from alias to FSSpec */
AEGetParamPtr(messagein,keyAEEditionFileLoc,typeAlias,&returnedType,(Ptr)&theFSSpec,sizeof(FSSpec),&returnedSize);
if(typeFSS == returnedType)
    theFSS = &theFSSpec;
 
/* checking for null instead of for an error 
because I don't care if either of these error out, I just care if they return a descriptor 
or not.  Which I could do with two error variables, but you know.... */
/* Now resolve the object I got (if I got one)  */
if(theObject.descriptorType != typeNull) 
    myErr = AEResolve(&theObject, kAEIDoMinimum, &returnedToken);
 
if(!myErr){
/* so the action, will be something like this, since I am but a lowly  */
/* example program */
/* if the value returned from AEResolve is a graphic-type thing, I will put it's */
/* rectangle into the current selection, and call CreatePub. */
/* if it's a text thing, I will save the current selection, reset the selction, and */
/* call CreatePub.  I'm typing this in as a comment because I don't know if I'll */
/* get it implemented within my release timeframe, but that is the idea. */
/* Also, because of the way I initially designed this program, the publisher must */
/* be the front window.  Not a good idea, I will re-write that in a future release, */
/* but for now we live with it. */
    switch(returnedToken.descriptorType){
    /* get the owning window */
    case cText:
    theType = kGenericTEXTWord;
    cTextBack = (CTextObjHandle)returnedToken.dataHandle;
    containingWindow=(*cTextBack)->theOwningWindow;
    tempWC = (windowCHandle)GetWRefCon(containingWindow);
    /* save off current  */
    savedStart = (*(*tempWC)->boxHandle)->selStart;
    savedEnd=(*(*tempWC)->boxHandle)->selEnd;
    /* and since they asked for the whole text, make the end equal the beginning */
    (*(*tempWC)->boxHandle)->selEnd = (*(*tempWC)->boxHandle)->teLength;
    (*(*tempWC)->boxHandle)->selStart=0;
    /* and do the thing */
    SelectWindow(containingWindow);
    
    myErr = CreatePublisher(theType,true,theFSS);
    /* restore */
    (*(*tempWC)->boxHandle)->selStart = savedStart;
    (*(*tempWC)->boxHandle)->selEnd = savedEnd;
 
 
    break;
    
    case cWord:
    theType = kGenericTEXTWord;
    cWordBack = (CWordObjHandle)returnedToken.dataHandle;
    containingWindow=(*cWordBack)->theOwningWindow;
    tempWC = (windowCHandle)GetWRefCon(containingWindow);
    savedStart = (*(*tempWC)->boxHandle)->selStart;
    savedEnd=(*(*tempWC)->boxHandle)->selEnd;
    (*(*tempWC)->boxHandle)->selStart = (*cWordBack)->startPos;
    (*(*tempWC)->boxHandle)->selEnd = (*cWordBack)->endPos;
    /* do the thing */
    SelectWindow(containingWindow);
 
    myErr = CreatePublisher(theType,true,theFSS);
    (*(*tempWC)->boxHandle)->selStart = savedStart;
    (*(*tempWC)->boxHandle)->selEnd = savedEnd;
    break;
    case cGraphicLine:
    case cRectangle:
    case cOval:
    theType = kGenericPICTWord;
    /* save the current selection rect if any */
    cShapeback = (CShapeObjHandle)returnedToken.dataHandle;
    containingWindow=(*cShapeback)->theOwningWindow;
    tempWC = (windowCHandle)GetWRefCon(containingWindow);
    savedRect=(*tempWC)->selectionRect;
    (*tempWC)->selectionRect = (*(*cShapeback)->theShape)->theRect;
    SelectWindow(containingWindow);
 
    myErr = CreatePublisher(theType,true,theFSS);
    (*tempWC)->selectionRect = savedRect; 
    break;
    default:
    myErr = errAEEventNotHandled;   /* I don't know how to publish this object */
    break;
    }
} else {
/* Here, there was an object, but I couldn't understand it.  That is an _error_ */
/* condition, which is different from no object being available */
 
myErr= errAENoSuchObject;
}
 
/* if there was an old front window, make it frontmost agin */
if(oldFront)ChangePlane(oldFront);
return(myErr);
}
/* end AECreatePubHandler */
 
 
 
/* AEScrollSectionHandler handles the scroll section event.  You'll get this
* event when the user clicks 'Open Publisher' either from the 
* Subcriber Options dialog, or from the Finder window.
* This may also have happened after an ODOC AppleEvent, so 
* don't assume anything about your state that wouldn't be true 
* after an initial application launch
*/
pascal OSErr AEScrollSectionHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
{
#pragma unused (reply,refIn)
    WindowPtr tempWindow;
    SectionHandle theSection;
    OSErr myErr;
    myErr = GetSectionHandleFromEvent(messagein, &theSection);
    tempWindow = FindSection(theSection);
    /* First bring our application to the front, then */
    /* treat this the same way you would a click in a back window */
 
    myErr=AEInteractWithUser(kAEDefaultTimeout,nil, gCommonIdleFunctionUPP);
    if(!myErr)SetFrontProcess(&gOurSN);
        else ShowMe("\ptheEr",myErr,__LINE__);
    if (tempWindow != nil)
        ChangePlane(tempWindow);
    return(noErr);
}
 
/* end AEScrollSectionHandler */
 
/* AECancelSectionHandler cancels a current section, either a publisher
* or subscriber.  This function pulls the section handle out of the 
* AppleEvent, then dispatches to the proper cancel routine for a
* pub or sub.
*/
pascal OSErr AECancelSectionHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
{
#pragma unused (reply,refIn)
    SectionHandle theSection;
    OSErr myErr;
    myErr = GetSectionHandleFromEvent(messagein, &theSection);
    myErr = IsRegisteredSection(theSection);
    if (myErr != noErr)
        return(myErr);                                      /* already killed by someone */
    MyCancelSection(theSection, FindSection(theSection));
    
}
 
/* end AECancelSectionHandler */
 
/* MyWriteSection actually opens and writes the section data.  This will
* be called in response to a click in 'Send Edition Now' in the pub options
* box, from the section event 'write section', or when the file is being saved
* and 'pumAuto' is enabled
*/
OSErr MyWriteSection(SectionHandle secHandle, Handle theData, OSType theType,FSSpecPtr inSpec)
{
    OSErr myErr;
    /* update the time in the section handle please */
    /* this tells the Edition Manager that the eidtion has changed, and */
    /* to alert all the subscribers to the change */
 
    SpinCursor();
    HLock((Handle)secHandle);
    GetDateTime(&(*secHandle)->mdDate);                     /* ¥¥¥ Please see NOTE in main.c about mdDate (find mdDate) */
    HUnlock((Handle)secHandle);
    /* OpenNewEdition, _NOT_ OpenEdition.  You need to use OpenNewEdition */
    /* to get write access and to let the Edition Manager determine if you */
    /* are allowed to write to this section */
    myErr = OpenNewEdition(secHandle, kMySignature,inSpec, &gEdRefNum);
    if (myErr)
        ShowMe("\pOpenNewEdition", myErr,__LINE__);
    HLock(theData);
    /* And actually write the data (finally) */
    SpinCursor();
    myErr = WriteEdition(gEdRefNum, theType, *theData, GetHandleSize(theData));
    if (myErr)
        ShowMe("\pWriteEdition", myErr,__LINE__);
    if (myErr)
        myErr = 0;
    else
        myErr = -1;
    /* The Boolean tells the Edition Manager if you were successful in */
    /* writing the data. */
    myErr = CloseEdition(gEdRefNum, (Boolean)myErr);
            if(myErr)ShowMe("\pCloseEdition", myErr,__LINE__);
    return(myErr);
}
 
/* end MyWriteSection */
 
/* StorePublisher moves the window data struct storing function to here */
/* shortName is locked on entry */
void StorePublisher(windowCHandle shortName, SectionHandle storeSection, Rect *inRect, mySectionDataHandle textIn, OSType typeIn)
{
    Rect *tempRectPtr;
    SectionHandle *tempPtr;
    OSErr myErr;
    switch (typeIn) {
        case kGenericPICTWord:
            HUnlock((*shortName)->pubs);
            MySetHandleSize((*shortName)->pubs, GetHandleSize((*shortName)->pubs) + sizeof(Handle));
            myErr = MemError();
            if (myErr)
                ShowMe("\pMemory", myErr,__LINE__);
            HLock((*shortName)->pubs);
            tempPtr = (SectionHandle *)((*(*shortName)->pubs) + (sizeof(Handle) * ((*shortName)->numPubs)));
            *tempPtr = (SectionHandle)storeSection;
            /* ¥¥¥¥ NOTE, please look at the note in the Subscribe.c file concerning the dirty flag and  */
            /* editions.  Open Subscribe.c and find the string 'Human Interface' */
            /*    (*shortName)->windowDirty = true;  */
            /* save the rectangle to show the published rectangle if the user wants to see it. */
            HUnlock((*shortName)->pubRects);
            MySetHandleSize((*shortName)->pubRects, (GetHandleSize((*shortName)->pubRects) + sizeof(Rect)));
            myErr = MemError();
            if (myErr)
                ShowMe("\pMemory", myErr,__LINE__);
            HLock((*shortName)->pubRects);
            tempRectPtr = (Rect *)*(*shortName)->pubRects;
            tempRectPtr += (*shortName)->numPubs;
            *tempRectPtr = *inRect;
            (*shortName)->numPubs++;
            HUnlock((*shortName)->pubRects);
            HUnlock((*shortName)->pubs);
            break;
        case kGenericTEXTWord:
            /* set my text section ID to the same as the actual section ID, again, it keeps */
            /* dereferencing down */
            (*textIn)->theID = (*storeSection)->sectionID;
            /* tell myself that this is a publisher */
            (*textIn)->publishing = true;
            if ((*shortName)->textSections == nil) {
                (*shortName)->textSections = textIn;
            } else {
                mySectionDataHandle tempTS = (*shortName)->textSections;
                while ((*tempTS)->nextSection != nil) {
                    tempTS = (*tempTS)->nextSection;
                }
                (*tempTS)->nextSection = textIn;
            }
            (*textIn)->theSection = storeSection;
            break;
    }
    gSectionID++;
}
 
/* Find Section returns the window that this section is included in */
/* Need to look in both the PICT and TEXT lists */
WindowPtr FindSection(SectionHandle inSection)
{
     long subIDtofind;
    Boolean secFound = false;
    SectionHandle *tempPtr;
    SectionRecord *tempRecord;
    Handle tempHandle;
    WindowPtr tempNextWindow;
    register jj;
    subIDtofind = (*inSection)->sectionID;
    tempNextWindow = (WindowPtr)LMGetWindowList();  /* start at the beginning of the chain */
    while(tempNextWindow){
    if (((WindowPeek)tempNextWindow)->windowKind == kDocumentWindow){ /* the clipboard is not publishing */
        windowCHandle tempWC;
        /* do housekeeping to get to the section handle list */
        tempWC = (windowCHandle)GetWRefCon(tempNextWindow);
        HLock((Handle)tempWC);
        if (((*inSection)->refCon & 0xf) == kPictType) {
            tempHandle = (*tempWC)->pubs;                   /* handle containing SectionHandles */
            HLock(tempHandle);
            tempPtr = (SectionHandle *)*tempHandle;
            /* Loop through all our sections until we find this edition */
            for (jj = 0; jj < (*tempWC)->numPubs; jj++) {
                HLock((Handle)*tempPtr);
                tempRecord = *(*tempPtr);
                if (tempRecord->sectionID == subIDtofind) {
                    HUnlock((Handle)*tempPtr);
                    HUnlock((Handle)tempWC);
                    return(tempNextWindow);
                } else {
                    HUnlock((Handle)tempWC);
                    HUnlock((Handle)*tempPtr);
                    tempPtr += 1;
                }
            }
            HUnlock(tempHandle);
            /* same thing for subscribers */
            tempHandle = (*tempWC)->subs;                   /* handle containing SectionHandles */
            HLock(tempHandle);
            tempPtr = (SectionHandle *)*tempHandle;
            /* Loop through all our sections until we find this edition */
            for (jj = 0; jj < (*tempWC)->numSubs; jj++) {
                HLock((Handle)*tempPtr);
                tempRecord = *(*tempPtr);
                if (tempRecord->sectionID == subIDtofind) {
                    HUnlock((Handle)*tempPtr);
                    HUnlock((Handle)tempWC);
                    return(tempNextWindow);
                } else {
                    HUnlock((Handle)tempWC);
                    HUnlock((Handle)*tempPtr);
                    tempPtr += 1;
                }
            }
            HUnlock(tempHandle);
        } else {
            /* Look in the TEXT lists */
            if ((*tempWC)->textSections) {
                mySectionDataHandle tempTS = (*tempWC)->textSections;
                do {
                    if ((*((*tempTS)->theSection))->sectionID == subIDtofind) {
                        HUnlock((Handle)tempWC);
                        return(tempNextWindow);
                    }
                    tempTS = (*tempTS)->nextSection;
                } while (tempTS);
                
            }
        }
        tempNextWindow = (WindowPtr)((WindowPeek)tempNextWindow)->nextWindow; 
        
        HUnlock((Handle)tempWC);
        }   /* if document */
        tempNextWindow = (WindowPtr) ((WindowPeek)tempNextWindow)->nextWindow;
    } /* while windows */
    return(nil);
}
 
pascal short ExpOptHook(short itemOffset, short itemHit, DialogPtr theDialog, Ptr yourDataPtr)
{
 #pragma unused (yourDataPtr)
    short myHit;
    short itemType;
    ControlHandle theButton;
    Rect theRect;
    /* first make sure that a sub-dialog is not frontmost */
    /* so we don't filter keys or hits to a sub-dialog */
    if (GetWRefCon((WindowPtr)theDialog) == sfMainDialogRefCon || GetWRefCon((WindowPtr)theDialog) == emOptionsDialogRefCon) {
        /* only have one item in this expansion, but we'll check the range anyway */
        myHit = itemHit - itemOffset;                       /* since our item numbers are relative to the total number */
        /* of items in the dialog, and the system may change.  Always do your item numbering based */
        /* on the offset, this will prevent incompatability when the system dialog grows or shrinks */
        if (myHit == 1) {                                   /* I only added one item, so this be the one */
            /* Pass itemHit here, not myHit, since the dialog manager has no idea that this is an */
            /* additive dialog.  It is counting from the actual start of the DITL, not the start of */
            /* your custom items */
            GetDialogItem(theDialog, itemHit, &itemType, (Handle *)&theButton, &theRect);
            if (GetControlValue(theButton))
                SetControlValue(theButton, false);
            else
                SetControlValue(theButton, true);
        }
    }
    return(itemHit);                                        /* the return value must be absolute */
}
 
pascal Boolean ExpOptFilter(DialogPtr theDialog, EventRecord *theEvent, short itemOffset, short *itemHit, Ptr yourDataPtr)
{
#pragma unused (itemHit,yourDataPtr)
    short itemType;
    ControlHandle theButton;
    Rect theRect;
    /* first make sure that a sub-dialog is not frontmost */
    /* so we don't filter keys or hits to a sub-dialog */
    if (GetWRefCon((WindowPtr)theDialog) == sfMainDialogRefCon || GetWRefCon((WindowPtr)theDialog) == emOptionsDialogRefCon) {
        /* standard filter proc kinda stuff here */
        if ((theEvent->what) == keyDown) {
            char tempChar;
            tempChar = theEvent->message & charCodeMask;
            
            if (((tempChar == 'A') || (tempChar == 'a')) && (theEvent->modifiers & cmdKey)) {
                /* they pressed an A with the command key down, we get to handle it. */
                GetDialogItem(theDialog, itemOffset + 1, &itemType, (Handle *)&theButton, &theRect);
                if (GetControlValue(theButton))
                    SetControlValue(theButton, false);
                else
                    SetControlValue(theButton, true);
                
                return(true);                               /* tell folks we handled it */
            }
        }
    }
    return(false);                                          /* was not a keystroke we wanted */
    
}
 
/* shortName is locked on entry */
mySectionDataHandle GetTextSection(windowCHandle shortName, SectionType what)
{
    CharsHandle theRawText;
    TEHandle tempTE;
    mySectionDataHandle theTextSection;
    Handle theSelection;
    theTextSection = (mySectionDataHandle)NewHandle(sizeof(mySectionData));
    HLock((Handle)theTextSection);
    (*theTextSection)->bordered = gShowingAll;              /* create section reflecting current */
    /* global border state */
    tempTE = (*shortName)->boxHandle;
    (*theTextSection)->startChar = (*tempTE)->selStart;
    if (what == stPublisher) {
        /* initialize it if it's a publisher */
        (*theTextSection)->endChar = (*tempTE)->selEnd;
        
        theRawText = TEGetText(tempTE);
        theSelection = NewHandle(((*tempTE)->selEnd) - ((*tempTE)->selStart));
        
        HLock(theSelection);
        HLock((Handle)theRawText);
        BlockMove((Ptr)*theRawText + (*tempTE)->selStart, (Ptr)*theSelection, (*tempTE)->selEnd - (*tempTE)->selStart);
        HUnlock(theSelection);
        HUnlock((Handle)theRawText);
        (*theTextSection)->additionalData = theSelection;
    } else {
        /* set start same as end for subscribers */
        (*theTextSection)->endChar = (*tempTE)->selStart;
        (*theTextSection)->additionalData = NewHandle(0);
    }
    (*theTextSection)->nextSection = nil;
    return(theTextSection);
}
 
mySectionDataHandle TextSectionFromSecHandle(SectionHandle theSection)
{
    windowCHandle tempWC = (windowCHandle)GetWRefCon(FindSection(theSection));      /* gets the window it's in */
    mySectionDataHandle tempTS = (*tempWC)->textSections;
    unsigned long idToFind;
    
    idToFind = (*theSection)->sectionID;
    /* find the ID that matches this thang */
    do {
        if ((*tempTS)->theID == idToFind)
            return(tempTS);
        tempTS = (*tempTS)->nextSection;
    } while (tempTS);
    return(nil);                                            /* failed */
}
 
/* In SearchPubs we'll search the publishers in this window for a publisher */
/* that was clicked in.  If we find one, hilite it and outline it. */
/* Point is already in local coordinates */
Boolean SearchPubs(Point thePoint)
{
    register qq;
    Rect rectToCheck;
    Rect cornerRect;
    Rect *theRects;
    Str63 pubString;
    Boolean gotIt = false;
    windowCHandle shortname = (windowCHandle)GetWRefCon(FrontWindow());
    HLock((Handle)shortname);
    if ((*shortname)->numPubs) {                            /* does this window have any publishers? */
        /* yes, see if one was clicked in */
        HLock((*shortname)->pubRects);                      /* lock the rect handle down */
        theRects = (Rect *)*(*shortname)->pubRects;
        /* dereference it and cast it to a rect pointer so checking will be 
        *   conceptually easier (i.e. you can read it) 
        */
        for (qq = 0; qq < (*shortname)->numPubs; qq++) {        /* step through 'em */
            SectionHandle *tempPtr;
            rectToCheck = *theRects;
            if (PtInRect(thePoint, &rectToCheck)) {         /* thePoint is coming from your */
                /* last event record */
                /* We've found a section that has been clicked in */
                if (gShowPub && (rectToCheck != gShowPubRect))
                    InvalRect(&gShowPubRect);               /* clear previous, if there was one */
                gShowPub = true;
                if (gShowSub) {/* clear previous, if there was one */
                    InsetRect(&gShowSubRect, -4, -4);
                    InvalRect(&gShowSubRect);
                    InsetRect(&gShowSubRect, 4, 4);
 
                    gShowSub = false;
                }
                /* make sure the border gets draw next update */
                InsetRect(&rectToCheck,-4,-4);
                InvalRect(&rectToCheck);
                InsetRect(&rectToCheck,4,4);
                /* we've found it with it's rectangle, so now dig out the */
                /* section handle */
                HLock((*shortname)->pubs);
                tempPtr = (SectionHandle *)*(*shortname)->pubs;
                tempPtr += qq;
                /* and move the section handle into our global variable that */
                /* contains the currently highlighted section, so we can */
                /* access it from the Options function and dialog */
                gShowingSecHandle = *tempPtr;
                /* done with the pointer handle */
                HUnlock((*shortname)->pubs);
                /* change the menu item name now */
                GetIndString(pubString, kGeneralStrings, kPubOptString);
                
                SetMenuItemText(gEditMenuHandle, kSoptionsItem,pubString);
                gShowPubRect = rectToCheck;
                gotIt = true;
                /* Now we need to stretch the thing if the user wants too */
                /* See if it was in the corner rect first */
                cornerRect = gShowPubRect;
                cornerRect.top = cornerRect.bottom - 7;
                cornerRect.left = cornerRect.right - 7;
                if (PtInRect(thePoint, &cornerRect)) {
                    PullRect(shortname, &gShowPubRect, false, true,true);
                    if (*theRects != gShowPubRect) {
                        *theRects = gShowPubRect;
                        InvalRect(theRects);
                    }
                }
            }
            if (gotIt)
                break;
            theRects++;                                     /* increase by one Rect */
        }
        HUnlock((*shortname)->pubRects);
    }
    HUnlock((Handle)shortname);
    return(gotIt);
}
 
/* end SearchPubs */
 
 
#undef __PUBLISH__