home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-06-15 | 19.9 KB | 824 lines | [TEXT/CWIE] |
- /*
-
- File: AppleEventHandling.cp
- Project: Sprocket Framework 1.1 (DR2), released 6/15/96
- Contains: Minimalist support for the required and Display Manager AppleEvents
- We also support openning and printing “LetterSpec” documents for AOCE.
- To Do: To really support AppleScript™, we’ll need to do ALOT more work in here.
-
- Sprocket Major Contributors:
- ----------------------------
- Dave Falkenburg, producer of Sprocket 1.0
- Bill Hayden, producer of Sprocket 1.1
- Steve Sisak, producer of the upcoming Sprocket 2.0
-
- Pete Alexander Steve Falkenburg Randy Thelen
- Eric Berdahl Nitin Ganatra Chris K. Thomas
- Marshall Clow Dave Hershey Leonard Rosenthal
- Tim Craycroft Dave Mark Dean Yu
- David denBoer Gary Powell
- Cameron Esfahani Jon Summers Apple Computer, Inc.
-
- Comments, Additions, or Corrections:
- ------------------------------------
- Bill Hayden, Nikol Software <nikol@codewell.com>
-
- */
-
- #include "Sprocket.h"
-
- #ifndef __APPLEEVENTS__
- #include <AppleEvents.h>
- #endif
-
- #ifndef __AEREGISTRY__
- #include <AERegistry.h>
- #endif
-
- #ifndef __DISPLAYS__
- #include <Displays.h> // for Display Manager AppleEvent constants
- #endif
-
- #ifndef __PPCTOOLBOX__
- #include <PPCToolbox.h>
- #endif
-
- #ifndef __EPPC__
- #include <EPPC.h>
- #endif
-
- #if qInlineInputAware
- #ifndef __TEXTSERVICES__
- #include <TextServices.h>
- #endif
- #endif
-
- #include "AEHandling.h"
-
-
-
- static pascal Boolean StandardAEIdleProc(EventRecord *theEvent, long *sleepTime, RgnHandle *mouseRgn);
-
-
- AEDesc gThisProcessDesc;
-
-
-
- /*****************************************************************************/
-
-
-
- void InitAppleEventRoutines(void)
- {
- ProcessSerialNumber thisProcess;
-
- // Create useful AE Targets for our aplication
-
- // By building the target in this fashion, we get the best performance
- // out of the AppleEvent manager because it can call our event handlers
- // inline.
-
- thisProcess.highLongOfPSN = 0;
- thisProcess.lowLongOfPSN = kCurrentProcess;
- (void) AECreateDesc(typeProcessSerialNumber, (Ptr)&thisProcess, sizeof(ProcessSerialNumber), &gThisProcessDesc);
-
-
- // It’s probably more efficient to use a table to install these handlers…
-
- (void) AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, NewAEEventHandlerProc(HandleOpenApplication), 0, false);
- (void) AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, NewAEEventHandlerProc(HandleOpenDocuments), 0, false);
- (void) AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, NewAEEventHandlerProc(HandlePrintDocuments), 0, false);
- (void) AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, NewAEEventHandlerProc(HandleQuitApplication), 0, false);
-
- // regardless of whether or not we have the display manager, go ahead and register an AppleEvent handler
-
- (void) AEInstallEventHandler(kCoreEventClass, kAESystemConfigNotice, NewAEEventHandlerProc(HandleSystemConfigNotice), 0, false);
-
- // It’s probably more efficient to use a table to install these handlers…
-
- (void) AEInstallEventHandler(kSprocketCommandClass, kProcessOneCommand, NewAEEventHandlerProc(HandleSprocketCommand), 0, false);
-
- #if qInlineInputAware
- if (gHasTextServices)
- {
- (void) AEInstallEventHandler(kTextServiceClass, kUpdateActiveInputArea, NewAEEventHandlerProc(HandleTextServicesUpdateActiveInputArea), 0, false);
- (void) AEInstallEventHandler(kTextServiceClass, kPos2Offset, NewAEEventHandlerProc(HandleTextServicesPos2Offset), 0, false);
- (void) AEInstallEventHandler(kTextServiceClass, kOffset2Pos, NewAEEventHandlerProc(HandleTextServicesOffset2Pos), 0, false);
- // we don’t need to handle <kTextServiceClass, kShowHideInputWindow> events
- }
- #endif
- }
-
-
-
- /*****************************************************************************/
-
-
-
- OSErr CheckAppleEventForMissingParams(AppleEvent *theAppleEvent)
- {
- DescType returnedType;
- Size actualSize;
- OSErr err;
-
- err = AEGetAttributePtr(theAppleEvent,keyMissedKeywordAttr,typeWildCard,
- &returnedType,nil,0,&actualSize);
-
- if (err == errAEDescNotFound) // If we couldn’t find the error attribute
- return noErr; // everything is ok, return noErr
-
- if (err == noErr) // We found an error attribute, so
- return errAEEventNotHandled; // tell the client we ignored the event
-
- return err; // Something else happened, return it
- }
-
-
-
- /*****************************************************************************/
-
-
-
- OSErr ChooseApplicationAsAETarget(AEAddressDesc *targetDesc, StringPtr prompt)
- {
- PortInfoRec thePortInfo;
- LocationNameRec theLocation;
- TargetID theTargetID;
- OSErr err;
-
- err = PPCBrowser(prompt, "\p", false, &theLocation, &thePortInfo, (PPCFilterUPP) NULL, "\p");
- if (err == noErr)
- {
- theTargetID.name = thePortInfo.name;
- theTargetID.location = theLocation;
-
- err = AECreateDesc(typeTargetID, &theTargetID, sizeof(theTargetID), targetDesc);
- }
-
- return err;
- }
-
-
-
-
- /*****************************************************************************/
-
-
-
- AEIdleUPP StandardAEIdleUPP = NewAEIdleProc(StandardAEIdleProc);
-
- static pascal Boolean
- StandardAEIdleProc(EventRecord *theEvent, long * /* sleepTime */, RgnHandle * /* mouseRgn */)
- {
- HandleEvent(theEvent); // First, always hand event off to our event handling code
- return false;
- }
-
-
-
-
- /*****************************************************************************/
-
-
-
-
- OSErr ForEachDocumentInList(AEDescList documentList,
- EachDocumentProcPtr documentProc,
- void * documentParam)
- {
- long documentCount,documentIndex;
- DescType returnedType;
- Size actualSize;
- FSSpec theFSSpec;
- AEKeyword keyword;
- OSErr err;
-
- if ((err = AECountItems(&documentList, &documentCount)) != noErr)
- return err;
-
- for (documentIndex=1; documentIndex <= documentCount; documentIndex++)
- {
- err = AEGetNthPtr(&documentList, documentIndex, typeFSS, &keyword, &returnedType,
- (Ptr) &theFSSpec, sizeof(theFSSpec), &actualSize);
-
- if (err == noErr)
- (*documentProc)(&theFSSpec, documentParam);
- else
- break;
- }
-
- return err;
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma mark ••• Required Events Support •••
-
-
- pascal OSErr HandleOpenApplication(AppleEvent *theAppleEvent,AppleEvent * /*reply*/,long /*refCon*/)
- {
- OSErr err;
-
- if ((err = CheckAppleEventForMissingParams(theAppleEvent)) != noErr)
- return err;
-
- return(CreateNewDocument());
- }
-
-
-
- /*****************************************************************************/
-
-
-
-
- pascal OSErr HandleOpenDocuments(AppleEvent* theAppleEvent, AppleEvent* /*reply*/, long /*refCon*/)
- {
- AEDescList documentList;
- OSErr err;
-
- if ((err = AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList, &documentList)) != noErr)
- return err;
-
- if ((err = CheckAppleEventForMissingParams(theAppleEvent)) != noErr)
- return err;
-
- err = ForEachDocumentInList(documentList, &OpenDocument, nil);
- (void) AEDisposeDesc(&documentList);
- return err;
- }
-
-
-
-
- /*****************************************************************************/
-
-
-
-
- pascal OSErr HandlePrintDocuments(AppleEvent *theAppleEvent, AppleEvent * /*reply*/, long /*refCon*/)
- {
- AEDescList documentList;
- #if qUseQuickDrawGX
- AEDescList desktopPrinterList;
- FSSpec thePrinterFSSpec;
- Boolean draggedToDesktopPrinter = false;
- #endif
- OSErr err;
-
- if ((err = AEGetParamDesc(theAppleEvent,keyDirectObject,typeAEList,&documentList)) != noErr)
- return err;
-
- #if qUseQuickDrawGX
- if (noErr == AEGetAttributeDesc(theAppleEvent, keyOptionalKeywordAttr, typeAEList, &desktopPrinterList))
- draggedToDesktopPrinter = true;
- #endif
-
- if ((err = CheckAppleEventForMissingParams(theAppleEvent)) != noErr)
- return err;
-
- #if qUseQuickDrawGX
- if (draggedToDesktopPrinter)
- {
- DescType returnedType;
- Size actualSize;
- AEKeyword keyword;
-
- err = AEGetNthPtr(&desktopPrinterList, 1, typeFSS, &keyword, &returnedType,
- (Ptr) &thePrinterFSSpec, sizeof(thePrinterFSSpec), &actualSize);
-
- (void) AEDisposeDesc(&desktopPrinterList);
- }
- err = ForEachDocumentInList(documentList, &PrintDocument, draggedToDesktopPrinter ? &thePrinterFSSpec : NULL);
- (void) AEDisposeDesc(&documentList);
- #else
- err = ForEachDocumentInList(documentList, &PrintDocument, nil);
- #endif
-
- return err;
- }
-
-
-
- /*****************************************************************************/
-
-
-
-
- pascal OSErr HandleQuitApplication(AppleEvent *theAppleEvent,AppleEvent * /* reply */,long /* refCon */)
- {
- OSErr err;
-
- if ((err = CheckAppleEventForMissingParams(theAppleEvent)) != noErr)
- return err;
-
- gDone = QuitApplication();
-
- if (gDone)
- return noErr;
- else
- return userCanceledErr;
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma mark ••• Sprocket Suite Support •••
-
- OSErr SendCommandToSelf(CommandID theCommand)
- {
- OSErr err;
- AEAddressDesc theTarget;
- AppleEvent quitAE, replyAE;
- ProcessSerialNumber psn;
-
-
- if (!gHasAppleScript) // don't bother recording, just queue the command and return
- {
- err = QueueCommand(theCommand);
- return err;
- }
-
- psn.highLongOfPSN = 0;
- psn.lowLongOfPSN = kCurrentProcess;
-
- err = AECreateDesc(typeProcessSerialNumber,
- (Ptr)&psn,
- sizeof(ProcessSerialNumber),
- &theTarget);
-
- if (err == noErr)
- {
- err = AECreateAppleEvent(kSprocketCommandClass, kProcessOneCommand, &theTarget,
- kAutoGenerateReturnID, kAnyTransactionID, &quitAE);
-
- if (err == noErr)
- {
- err = AEPutParamPtr( &quitAE, keyDirectObject, typeLongInteger,
- (Ptr)(&theCommand), sizeof(CommandID) );
- }
-
- if (err == noErr)
- {
- err = AESend(&quitAE, &replyAE, kAENoReply + kAECanInteract,
- kAENormalPriority, 3600, NULL, NULL);
- }
-
- err = AEDisposeDesc(&theTarget);
- }
-
- return err;
- }
-
-
-
- /*****************************************************************************/
-
-
-
- pascal OSErr HandleSprocketCommand(AppleEvent* theAppleEvent, AppleEvent* /*reply*/, long /*refCon*/)
- {
- CommandID theCommand;
- OSErr err;
- long actualSize;
- DescType actualType;
-
-
- err = AEGetParamPtr(theAppleEvent, keyDirectObject, typeLongInteger, &actualType,
- (UInt32 *)&theCommand, sizeof(UInt32), &actualSize);
- if (err)
- return err;
-
- err = CheckAppleEventForMissingParams(theAppleEvent);
-
- if (err)
- return err;
-
- err = QueueCommand(theCommand);
-
- return err;
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma mark ••• Display Manager Support •••
-
- static OSErr HandleDeviceChange(DisplayIDType displayID, Rect *newRect);
- static Boolean OutOfBoundsRect(GDHandle gd, WindowRef window, Rect screenRect);
- static void MoveInbounds(WindowRef window, GDHandle gd, Rect screenRect);
- static void ResizeInbounds(WindowRef window, GDHandle gd, Rect screenRect);
- static GDHandle GetGreatestDevice(WindowRef window);
- static void GetWindowRect(WindowRef window, Rect *windRect);
- static void ResetStdState(WindowRef window);
-
- #define kFudgeFactor 4 // fudge factor for boundary around window
- #define kTitleBarHeight 18 // title bar height
-
-
-
- pascal OSErr
- HandleSystemConfigNotice(AppleEvent *event, AppleEvent * /* reply */,long /* refCon */)
- {
- OSErr err;
- GrafPtr oldPort;
- AEDescList displayList;
- AEDescList aDisplay;
- AERecord oldConfig,newConfig;
- AEKeyword tempWord;
- DisplayIDType displayID;
- unsigned long returnType;
- long count;
- Rect oldRect, newRect;
-
- GetPort(&oldPort);
-
- // Get a list of the displays from the Display Notice AppleEvent.
- err = AEGetParamDesc(event, kAEDisplayNotice, typeWildCard, &displayList);
- // How many items in the list
- err = AECountItems(&displayList,&count);
-
- while (count > 0)
- { // Loop through the list.
- err = AEGetNthDesc(&displayList, count, typeWildCard, &tempWord, &aDisplay);
-
- // Get the Old Rect.
- err = AEGetNthDesc(&aDisplay, 1, typeWildCard, &tempWord,
- &oldConfig);
- err = AEGetParamPtr(&oldConfig, keyDeviceRect, typeWildCard,
- &returnType, &oldRect, 8, nil);
-
- // Get the DisplayID so we can get the GDevice later.
- err = AEGetParamPtr(&oldConfig, keyDisplayID, typeWildCard,
- &returnType, &displayID, 8, nil);
-
- // Get the New Rect.
- err = AEGetNthDesc(&aDisplay, 2, typeWildCard, &tempWord, &newConfig);
- err = AEGetParamPtr(&newConfig, keyDeviceRect, typeWildCard,
- &returnType, &newRect, 8, nil);
-
- // If the New and Old rects are not the same then we can assume
- // the GDevice has changed and we need to rearrange the windows.
-
- if (err == noErr && !EqualRect(&newRect, &oldRect))
- HandleDeviceChange(displayID, &newRect);
-
- count--;
- err = AEDisposeDesc(&aDisplay);
- err = AEDisposeDesc(&oldConfig);
- err = AEDisposeDesc(&newConfig);
- }
-
- err = AEDisposeDesc(&displayList);
- SetPort(oldPort);
-
- return err;
- }
-
-
-
- /*****************************************************************************/
-
- //----------------------------------------------------------------------
- //
- // HandleDeviceChange - called when the oldconfig is different from
- // newconfig. Will check all windows on effected
- // device and move if needed.
- //----------------------------------------------------------------------
-
- static OSErr HandleDeviceChange(DisplayIDType displayID, Rect *newRect)
- {
- OSErr err = noErr;
- GDHandle gd;
- GDHandle onGD;
- WindowRef window;
- Rect oldRect = *newRect; // save it for AdjustWindowSize
-
- // Get the GDevice from the DisplayID.
-
- err = DMGetGDeviceByDisplayID((DisplayIDType) displayID, &gd, false);
-
- if (err == noErr && gd != nil)
- {
- window = FrontWindow();
-
- while (window != nil)
- {
- SetPortWindowPort(window);
- // which device holds the greatest portion of the window
- onGD = GetGreatestDevice(window);
-
- // If the window is not 50% or greater on
- // the desired device then pass it up.
- if (onGD == gd)
- {
- if (OutOfBoundsRect(gd, window, *newRect))
- {
- MoveInbounds(window, gd, *newRect);
- if (OutOfBoundsRect(gd, window, *newRect))
- {
- ResizeInbounds(window, gd, *newRect);
-
- // If it is one of our document windows then we need
- // to reset the std state and the scroll bars.
- TWindow* thisWindow = GetWindowObject(window);
-
- if (thisWindow)
- thisWindow->AdjustForNewWindowSize(&oldRect, newRect);
- }
- }
-
- ResetStdState(window);
- }
-
- window = GetNextWindow(window);
- }
- }
-
- return err;
-
- }
-
-
-
- /*****************************************************************************/
-
-
-
- // Check to see if the window is out of the device rect.
-
- static Boolean OutOfBoundsRect(GDHandle gd, WindowRef window, Rect screenRect)
- {
- Boolean out = false;
- Rect windRect;
- short mHeight = 0;
-
- GetWindowRect(window, &windRect);
-
- if (gd == GetMainDevice())
- mHeight = GetMBarHeight();
-
- if ((windRect.right > screenRect.right) || (windRect.bottom > screenRect.bottom))
- out = true;
-
- if ((windRect.left < screenRect.left) || (windRect.top < screenRect.top + mHeight))
- out = true;
-
- return out;
-
- }
-
-
-
- /*****************************************************************************/
-
-
-
- // Move window onto the desired device
-
- static void MoveInbounds(WindowRef window, GDHandle gd, Rect screenRect)
- {
- Rect bounds;
- short mHeight = 0;
- short hGlobal;
- short vGlobal;
-
- GetWindowRect(window, &bounds);
-
- if (gd == GetMainDevice())
- mHeight = GetMBarHeight();
-
- hGlobal = bounds.left;
- vGlobal = bounds.top + kTitleBarHeight;
-
- // We want to make the left-top a priority so adjust it first
- // as to override the bottom, right movements. This is so we
- // can resize the window later.
-
- if (((bounds.right - bounds.left) > (screenRect.right - screenRect.left)) ||
- ((bounds.bottom - bounds.top) >
- ((screenRect.bottom - screenRect.top) - mHeight)))
- {
-
- // adjust left
- if (bounds.left < screenRect.left)
- hGlobal = screenRect.left + kFudgeFactor;
-
- // adjust top
- if (bounds.top < screenRect.top + mHeight)
- vGlobal = screenRect.top + kTitleBarHeight + mHeight + kFudgeFactor;
-
- }
- else
- {
- // adjust left
- if (bounds.left < screenRect.left)
- hGlobal = screenRect.left + kFudgeFactor;
- else
- {
- // adjust right
- if (bounds.right > screenRect.right)
- hGlobal = (screenRect.right - (bounds.right - bounds.left)) - kFudgeFactor;
- }
-
- // adjust top
- if (bounds.top < screenRect.top + mHeight)
- vGlobal = screenRect.top + kTitleBarHeight + mHeight + kFudgeFactor;
-
- else {
- // adjust bottom
- if (bounds.bottom > screenRect.bottom)
- vGlobal = (screenRect.bottom - kFudgeFactor -
- (bounds.bottom - bounds.top) + mHeight);
- }
-
- }
-
- MoveWindow(window, hGlobal, vGlobal,false);
-
- }
-
-
-
-
- /*****************************************************************************/
-
-
-
- // Resize the window to fit in the graphics device
-
- static void ResizeInbounds(WindowRef window, GDHandle gd, Rect screenRect)
- {
- Rect windRect;
- short h;
- short v;
-
-
- windRect = (GetWindowPort(window))->portRect;
-
- // make the window bounds the size of the gdRect less the fudge factor.
-
- h = windRect.right - windRect.left;
- v = windRect.bottom - windRect.top;
-
- if (h > screenRect.right - screenRect.left)
- h = ((screenRect.right - screenRect.left) - (kFudgeFactor * 2));
-
- if (v > screenRect.bottom - screenRect.top)
- {
- v = ((screenRect.bottom - screenRect.top) - (kFudgeFactor * 2));
-
- // If we are on the main device then subtract the mBar
- // height plus a fudge factor for a boundary.
-
- if (gd == GetMainDevice())
- v -= (GetMBarHeight() + kTitleBarHeight);
- }
-
- SizeWindow(window, h, v, true);
- }
-
-
-
-
- /*****************************************************************************/
-
-
-
- // Find thw device that holds the greatest area of the window.
-
- static GDHandle GetGreatestDevice(WindowRef window)
- {
- GDHandle gd;
- GDHandle savedGD;
- Rect gdRect;
- Rect foundRect;
- long size;
- long greatest = nil;
-
-
- gd = DMGetFirstScreenDevice(dmOnlyActiveDisplays);
- savedGD = gd;
-
- // Loop through the device list
-
- while (gd != nil)
- {
- gdRect = (**gd).gdRect;
-
- GlobalToLocal(&TopLeft(gdRect));
- GlobalToLocal(&BotRight(gdRect));
-
- if (SectRect(&(GetWindowPort(window))->portRect, &gdRect, &foundRect))
- {
- size = ((long)(foundRect.right - foundRect.left) *
- (long)(foundRect.bottom - foundRect.top));
-
- if (size > greatest)
- {
- greatest = size;
- savedGD = gd; // save the greatest device
- }
- }
-
- gd = DMGetNextScreenDevice(gd, dmOnlyActiveDisplays);
- }
-
- return savedGD;
- }
-
-
-
-
- /*****************************************************************************/
-
-
-
- // Return the actual window rect in global coords
-
- static void GetWindowRect(WindowRef window, Rect *windRect)
- {
- *windRect = (GetWindowPort(window))->portRect;
-
- // add the titlebar height for actual height
-
- windRect->top -= kTitleBarHeight;
-
- LocalToGlobal(&TopLeft(*windRect));
- LocalToGlobal(&BotRight(*windRect));
- }
-
-
-
-
- /*****************************************************************************/
-
-
- // Since we are now on a different size screen we need
- // to change the stdState window size so our zooming will work properly.
-
- static void ResetStdState(WindowRef window)
- {
- Rect screenRect;
-
- screenRect = (GetWindowPort(window))->portRect;
-
- LocalToGlobal(&TopLeft(screenRect));
- LocalToGlobal(&BotRight(screenRect));
-
- SetWindowStandardState(window, &screenRect);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma mark ••• Inline Input Support •••
-
- #if qInlineInputAware
-
- pascal OSErr
- HandleTextServicesUpdateActiveInputArea(AppleEvent *theAppleEvent,AppleEvent *reply,long refCon)
- {
- DebugMessage("\pTextServicesUpdateActiveInputArea");
- return errAEEventNotHandled; // we really don’t handle this yet...
- }
-
-
-
- /*****************************************************************************/
-
-
- pascal OSErr
- HandleTextServicesPos2Offset(AppleEvent *theAppleEvent,AppleEvent *reply,long refCon)
- {
- DebugMessage("\pTextServicesPos2Offset");
- return errAEEventNotHandled; // we really don’t handle this yet...
- }
-
-
-
- /*****************************************************************************/
-
-
- pascal OSErr
- HandleTextServicesOffset2Pos(AppleEvent *theAppleEvent,AppleEvent *reply,long refCon)
- {
- DebugMessage("\pTextServicesOffset2Pos");
- return errAEEventNotHandled; // we really don’t handle this yet...
- }
-
- #endif
-