main.c

/*------------------------------------------------------------------------------
#
#   Apple Developer Technical Support
#
#   AppleEvents & Edition Manager Sample Application
#
#   AEObject-Edition Sample
#
#   main.c  -   C Source
#
#   Copyright © 1990-1992 Apple Computer, Inc.
#   All rights reserved.
#
#   Versions:   
#               1.0.1               2/92       C.K. Haun <TR>
#               1.0                11/91       C.K. Haun <TR>
#               based on the EditionSample
#   Components:
#                           main.c
#                           Menu.c
#                           Files.c
#                           Publish.c
#                           Subscribe.c
#                           TextSections.c
#                           Windows.c
#                           AppleEventCore.c
#                           AEObject-Edition Sample.make                          
#                           BuildHeaders.c
#                           AEUtilities.c
#                           AEObjects.c
#                           Utilities.c
#                           Initialize.c
#                           globals.c
#                           Print.c
#                           prototypes.h
#                           SampConstants.h
#                           Structs.h
#                           Macros.h
#                           Sampdefines.h
#
#  
#   This sample demonstrates the Apple Event Object model and
#   the Edition Manager.
#   It is an expanded version of the the earlier EditionSample,
#   most of the changes (besides bug fixes) have been made in the 
#   files AppleEventCore.c,AEUtilities.c and AEObjects.c.
#   I decided to add the Object Model demonstration to the Edition Sample
#   to use the objects (windows, shapes) that already existed 
#   instead of developing a new sample.
#   I beleive that the fuctional areas are discreet enough that 
#   you can find what you are looking for without too much difficulty,
#   the file names really do reflect the major contents of a
#   specific source file.  
#   
#   This sample contains most of the Edition Manager calls that
#   you'll need in your application.  It also contains one method
#   for keeping track of the edition data for all your documents.
#   It does NOT by any means demonstrate all the techniques 
#   you need for a large application, nor the best data handling 
#   methods for all cases.  
#   
#   This sample also implements some Apple Event Object model objects,
#   specifically cWindow, cText,cWord,cGraphicLine,cRectangle and cOval.
#
#   Use this sample as a starting point, and adapt its' routines to 
#   meet the specific needs of your project.  
#   This sample will grow as more edition types are implemented,
#   periodically check AppleLink for a later, expanded sample.
#   This application is an example of the form of a Macintosh 
#   application; it is NOT a template. It is NOT intended to be 
#   used as a foundation for the next world-class, best-selling, 
#   600K application. A stick figure drawing of the human body may 
#   be a good example of the form for a painting, but that does not 
#   mean it should be used as the basis for the next Mona Lisa.
#   This sample's focus is the Edition Manager and AppleEvents, NOT
#   drawing or text editing, so those areas are implemented in
#   a very minimal fashion.  This is done to prevent obscuring the
#   goal of this sample.  If you are interested in those (or other)
#   areas, please look for a sample that focuses on them.
#
#
------------------------------------------------------------------------------*/
#define __SAMPMAIN__
 
#pragma segment Main
 
#include "Sampdefines.h"
#include <SegLoad.h>
 
extern void _DataInit();
main()
{
    WindowPtr twindow;
    Boolean x;
    Boolean menuAction;
    windowCHandle tempWCH;       
    PScrapStuff theScrap;
    short myScrapCount = -999;                               /* intialize to a silly value */
    UnloadSeg((Ptr)_DataInit);                              /* throw the bums out */
    StartStuff();                                           /* initialize managers and normal startup actions */
    UnloadSeg((Ptr)StartStuff);
    theScrap = InfoScrap();
    FlushEvents(everyEvent, 0);
    mousergn = NewRgn();
    gStop = false;
    while (!gStop){
    
    x = WaitNextEvent(everyEvent, &gERecord, gMySleep,mousergn);
        theScrap = InfoScrap();
        if (theScrap->scrapCount != myScrapCount) {
            myScrapCount = theScrap->scrapCount;
            UpdateScrap(true);
        }
        if (FrontWindow() != nil) {
        /* if there is a text box, idle the cursor */
            TEHandle tempTE;
            windowCHandle tempWCH = (windowCHandle)GetWRefCon(FrontWindow());
            tempTE = (*tempWCH)->boxHandle;
            if (tempTE != nil)
                TEIdle(tempTE);             
        }
        switch (gERecord.what) {short fHit;
            case nullEvent:
            /* marching ants as necessary */
            DoAnts(nil);
                break;
            case updateEvt:
                DrawIt((WindowPtr)gERecord.message);                                   /* draw whatever window needs an update */
                break;
            case mouseDown:
                /* first see where the hit was */
                fHit = FindWindow(gERecord.where, &twindow);
                switch (fHit) {Rect limitRect;
                              long back;
                              Str255 tempString;
                    case inDesk:                            /* if they hit in desk, then the process manager */
                        break;                              /* will switch us out, we don't need to do anything */
                    case inMenuBar:
                        /* If they clicked in the menu bar, we need to set up the Undo */
                        /* text string for the current window, and the toggle of */
                        /* Publisher or Subscriber options before we drop the */
                        /* menu down. */
                        /* Also change the Save string depending on the save state */
                        /* Pull our aux data structure out of the current window */
                        if (FrontWindow()) {
                            tempWCH = (windowCHandle)GetWRefCon(FrontWindow());
                            HLock((Handle)tempWCH);          /* lock it */
                            AdjustMenus(tempWCH,FrontWindow());            /* in menu.c */
                            HUnlock((Handle)tempWCH);
                        } else {
                            AdjustMenus(nil,nil);
                        }
                        /* Now we drop the menu down, and pass the results */
                        /* to our menu handler (in Menu.c) */
                        menuAction = DoSelected(MenuSelect(gERecord.where));
                        break;
                    case inSysWindow:
                        /* pass to the system */
                        SystemClick(&gERecord, twindow);
                        break;
                    case inContent:
                        /* Our major workarea.  Depending on other factors, a */
                        /* user could be drawing, moving a subscriber, selecting */
                        /* a publisher or subscriber, selecting an area, or nothing. */
                        /* First, if they did not click in the front window, we need */
                        /* to bring the window they did click in to the front, and */
                        /* pull the information we need (cursor mode, undo action, etc. ) */
                        /* out of the aux record and update things */
                        if (twindow != FrontWindow()) {
                            ChangePlane(twindow);
                        } else {
                            if (FrontWindow()) {           /* don't do this unless we have a window open, silly */
                                windowCHandle clicker;
                                clicker = (windowCHandle)GetWRefCon(twindow);
                                /* jump to the content function stored for this window */
                                HLock((Handle)clicker);     /* lock it down so things don't get stupid */
                                (ProcPtr)((*clicker)->clickMe)(twindow);
                                HUnlock((Handle)clicker);       /* all done */
                            }
                        }
                        break;
                    case inDrag:
                        DragWindow(twindow, gERecord.where, &qd.screenBits.bounds);
                        break;
                    case inGrow:
                     SetPort(twindow);
                        limitRect = qd.screenBits.bounds;
                        limitRect.top = kMinHeight;
                        GetWTitle(twindow, tempString);
                        /* I'm not letting the user shrink the window so */
                        /* small that the title is truncated */
                        limitRect.left = StringWidth(tempString) + 120;
                        back = GrowWindow(twindow,gERecord.where, &limitRect);
                        if (back) {windowCHandle tempWCH = (windowCHandle)GetWRefCon(twindow);
                            Rect sizeRect = ((WindowPtr)twindow)->portRect;                            
                            sizeRect.top = sizeRect.bottom - 16;
                            sizeRect.left = sizeRect.right - 16;
                            EraseRect(&sizeRect);
                            InvalRect(&sizeRect);                            
                            SizeWindow(twindow, back & 0xffff, back >> 16, true);
                            (ProcPtr)((*tempWCH)->sizeMe)(twindow);                         
                        }
                       
                        InvalRect(&twindow->portRect);
                        break;
 
                    case inGoAway:
                        /* Track a click in the go away box.  If the user stays in it, */
                        /* call the close proc for this window */
                        if (TrackGoAway(twindow, gERecord.where))
                            (ProcPtr)((*(windowCHandle)((WindowPeek)twindow)->refCon)->closeMe)(twindow);
                        break;
                    case inZoomIn:
                    case inZoomOut:
                    if (TrackBox(twindow, gERecord.where, fHit)) {windowCHandle tempWCH = (windowCHandle)GetWRefCon(twindow);
                            SetPort(twindow);                            
                            ZoomWindow(twindow, fHit, true);
                            InvalRect(&twindow->portRect);                        
                        (ProcPtr)((*tempWCH)->sizeMe)(twindow);
                        }
 
                    break;                                      
                }
            case mouseUp:
                /* don't care */
                break;
                /* same action for key or auto key */
            case keyDown:
            case autoKey:
                /* Do menu commands.  */
                /* Also check the window record for a TextEdit field, if there */
                /* is one pass the key to it */
                if (gERecord.modifiers & cmdKey) {
                    if (FrontWindow()) {
                        tempWCH = (windowCHandle)GetWRefCon(FrontWindow());
                        HLock((Handle)tempWCH);              /* lock it */
                        AdjustMenus(tempWCH,FrontWindow());                /* in menu.c */
                        HUnlock((Handle)tempWCH);
                    } else {
                        AdjustMenus(nil,nil);
                    }
                    menuAction = DoSelected(MenuKey(gERecord.message & charCodeMask));
                } else {
                    WindowPtr tempWP = FrontWindow();
                    tempWCH = (windowCHandle)GetWRefCon(tempWP);
                    if (((WindowPeek)tempWP)->windowKind == kDocumentWindow && ((*tempWCH)->boxHandle != nil)) {
                    
                        Boolean wasPC = false;
                        tempWCH = (windowCHandle)GetWRefCon(tempWP);
                        
                        if ((*tempWCH)->textSections != nil) {
                            /* this text box has sections, and the sections may need to be */
                            /* adjusted by this keystroke.  First, see if it's a pure cursor move, */
                            if (wasPC= PureCursor(gERecord.message & charCodeMask))
                                wasPC = SkipOverSubscriber(tempWCH, gERecord.message & charCodeMask);
                            else
                                CheckTextSections(tempWCH, kKeyStroke);
                        }
                        if (!wasPC) {
                            /* ExcludeSubscriber shortens the current selection if it impact on any */
                            /* subscribers */
                            ExcludeSubscriber(tempWCH);
                            TEKey(gERecord.message & charCodeMask, (*tempWCH)->boxHandle);
                            KillSelection(tempWCH);
                        }
                   
                    }
                    if(((WindowPeek)tempWP)->windowKind == kAEStatusWindow)AESKey(gERecord.message & charCodeMask,tempWCH);
                }
                break;
            case keyUp:
                /* don't care */
                break;
            case diskEvt:
                /* I don't do anything special for disk events, this just passes them */
                /* to a function that checks for an error on the mount */
                DoDiskEvents(gERecord.message);
                break;
            case activateEvt:
                /* Draws on a window activate.  Other activate/deactivate stuff is */
                /* handled in either the ChangePlane function (for normal shuffling ) */
                /* or in the suspend/resume handler for layer swaps */
                if (gERecord.modifiers & activeFlag){
                   ChangePlane((WindowPtr)gERecord.message);
                    DrawIt((WindowPtr)gERecord.message);
                    } else {
                     windowCHandle tempWCH = (windowCHandle)GetWRefCon((WindowPtr)gERecord.message);
                                if ((*tempWCH)->boxHandle != nil)
                                    TEDeactivate((*tempWCH)->boxHandle);
                    }
                break;
            case networkEvt:
                /* don't care */
                break;
            case driverEvt:
                /* don't care */
                break;
            case app4Evt:
                switch ((gERecord.message >> 24) & 0x0FF) {     /* high byte of message */
                    case suspendResumeMessage:              /* suspend/resume is also an activate/deactivate */
                        gInBackground = (gERecord.message & kResumeMask) == 0;
                        if (gInBackground) {
                            SpitClip();    /* export the clipboard please */
                            /* If the clipboard is showing, hide it, since a clipboard */
                            /* is not valid when you are in another layer */
                            if(((WindowPeek)FindClipWindow())->visible == true)CloseClip(FindClipWindow());
                            /* deactivate the current TextEdit record as necessary */
                            if (FrontWindow() != nil) {
                                windowCHandle tempWCH = (windowCHandle)GetWRefCon(FrontWindow());
                                if ((*tempWCH)->boxHandle != nil)
                                    TEDeactivate((*tempWCH)->boxHandle);
                            /* set sleep value very high, since I'm doing no nul processing */      
                            gMySleep = -1;
                            }
                            if (gShowSub || gShowPub) {
                            /* I forget what this is here for.  Oh well */    
                            }
                        } else {
                        gMySleep = 5;   /* wake up more */
                            if (FrontWindow() != nil) {
                                windowCHandle tempWCH = (windowCHandle)GetWRefCon(FrontWindow());
                                if ((*tempWCH)->boxHandle != nil)
                                    TEActivate((*tempWCH)->boxHandle);
                            }
                        }
                        break;
                    case mouseMovedMessage:
                    AdjustCursor(gERecord.where, mousergn);
                    break;
                }
                break;
                /* This dispatches high level events (AppleEvents, for example) */
                /* to our dispatch routine.  This is NEW in the event loop for */
                /* System 7 */
            case kHighLevelEvent:
                DoHighLevel(gERecord);
                break;
            default:
                break;
 
                
        }       
    }
    /* save current prferences on exit */
    SavePrefs();    
}
 
 
/* DrawIt calls the drawing routine for the window that requires a refresh,
* either for a update or activate 
*/
void DrawIt(WindowPtr theWindow)
{
    WindowPtr  tempwind;
    windowCHandle tempWCH;
    GetPort(&tempwind);                                     /* save the current port */                                                                                         
    BeginUpdate(theWindow);                                   /* tell window manager to do it's thing */
    SetPort(theWindow);
    EraseRgn(theWindow->visRgn);                              /* erase whatever needs updating, remember that
                                                            BeginUpdate copies the update region into the visRgn */
    /* pull our control structure out of the refCon */
    tempWCH = (windowCHandle)GetWRefCon(theWindow);
    HLock((Handle)tempWCH);                                 /* lock it down so things don't get stupid */
    /* jump to the drawing function stored for this window */
    (ProcPtr)((*tempWCH)->drawMe)(tempWCH, theWindow);
    HUnlock((Handle)tempWCH);                               /* all done */
    EndUpdate(theWindow);                                     /* all done */
    SetPort(tempwind);                                      /* reset the port to the entry port */
}
 
/* DrawIt */
 
 
 
void DeBorderSelection(void)
{
    if (gShowPub) {
        gShowPub = false;
        gShowingSecHandle = nil;
        InsetRect(&gShowPubRect, kNegFour, kNegFour);
        InvalRect(&gShowPubRect);
        InsetRect(&gShowPubRect, kFour, kFour);
    } else {
        if (gShowSub) {
            gShowSub = false;
            gShowingSecHandle = nil;
            InsetRect(&gShowSubRect, kNegFour, kNegFour);
            InvalRect(&gShowSubRect);
            InsetRect(&gShowSubRect, kFour, kFour);
        }
    }
}
 
/* Just in case I need a nothing proc, here's one.  In Main so I'm not dragging in other segments */
void NilProc(void)
{
}
 
 
 
#undef __SAMPMAIN__