home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-10-16 | 19.3 KB | 845 lines | [TEXT/MPS ] |
- /*------------------------------------------------------------------------------------------
-
- Program: CPlusTESample 2.0AE
- File: TESample.cp
- Uses: TEDocument.h
- TESample.h
-
- by Andrew Shebanow
- of Apple Macintosh Developer Technical Support
- with modifications by Eric Berdahl
-
- Copyright © 1989-1990 Apple Computer, Inc.
- Copyright © 1992 Eric Berdahl
- All rights reserved.
-
- ------------------------------------------------------------------------------------------*/
-
- #ifndef __TYPES__
- #include <Types.h>
- #endif
- #ifndef __QUICKDRAW__
- #include <QuickDraw.h>
- #endif
- #ifndef __FONTS__
- #include <Fonts.h>
- #endif
- #ifndef __EVENTS__
- #include <Events.h>
- #endif
- #ifndef __CONTROLS__
- #include <Controls.h>
- #endif
- #ifndef __WINDOWS__
- #include <Windows.h>
- #endif
- #ifndef __MENUS__
- #include <Menus.h>
- #endif
- #ifndef __TEXTEDIT__
- #include <TextEdit.h>
- #endif
- #ifndef __DIALOGS__
- #include <Dialogs.h>
- #endif
- #ifndef __DESK__
- #include <Desk.h>
- #endif
- #ifndef __SCRAP__
- #include <Scrap.h>
- #endif
- #ifndef __TOOLUTILS__
- #include <ToolUtils.h>
- #endif
- #ifndef __MEMORY__
- #include <Memory.h>
- #endif
- #ifndef __SEGLOAD__
- #include <SegLoad.h>
- #endif
- #ifndef __FILES__
- #include <Files.h>
- #endif
- #ifndef __OSUTILS__
- #include <OSUtils.h>
- #endif
- #ifndef __TRAPS__
- #include <Traps.h>
- #endif
- #ifndef __PACKAGES__
- #include <Packages.h>
- #endif
- #ifndef __ERRORS__
- #include <Errors.h>
- #endif
-
- // our class definitions
- #ifndef __AEOBJECTS__
- #include "AEObjects.h"
- #endif
- #ifndef __AEREGISTRY__
- #include "AERegistry.h"
- #endif
- #ifndef __TEDOCUMENT__
- #include "TEDocument.h"
- #endif
- #ifndef __TESAMPLE__
- #include "TESample.h"
- #endif
-
- // ExtremeNeg and ExtremePos are used to set up wide open rectangles and regions.
- const short kExtremeNeg = -32768;
- const short kExtremePos = 32767 - 1; // required to address an old region bug
-
- // kMaxOpenDocuments is used to determine whether a new document can be opened
- // or created. We keep track of the number of open documents, and disable the
- // menu items that create a new document when the maximum is reached. If the
- // number of documents falls below the maximum, the items are enabled again.
- const short kMaxOpenDocuments = 4;
-
- const OSType kCreatorType = 'MOOT';
-
- // Define max and min macros for efficiency.
- #define max(a,b) ((a) > (b) ? (a) : (b))
- #define min(a,b) ((a) < (b) ? (a) : (b))
-
- // main is the entrypoint to the program
- int main()
- {
- // Create our application object. This MUST be the FIRST thing
- // done in main(), since it initializes the Toolbox for us.
- // And since we really don’t need more than one, and since
- // it’s faster and less heap-fragmenting to allocate it on the
- // stack, we do.
- TESample theApp;
-
- theApp.ProcessArgs();
-
- // Start our main event loop running. This won't return until user quits
- theApp.EventLoop();
-
- // We always return a value, like good little ANSI worshippers,
- // so that the compiler won't complain
- return 0;
- }
-
- // the constructor for our class, called automatically when we create
- // an instance of this class. In this particular case, we only want
- // one instance since the constructor does all the menu setups and
- // creates our (untitled) document.
- // Note that we call our base TApplication constructor, passing it
- // our creator signature constant.
- TESample::TESample() : TApplication(kCreatorType)
- {
- Handle menuBar;
-
- // initialize AppleEvent code
- MAppleObject::InitAppleObject();
-
- // read menus into menu bar
- menuBar = GetNewMBar(rMenuBar);
- // install menus
- SetMenuBar(menuBar);
- DisposHandle(menuBar);
- // add DA names to Apple menu
- AddResMenu(GetMHandle(mApple), 'DRVR');
- // add font names to Font menu
- AddResMenu(GetMHandle(mFont), 'FONT');
- DrawMenuBar();
-
- // create empty mouse region
- fMouseRgn = NewRgn();
- // make sure we have a valid cursor region
- AdjustCursor();
-
- MAppleObject::SetDefaultAppleObject(this);
- }
-
- TESample* TESample::GetTEApplication()
- {
- return (TESample*) TApplication::GetApplication();
- }
-
- // Tell TApplication class how much heap we need
- long TESample::HeapNeeded()
- {
- return (kMinSize * 1024);
- }
-
- // Calculate a sleep value for WaitNextEvent. This takes into account the things
- // that DoIdle does with idle time.
-
- unsigned long TESample::SleepVal()
- {
- unsigned long sleep;
-
- sleep = kMaxSleepTime; // default value for sleep
- // if we aren't in background, let document tell us how long to sleep
- if ((!fInBackground) && (fCurDoc != nil))
- sleep = min(sleep,fCurDoc->CalcIdle());
- return sleep;
- }
-
- // This is called whenever we get a null event et al.
- // It takes care of necessary periodic actions. For this program,
- // it calls TEIdle.
-
- void TESample::DoIdle()
- {
- TEDocument* fTECurDoc = (TEDocument*) fCurDoc;
-
- if (fTECurDoc != nil)
- fTECurDoc->DoIdle();
- } // DoIdle
-
- // Change the cursor's shape, depending on its position. This also calculates a
- // region that includes the cursor for WaitNextEvent.
-
- void TESample::AdjustCursor()
- {
- TEDocument* fTECurDoc = (TEDocument*) fCurDoc;
-
- // notice that we don't change cursor if front window isn't ours
- if ( (!fInBackground) && (fTECurDoc != nil) )
- {
- RgnHandle arrowRgn;
- RgnHandle iBeamRgn;
- Point mouse;
-
- // get mouse location and convert to global coordinates
- GetMouse(&mouse);
- LocalToGlobal(&mouse);
-
- // calculate regions for different cursor shapes
- arrowRgn = NewRgn();
- iBeamRgn = NewRgn();
- // start arrowRgn wide open
- SetRectRgn(arrowRgn, kExtremeNeg, kExtremeNeg, kExtremePos, kExtremePos);
- // calculate iBeamRgn
- fTECurDoc->GetVisTERgn(iBeamRgn);
- // subtract iBeamRgn from arrowRgn
- DiffRgn(arrowRgn, iBeamRgn, arrowRgn);
-
- // change the cursor and the region parameter
- if (PtInRgn(mouse, iBeamRgn))
- {
- SetCursor(*GetCursor(iBeamCursor));
- CopyRgn(iBeamRgn, fMouseRgn);
- }
- else
- {
- SetCursor(&qd.arrow);
- CopyRgn(arrowRgn, fMouseRgn);
- }
- // get rid of regions we don't need anymore
- DisposeRgn(arrowRgn);
- DisposeRgn(iBeamRgn);
- }
- } // AdjustCursor
-
- // Enable and disable menus based on the current state. The
- // user can only select enabled menu items. We set up all the
- // menu items before calling MenuSelect or MenuKey, since
- // these are the only times that a menu item can be selected.
- // Note that MenuSelect is also the only time the user will
- // see menu items. This approach to deciding what enable/
- // disable state a menu item has the advantage of
- // concentrating all the decision-making in one routine, as
- // opposed to being spread throughout the application. Other
- // application designs may take a different approach that may
- // or may not be as valid.
-
- void TESample::AdjustMenus()
- {
- WindowPtr frontmost;
- MenuHandle fileMenu, editMenu;
- long offset;
- Boolean undo;
- Boolean cutCopyClear;
- Boolean paste;
- Boolean save, saveAs;
- Boolean selectAll;
- TEDocument* fTECurDoc = (TEDocument*) fCurDoc;
-
- frontmost = FrontWindow();
-
- fileMenu = GetMHandle(mFile);
- if (fDocList->NumDocs() < kMaxOpenDocuments)
- {
- // New & Open are enabled when we can open more documents
- EnableItem(fileMenu, iNew);
- EnableItem(fileMenu, iOpen);
- }
- else
- {
- DisableItem(fileMenu, iNew);
- DisableItem(fileMenu, iOpen);
- }
- if (frontmost != (WindowPtr) nil) // Close is enabled when there is a window to close
- EnableItem(fileMenu, iClose);
- else DisableItem(fileMenu, iClose);
-
- editMenu = GetMHandle(mEdit);
- undo = false;
- cutCopyClear = false;
- paste = false;
- save = saveAs = false;
- selectAll = false;
- if (frontmost != nil)
- {
- selectAll = true;
- if (fCurDoc == nil)
- {
- undo = true; // all editing is enabled for DA windows
- cutCopyClear = true;
- paste = true;
- }
- else
- {
- // Cut, Copy, and Clear is enabled for app. windows with selections
- if ( fTECurDoc->HaveSelection() )
- cutCopyClear = true;
- // If we have any TEXT in the scrap, enable paste
- if ( GetScrap(nil, 'TEXT', &offset) )
- paste = true;
- // enable save if we are dirty
- save = fCurDoc->CanSave();
- saveAs = fCurDoc->CanSaveAs();
- }
- }
- if (save)
- EnableItem(fileMenu, iSave);
- else DisableItem(fileMenu, iSave);
- if (saveAs)
- EnableItem(fileMenu, iSaveAs);
- else DisableItem(fileMenu, iSaveAs);
-
- if (undo)
- EnableItem(editMenu, iUndo);
- else DisableItem(editMenu, iUndo);
- if ( cutCopyClear )
- {
- EnableItem(editMenu, iCut);
- EnableItem(editMenu, iCopy);
- EnableItem(editMenu, iClear);
- }
- else
- {
- DisableItem(editMenu, iCut);
- DisableItem(editMenu, iCopy);
- DisableItem(editMenu, iClear);
- }
- if (paste)
- EnableItem(editMenu, iPaste);
- else DisableItem(editMenu, iPaste);
- if (selectAll)
- EnableItem(editMenu, iSelectAll);
- else DisableItem(editMenu, iSelectAll);
-
- MenuHandle fontMenu, fontSizeMenu, styleMenu;
- fontMenu = GetMHandle(mFont);
- fontSizeMenu = GetMHandle(mFontSize);
- styleMenu = GetMHandle(mStyle);
- if (frontmost == (WindowPtr) nil) // the “font” menus are disabled if there is no doc
- {
- DisableItem(fontMenu, 0);
- DisableItem(fontSizeMenu, 0);
- DisableItem(styleMenu, 0);
- }
- else
- {
- EnableItem(fontMenu, 0);
- EnableItem(fontSizeMenu, 0);
- EnableItem(styleMenu, 0);
-
- short fontSize = fTECurDoc->GetSelectionFontSize();
- CheckItem(fontSizeMenu, i9Point, fontSize == 9);
- CheckItem(fontSizeMenu, i10Point, fontSize == 10);
- CheckItem(fontSizeMenu, i12Point, fontSize == 12);
- CheckItem(fontSizeMenu, i14Point, fontSize == 14);
- CheckItem(fontSizeMenu, i18Point, fontSize == 18);
- CheckItem(fontSizeMenu, i24Point, fontSize == 24);
-
- short fontID = fTECurDoc->GetSelectionFont();
- short nFonts = CountMItems(fontMenu);
- short i;
- for (i = 1; i <= nFonts; i++)
- CheckItem(fontMenu, i, false);
- for (i = 1; i <= nFonts; i++)
- {
- Str255 fontName;
- short aFontID;
- GetItem(fontMenu, i, fontName);
- GetFNum(fontName, &aFontID);
- if (aFontID == fontID)
- {
- CheckItem(fontMenu, i, true);
- break;
- }
- }
-
- CheckItem(styleMenu, iPlain, fTECurDoc->SelectionIsPlain());
- CheckItem(styleMenu, iBold, fTECurDoc->SelectionIsBold());
- CheckItem(styleMenu, iItalic, fTECurDoc->SelectionIsItalic());
- CheckItem(styleMenu, iUnderline, fTECurDoc->SelectionIsUnderline());
- CheckItem(styleMenu, iOutline, fTECurDoc->SelectionIsOutline());
- CheckItem(styleMenu, iShadow, fTECurDoc->SelectionIsShadow());
- }
-
- } // AdjustMenus
-
-
- // This is called when an item is chosen from the menu bar (after calling
- // MenuSelect or MenuKey). It does the right thing for each command.
-
- void TESample::DoMenuCommand(short menuID, short menuItem)
- {
- short itemHit;
- short fontSize;
- Str255 fontName;
- Str255 daName;
- short daRefNum;
- WindowPtr window;
- TEDocument* fTECurDoc = (TEDocument*) fCurDoc;
-
- window = FrontWindow();
- switch ( menuID )
- {
- case mApple:
- switch ( menuItem )
- {
- case iAbout: // bring up alert for About
- itemHit = Alert(rAboutAlert, nil);
- break;
- default: // all non-About items in this menu are DAs et al
- GetItem(GetMHandle(mApple), menuItem, daName);
- daRefNum = OpenDeskAcc(daName);
- break;
- }
- break;
- case mFile:
- switch ( menuItem )
- {
- case iNew:
- DoNew();
- break;
- case iOpen:
- DoOpen();
- break;
- case iClose:
- if (fTECurDoc != nil)
- {
- // only close the document if the user doesn't cancel
- if (fTECurDoc->DoClose(true, yesResult, false) != cancelResult)
- {
- fDocList->RemoveDoc(fTECurDoc);
- delete fTECurDoc;
- }
- }
- else CloseDeskAcc(((WindowPeek) fWhichWindow)->windowKind);
- // make sure our current document/window references are valid
- fWhichWindow = FrontWindow();
- if (fWhichWindow != nil)
- {
- fCurDoc = fDocList->FindDoc(fWhichWindow);
- SetPort(fWhichWindow);
- }
- else fCurDoc = nil;
- break;
- case iSave:
- if (fTECurDoc != nil)
- fTECurDoc->DoSave();
- break;
- case iSaveAs:
- if (fTECurDoc != nil)
- fTECurDoc->DoSaveAs();
- break;
- case iQuit:
- DoQuit(true, yesResult);
- break;
- }
- break;
- case mEdit: // call SystemEdit for DA editing & MultiFinder
- if (!SystemEdit(menuItem-1))
- {
- switch (menuItem)
- {
- case iCut:
- fTECurDoc->DoCut();
- break;
- case iCopy:
- fTECurDoc->DoCopy();
- break;
- case iPaste:
- fTECurDoc->DoPaste();
- break;
- case iClear:
- fTECurDoc->DoClear();
- break;
- case iSelectAll:
- fTECurDoc->DoSelectAll();
- break;
- }
- }
- break;
- case mFont:
- GetItem(GetMHandle(mFont), menuItem, fontName);
- fTECurDoc->SetFontName(fontName);
- break;
- case mFontSize:
- switch (menuItem)
- {
- case i9Point:
- fontSize = 9;
- break;
- case i10Point:
- fontSize = 10;
- break;
- case i12Point:
- fontSize = 12;
- break;
- case i14Point:
- fontSize = 14;
- break;
- case i18Point:
- fontSize = 18;
- break;
- case i24Point:
- fontSize = 24;
- break;
- }
- fTECurDoc->SetFontSize(fontSize);
- break;
- case mStyle:
- switch (menuItem)
- {
- case iPlain:
- fTECurDoc->SetPlain();
- break;
- case iBold:
- fTECurDoc->SetBold(!fTECurDoc->SelectionIsBold());
- break;
- case iItalic:
- fTECurDoc->SetItalic(!fTECurDoc->SelectionIsItalic());
- break;
- case iUnderline:
- fTECurDoc->SetUnderline(!fTECurDoc->SelectionIsUnderline());
- break;
- case iOutline:
- fTECurDoc->SetOutline(!fTECurDoc->SelectionIsOutline());
- break;
- case iShadow:
- fTECurDoc->SetShadow(!fTECurDoc->SelectionIsShadow());
- break;
- }
- break;
- }
- HiliteMenu(0); // unhighlight what MenuSelect (or MenuKey) hilited
- } // DoMenuCommand
-
- // Create a new document and window.
-
- void TESample::DoNew()
- {
- TEDocument* tDoc;
-
- tDoc = new TEDocument(rDocWindow);
- FailNIL(tDoc);
-
- TRY
- {
- tDoc->OpenNewDoc();
- fDocList->AddDoc(tDoc);
- }
- RECOVER
- {
- delete tDoc;
- }
- ENDTRY
- } // DoNew
-
- void TESample::OpenADoc(short vRefNum, long dirID, StringPtr fName, OSType fType)
- {
- if (fType != kTEFileType)
- Failure(eBadFileType,kTEDocErrStrings);
-
- TEDocument* tDoc = new TEDocument(rDocWindow);
- FailNIL(tDoc);
-
- TRY
- {
- FSSpec fileSpec;
-
- fileSpec.vRefNum = vRefNum;
- fileSpec.parID = dirID;
- CopyPString(fileSpec.name, fName);
-
- tDoc->OpenOldDoc(fileSpec,false);
- fDocList->AddDoc(tDoc);
- }
- RECOVER
- {
- delete tDoc;
- }
- ENDTRY
- }
-
- void TESample::DoOpen()
- {
- Point where;
- Str255 prompt;
- SFTypeList typeList;
- SFReply reply;
- short vRefNum;
- long dirID;
-
- SetPt(&where,100,100);
- prompt[0] = '\0';
- typeList[0] = kTEFileType;
- SFGetFile(where,prompt,(FileFilterProcPtr) nil,
- 1,typeList,(DlgHookProcPtr) nil,&reply);
- if (reply.good == false)
- return;
-
- WDToDirID(reply.vRefNum,vRefNum,dirID);
- OpenADoc(vRefNum,dirID,reply.fName, kTEFileType);
- }
-
-
- DescType TESample::GetAppleClass() const
- {
- return typeNull;
- }
-
-
- long TESample::CountContainedObjects(DescType ofType)
- {
- long result = 0;
-
- switch (ofType)
- {
- case cWindow:
- result = this->DocList()->NumDocs();
- break;
- }
-
- // now, add the number of objects contained by parents
- result += MAppleObject::CountContainedObjects(ofType);
-
- return result;
- }
-
-
- void TESample::DoAppleEvent(const AppleEvent& message, AppleEvent& reply, long refCon)
- {
- switch (refCon)
- {
- case cFinderNew:
- this->DoFinderNew(message, reply);
- break;
- case cFinderOpen:
- this->DoFinderOpen(message, reply);
- break;
- case cFinderPrint:
- this->DoFinderPrint(message, reply);
- break;
- case cFinderQuit:
- this->DoFinderQuit(message, reply);
- break;
- case cNewElement:
- this->DoAppleNewElement(message, reply);
- break;
- default:
- MAppleObject::DoAppleEvent(message, reply, refCon);
- break;
- }
- }
-
-
- MAppleObject* TESample::GetContainedObject(DescType desiredType, DescType keyForm,
- const AEDesc& keyData, Boolean& needDisposal)
- {
- MAppleObject* result = nil;
-
- switch (desiredType)
- {
- case cWindow:
- result = this->GetWindowObject(keyForm, keyData);
- needDisposal = false;
- break;
- }
-
- // if we can’t find it, let the parent find it
- if (result == nil)
- result = MAppleObject::GetContainedObject(desiredType, keyForm, keyData, needDisposal);
-
- return result;
- }
-
-
- Boolean TESample::CompareAppleObjects(DescType operation, const MAppleObject& toWhat)
- {
- return MAppleObject::CompareAppleObjects(operation, toWhat);
- }
-
-
- void TESample::DoFinderNew(const AppleEvent& message, AppleEvent& /* reply */)
- {
- MAppleObject::GotRequiredParameters(message);
- this->DoNew();
- }
-
-
- void TESample::DoFinderOpen(const AppleEvent& message, AppleEvent& /* reply */)
- {
- AEDescList listOfFiles;
- OSErr theErr;
-
- FailOSErr(AEGetParamDesc(&message, keyDirectObject, typeAEList, &listOfFiles));
- TRY
- {
- long numFiles;
- FailOSErr(AECountItems(&listOfFiles, &numFiles));
-
- for (long i = 1; i <= numFiles; i++)
- {
- TRY
- {
- DescType actualType;
- FSSpec theFileSpec;
- AEKeyword theActualKey;
- Size actualSize;
- FInfo finderInfo;
-
- FailOSErr(AEGetNthPtr(&listOfFiles, i, typeFSS, &theActualKey,
- &actualType, (Ptr) &theFileSpec,
- sizeof(theFileSpec), &actualSize));
- FailOSErr(FSpGetFInfo(&theFileSpec, &finderInfo));
-
- MAppleObject::GotRequiredParameters(message);
- this->OpenADoc(theFileSpec.vRefNum, theFileSpec.parID, theFileSpec.name,
- finderInfo.fdType);
- }
- RECOVER
- {
- goto processNextFile;
- }
- ENDTRY
-
- processNextFile:
- ;
- }
- }
- RECOVER
- {
- theErr = AEDisposeDesc(&listOfFiles);
- }
- ENDTRY
-
- theErr = AEDisposeDesc(&listOfFiles);
- }
-
-
- void TESample::DoFinderPrint(const AppleEvent& /* message */, AppleEvent& /* reply */)
- {
- // we don’t print from the finder, yet
- }
-
-
- void TESample::DoFinderQuit(const AppleEvent& message, AppleEvent& /* reply */)
- {
- MAppleObject::GotRequiredParameters(message);
- fDone = true;
- }
-
-
- MAppleObject* TESample::GetWindowObject(DescType form, const AEDesc& selectionData)
- {
- WindowPtr theWindow = nil;
-
- OSErr ignoreErr;
-
- switch (form)
- {
- case formName:
- {
- AEDesc theNameDesc;
- Str255 theName;
- Size stringSize;
- FailOSErr(AECoerceDesc(&selectionData, cText, &theNameDesc));
- stringSize = GetHandleSize(theNameDesc.dataHandle);
- if (stringSize < 256)
- {
- theName[0] = (char) stringSize;
- BlockMove(*theNameDesc.dataHandle, &theName[1], stringSize);
- theWindow = GetWindowFromName(theName);
- }
- ignoreErr = AEDisposeDesc(&theNameDesc);
- }
- break;
- case formAbsolutePosition:
- {
- AEDesc indexDesc;
- short index;
- FailOSErr(AECoerceDesc(&selectionData, typeShortInteger, &indexDesc));
- index = *(short*)*indexDesc.dataHandle;
- ignoreErr = AEDisposeDesc(&indexDesc);
-
- theWindow = GetWindowFromIndex(index);
- }
- break;
- default:
- FailOSErr(errAEWrongDataType);
- }
-
- return (TEDocument*) DocList()->FindDoc(theWindow);
- }
-
-
- void TESample::DoAppleNewElement(const AppleEvent& message, AppleEvent& /* reply */)
- {
- DescType returnedType;
- DescType classOfNewElement;
- Size actualSize;
- FailOSErr(AEGetParamPtr(&message, keyAEObjToCreate, typeType, &returnedType,
- (Ptr) &classOfNewElement, sizeof(classOfNewElement),
- &actualSize));
-
- // we only create new windows
- if (classOfNewElement != cWindow)
- FailOSErr(errAEWrongDataType);
-
- MAppleObject::GotRequiredParameters(message);
-
- // create the new window
- this->DoNew();
- }
-
-
- WindowPtr GetWindowFromName(Str255 name)
- {
- WindowPtr result = FrontWindow();
- Str255 windowTitle;
-
- for (;result != nil;)
- {
- GetWTitle(result, windowTitle);
- if (EqualString(windowTitle, name, false, true))
- break;
-
- result = (WindowPtr) ((WindowPeek)result)->nextWindow;
- }
-
- return result;
- }
-
-
- WindowPtr GetWindowFromIndex(short index)
- {
- WindowPtr result = FrontWindow();
-
- for (short i = 1; i < index && result != nil; i++)
- result = (WindowPtr) ((WindowPeek)result)->nextWindow;
-
- return result;
- }