home *** CD-ROM | disk | FTP | other *** search
- /* -----------------------------------------------------------------------------------------
- ESDemo.c
-
- ©1995-2000 Ammon Skidmore, Skidperfect Software Inc. http://www.skidperfect.com/
-
- Public Domain: use, borrow and steal whatever code you want for your own modules!
-
- This is a "quick" hack that I threw together to test and demonstrate
- Extensions Strip's powerful additions to the Control Strip API. Do not
- think that I bothered to optimize anything or that I choose the best methods
- to approach each situation. I'd rather waste my time doing that to ES :-)
-
- Key features of this module:
- - Fat binary.
- - Backward compatibility with Control/Desktop Strip.
- - Intelligent drag handling. Under Control/Desktop Strip the draggable
- area is the location of the module's icon. Under Extensions Strip this
- area is the total amount of space that the module takes up.
- - 2 out of the 3 possible methods for sending "safe" AppleEvents that don't rely
- upon the front process' context. Under Control/Desktop Strip the event is still
- sent, but will not work if the front process does not support Apple Events.
- - Ability to get key presses under Extensions Strip without having to install
- a custom jGNE filter (as my Key Holder module does.)
- - Ability to change the sdevFeatures without having to restart. Examples are
- given for changing almost all of the possible features, even locking and
- unlocking my sdev code.
- - Demonstrates the changing of display height and width.
- - Demonstrates a good compatible method of handling hierarchial menus.
-
- Notes about PPC linking:
- - For PPC compiling, remember to use 'weak links' to shared libraries that may not
- be on every user's computer. Not doing so will cause a crash because Extensions
- Strip will be forced to quit if the library is not present. Modules should use
- Gestalt calls to determine the presence of libraries they use.
- For example, this project has a weak link to the DragLib, yet it does not have
- one to the ControlStripLib or the InterfaceLib because these two libraries
- will always be present.
- - This project, because it is Extensions Strip savvy, must be linked with the
- ControlStripLibStub that comes with ES rather than the default ControlStripLib
- of the Universal headers. This way it can link to the additional ES functions.
-
- Version History
- -=-=-=-=-=-=-=-
- 1.0 8/95 - 10/95 - initial release
- 30 Oct, 1995 - Made THINK compiler friendly by Vincent Tan.
-
- 1.1 09 Nov, 1995 - Added the menu item 'Large Icon' to demonstrate the changing
- of display height and width. Also, the icons were slightly
- modified, the creator type was changed to '!!!!', and a
- 'hfdr' resource was added so programs like Conflict Catcher
- can look at our info text. Maybe future Finders will display
- this balloon help as well...
- 15 Nov, 1995 - Added Code Warrior 7 projects, by François Pottier.
-
- 1.1.1 20 Nov, 1995 - Fixed a bug that caused the icon to be drawn incorrectly
- when not using Extensions Strip.
- - Changed the drag handlers to return dragNotAcceptedErr when
- the draw was not accepted, instead of the value -1 as before.
-
- 1.1.2 27 July, 1998 - Converted project to Code Warrior IDE 3. Note: CW IDE 2 allows
- you to open the project but it clears all the build settings.
- - Fixed a bug that caused the icon to be drawn incorrectly
- when when using the miniature module mode of Extensions Strip 1.8.
- - Now works if the triangle PICT resource is deleted.
-
- 1.1.3 05 Nov, 1998 - Converted project to CW IDE 4.
- - The PPC code is now compiled as a shared library so that it
- will run under Control Strip 2.0 (part of System 8.5 and later)
- and Extensions Strip 1.8 and later. To get this to work, you
- need to rename ExtensionsStripLib to ControlStripLibStub.
- - Added a FAT taget to the project. No source changes were made.
-
- 1.2 30 July, 2000 - Converted project to CW IDE 5 (with latest patches: Update 5.3).
- - Demonstrates a compatible method of handling hierarchial menus.
- - Rearranged the code a bit and added some more comments.
-
- 1.2.1 10 Aug, 2000 - when sdevInit() fails, it now frees memory by calling sdevClose().
- - made all the shared libraries "Import Weak". A common mistake.
- - added some debugging macros and updated some comments.
- 25 April, 2001 - updated project file for CodeWarrior 6 (no source changes needed)
- - removed an old, unnecessary ES 2 beta flag (sdevMiniModulesFriendly)
-
- -=-=-=-=-=-=-=-
- Framework taken from the CSShell.c Control Strip Sample by Martin R. Wachter.
- It is freely availible and can be found on the usual UMich/Info-Mac mirrors.
- ----------------------------------------------------------------------------------------- */
-
- #ifdef powerc
- // for Metrowerks' linker, this defines the mixed-mode interface for main().
- ProcInfoType __procinfo = kPascalStackBased
- | RESULT_SIZE(SIZE_CODE(sizeof(long)))
- | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(long)))
- | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(long)))
- | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(Rect*)))
- | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(WindowRef)));
- #endif
-
- //#define DEBUG_ON /* comment this out when making a release! */
-
- #ifndef SystemSevenOrLater
- #define SystemSevenOrLater 1
- #endif
-
- #define CALL_NOT_IN_CARBON 1 // OS X doesn't have ControlStrip
-
- #include <Gestalt.h>
- #include <Icons.h>
- #include <Drag.h>
- #include <ControlStrip.h>
- #include "ExtensionsStrip.h"
- #include "Custom Def Utils.h"
-
- #include "ESDemo.h"
-
- /******************************************************************************
- main: Control Strip's entry point into our sdev code
- ******************************************************************************/
- pascal long main (long message, long params, Rect *statusRect, WindowRef statusPort)
- {
- register long result = 0L;
- MyGlobalHandle globH = (MyGlobalHandle)params;
-
- switch (message)
- {
- //
- // Default Control Strip selectors:
- //
-
- case sdevInitModule: // check environs, allocate globals
- result = sdevInit(statusPort);
- break;
-
- case sdevCloseModule: // release my memory
- sdevClose(globH, statusPort);
- break;
-
- case sdevFeatures: // let the strip track the mouse down
- result = (**globH).currentFeatures;
- break;
-
- case sdevGetDisplayWidth: // inform the strip how much space we need
- {
- PicHandle myArrowPict = (**globH).myArrowPict;
-
- if ((**globH).useLargeIcon)
- result = kLargeIconWidth + ((unsigned long)kLargeIconWidth << 16);
- else
- result = kSmallIconWidth;
-
- if (myArrowPict) /* if the arrow PICT was loaded, add it's width */
- result += width((*myArrowPict)->picFrame);
- break;
- }
-
- case sdevPeriodicTickle: // never called by Extensions Strip because we
- { // returned the sdevDontPeriodicTickle bit.
- Rect viewRect = *statusRect;
-
- // update the draggable box upon each idle cycle in case the user
- // shrunk the Control Strip bar so that we are not visible, but our
- // old position still is because the end of the bar is there.
- viewRect.right = viewRect.left + ( (**globH).useLargeIcon ?
- kLargeIconWidth : kSmallIconWidth );
- (**globH).myBox = viewRect;
-
- break;
- }
-
- case sdevDrawStatus: // draw my icon and arrow pict
- sdevDraw(globH, statusRect, statusPort);
- break;
-
- case sdevMouseClick: // the mouse was clicked & released in my button
- result = sdevClick(globH, statusRect, statusPort);
- break;
-
- case sdevSaveSettings: // no settings in this module
- break;
-
- case sdevShowBalloonHelp: // we have a custom ballon help string
- {
- Str255 helpString;
-
- SBGetDetachedIndString(helpString, (**globH).myStrings, kHelpStringIndex);
- SBShowHelpString(statusRect, helpString);
-
- break;
- }
-
- //
- // Extensions Strip specific selectors:
- // Note that we check for the presence of ES just in case...
- //
-
- case sdevInAppContext: // we are inside Extensions Strip's context so
- // is is safe to send Apple Events from here.
- {
- ProcessSerialNumber finderPSN;
- ProcessInfoRec infoRec;
- #define kFinderType 'FNDR'
- #define kSysCreator 'MACS'
-
- if ((**globH).hasExtensionsStrip) {
- infoRec.processInfoLength = sizeof(ProcessInfoRec);
- infoRec.processName = nil; // no name wanted processName;
- infoRec.processAppSpec = nil; // no spec wanted &procSpec;
-
- if (FindAProcess(kFinderType, kSysCreator, &finderPSN, &infoRec) == noErr)
- QuitProcess(finderPSN, FALSE); // FALSE because we don't HAVE to use
- // _SBSimpleAESend here
- }
- break;
- }
-
- case sdevInterceptedEvent: // a chance to look at and modify the current event
- {
- EventRecord *theEvent;
-
- if ((**globH).hasExtensionsStrip) {
- // for demonstration's purpose, we'll intercept command + *
- // (* on the keypad only since cmd-shift-8 is an FKEY combo that
- // is intercepted by the System.)
- theEvent = SBGetCurrentEvent();
- // we can assume a keydown since our mask filters out the rest.
- // if (theEvent->what == keyDown)
- if (theEvent->modifiers & cmdKey) {
- switch (theEvent->message & charCodeMask)
- {
- case '*':
- SysBeep(0);
- theEvent->what = nullEvent; // don't pass on the event
- break;
- }
- }
- }
- break;
- }
-
- case sdevDragAccept: // let Extensions Strip know if we won't handle the drag
- if ((**globH).hasExtensionsStrip &&
- !(**globH).canAcceptDrag)
- result = 1; // we don't accept the drag
- break;
-
- case sdevEventMask: // let Extensions Strip know we want key down events
- if ((**globH).hasExtensionsStrip)
- result = keyDownMask; // our GNE style event mask
- break;
- }
-
- return (result);
- }
-
-
- static pascal void MyDrawPicture(PicHandle thePicture, Rect *destRect)
- {
- CallDrawPictureProc(gSaveDrawPicture, gDownArrow, destRect);
- }
-
-
- Boolean inMenuBarMode = false, fakeOutButton = false;
- static pascal Boolean MyButton(void)
- {
- Boolean result;
-
- result = CallButtonProc(gSaveButton);
- if (fakeOutButton) {
- return (!result);
- }
-
- return (result);
- }
-
-
- // MDEF Code Resource entry point
- static pascal void menuMDEF(short msg, MenuHandle whichMenu, Rect *menuRect, Point hitPt, short *itemID )
- {
- // char cMemTags;
- Handle oldMDEF, curMDEF;
- Rect popupRect;
- Point localPt;
- Boolean bail = false,
- outsideOfTriangle = false;
-
- CallMenuDefProc((MenuDefUPP)*(gOldMDEF), msg, whichMenu, menuRect, hitPt, itemID);
-
- switch (msg)
- {
- case kMenuChooseMsg:
- GetMouse(&localPt);
- // if in the menu area, do nothing special
- if (PtInRect(hitPt, menuRect))
- break;
- if (PtInRect(localPt, menuRect))
- break;
- // if menu item is blinking (was selected), do nothing special
- if (*(long*)&hitPt == 0L)
- break;
- // if released mouse before dragging to other modules, go into mouseup menubar mode
- // if (!Button() && !esGlob->inMenuBarMode)
- // esGlob->isMouseUpMenu = true;
-
- // if mouse is inside the module's bounds, just record the last mouse pos
- if ((hitPt.h > menuRect->left-4) && (hitPt.h < menuRect->left+35)) {
- } else {
- inMenuBarMode = true;
- if (!Button()) {
- // PostEvent(mouseDown, 0);
- } else {
- // PostEvent(mouseUp, 0);
- PostEvent(mouseDown, 0);
- fakeOutButton = true;
- }
- *itemID = 0;
- }
- break;
- }
- }
-
-
- static long CSMenuHackPopUpMenuSelect(MenuHandle theMenu, short top, short left, short popUpItem)
- {
- long result;
- Handle mdefStubH=0L;
-
- gOldMDEF = (**theMenu).menuProc;
- mdefStubH = GetUniversalFunctionHandle((ProcPtr)menuMDEF, uppMenuDefProcInfo);
- (**theMenu).menuProc = mdefStubH;
-
- result = CallPopupMenuSelectProc(gOldPopupMenuSelect, theMenu, top, left, popUpItem);
-
- fakeOutButton = false;
-
- (**theMenu).menuProc = gOldMDEF;
- if (mdefStubH) DisposeHandle(mdefStubH);
- return result;
- }
-
-
-
- /******************************************************************************
- sdevInit: allocate memory for our globals and init our globals
- ******************************************************************************/
- long sdevInit(WindowRef statusPort)
- {
- MyGlobalHandle globH;
-
- //
- // get some memory
- //
- globH = (MyGlobalHandle) NewHandleClear(sizeof(MyGlobals));
- if (!globH)
- goto exit;
-
- //
- // temporarily lock our global handle because we pass pointers of it to toolbox
- // functions. If I wanted to be really cool I'd load all the handles into local
- // variables to remove this need, as well as the repetitive double deferencing...
- //
- HLock((Handle)globH);
-
- //
- // get our icon suite
- //
- if (SBGetDetachIconSuite(&(**globH).iconSuite, rIconSuiteId, svAllSmallData) != noErr) goto exit;
- //
- // get our string list
- //
- (**globH).myStrings = GetResource('STR#', rMyStringsID);
- if (!(**globH).myStrings) goto exit;
- DetachResource((**globH).myStrings);
- //
- // get our menus
- //
- (**globH).myMenuH = GetMenu(rPopupMenuID);
- (**globH).myHierMenuH = GetMenu(rHierMenuID);
- if ( (!(**globH).myMenuH) || (!(**globH).myHierMenuH) )
- goto exit;
- DetachResource((Handle)(**globH).myMenuH);
- DetachResource((Handle)(**globH).myHierMenuH);
- //
- // get our arrow picture
- //
- (**globH).myArrowPict = GetPicture(rArrowPictID);
- if ((**globH).myArrowPict)
- DetachResource((Handle)(**globH).myArrowPict);
- //
- // setup our initial features
- //
- (**globH).currentFeatures = (
- (1L<<sdevWantMouseClicks) // we handle mouse down
- | (1L<<sdevDontAutoTrack) // we track the mouse, too
- | (1L<<sdevHasCustomHelp) // custom help string
- | (1L<<sdevKeepModuleLocked) // I need to be locked
- // for drag-n-drop.
- );
- //
- // determine if Extensions Strip is running.
- // If so, get my reference number and setup ES specific feature flags
- //
- (**globH).hasExtensionsStrip = HasExtensionsStrip();
- if ((**globH).hasExtensionsStrip)
- {
- (**globH).myReferenceNum = SBGetMyReferenceNum();
- (**globH).currentFeatures +=
- (
- (1L<<sdevHasDragHandlers) // flag that we have drag handlers
- | (1L<<sdevDontPeriodicTickle) // we don't need any idle time
- | (1L<<sdevInterceptAllEvents) // get all events under Extensions Strip
- );
- }
- //
- // setup the drag stuff
- //
- InstallDragHandlers(statusPort, globH);
- (**globH).acceptFiles = true;
- SetItemMark((**globH).myMenuH, kDragFiles, sdevMenuItemMark);
-
-
- // hack stuff:
- if (! gPopupPatch) gPopupPatch = NewPopupMenuSelectProc(CSMenuHackPopUpMenuSelect);
- if (! gPopupPatch) goto exit;
-
- gOldPopupMenuSelect = (PopupMenuSelectUPP) NGetTrapAddress(_PopUpMenuSelect, toolOrOSTrap(_PopUpMenuSelect));
- NSetTrapAddress(gPopupPatch, _PopUpMenuSelect, toolOrOSTrap(_PopUpMenuSelect));
-
- if (! gButtonPatch) gButtonPatch = NewButtonProc(MyButton);
- if (! gButtonPatch) goto exit;
- gSaveButton = (ButtonUPP) NGetTrapAddress(_Button, toolOrOSTrap(_Button));
- NSetTrapAddress( (UniversalProcPtr) gButtonPatch,
- _Button, toolOrOSTrap(_Button));
-
- gDownArrow = (PicHandle)Get1Resource('PICT', 128);
- if (! gDownArrow) goto exit;
- DetachResource((Handle)gDownArrow);
- if (! gDrawPicturePatch) gDrawPicturePatch = NewDrawPictureProc(MyDrawPicture);
- if (! gDrawPicturePatch) return (-1L);
- gSaveDrawPicture = (DrawPictureUPP) NGetTrapAddress(_DrawPicture, toolOrOSTrap(_DrawPicture));
- NSetTrapAddress( (UniversalProcPtr) gDrawPicturePatch,
- _DrawPicture, toolOrOSTrap(_DrawPicture));
-
- {// clear strip
- RgnHandle curClip = NewRgn();
- SetPort(statusPort);
- SetClip(statusPort->visRgn);
- EraseRgn(statusPort->visRgn);
- InvalRgn(statusPort->visRgn);
- SetClip(curClip);
- DisposeRgn(curClip);
- }
-
- //
- // set my handle free and return its value
- //
- HUnlock((Handle)globH);
- return ((long) globH);
-
- //
- // did not get any memory, don't install
- //
- exit:
- sdevClose(globH, statusPort); // (ammon 000804)
- return (-1L);
- }
-
- /******************************************************************************
- sdevClose: free memory for our globals
- ******************************************************************************/
- void sdevClose(MyGlobalHandle globH, WindowRef statusPort)
- {
- // useful macros:
- #define myDisposeHandle(h)\
- if ((h) != nil)\
- DisposeHandle((Handle) (h))
- #define myDisposeIconSuite(h, p1)\
- if ((h) != nil)\
- DisposeIconSuite(h, p1)
-
- // dispose of everything:
- if (globH){
- myDisposeIconSuite((**globH).iconSuite, true);
- myDisposeHandle((**globH).myMenuH);
- myDisposeHandle((**globH).myHierMenuH);
- myDisposeHandle((**globH).myStrings);
- myDisposeHandle((**globH).myArrowPict);
-
- RemoveDragHandlers(statusPort, globH);
-
- DisposeHandle((Handle) globH);
- }
-
- if (gOldPopupMenuSelect)
- NSetTrapAddress(gOldPopupMenuSelect, _PopUpMenuSelect, toolOrOSTrap(_PopUpMenuSelect));
- if (gSaveButton)
- NSetTrapAddress(gSaveButton, _Button, toolOrOSTrap(_Button));
- if (gSaveDrawPicture)
- NSetTrapAddress((UniversalProcPtr) gSaveDrawPicture, _DrawPicture, toolOrOSTrap(_DrawPicture));
- {// clear strip
- RgnHandle curClip = NewRgn();
- SetPort(statusPort);
- SetClip(statusPort->visRgn);
- EraseRgn(statusPort->visRgn);
- InvalRgn(statusPort->visRgn);
- SetClip(curClip);
- DisposeRgn(curClip);
- }
- }
-
- /******************************************************************************
- sdevClick: handle a click in our status rect
- ******************************************************************************/
- long sdevClick(MyGlobalHandle globH, const Rect *statusRect, WindowRef statusPort)
- {
- short menuItem;
- MenuHandle menuH = (**globH).myMenuH, // local copy to save deferencing
- hierMenuH = (**globH).myHierMenuH; // (ammon 000730)
- long result = 0L;
- char itemMark;
- short theBit, index;
- long menuResult; // (ammon 000730)
-
- // reflect the current features in th popup menu
- itemMark = ((**globH).currentFeatures & (1L<<sdevWantMouseClicks)) ? sdevMenuItemMark : noMark;
- SetItemMark(menuH, kHiliteClicks, itemMark);
- itemMark = ((**globH).currentFeatures & (1L<<sdevHasCustomHelp)) ? sdevMenuItemMark : noMark;
- SetItemMark(menuH, kCustomBalloons, itemMark);
- itemMark = ((**globH).currentFeatures & (1L<<sdevInterceptAllEvents)) ? sdevMenuItemMark : noMark;
- SetItemMark(menuH, kCheckKeyDowns, itemMark);
- itemMark = ((**globH).useLargeIcon) ? sdevMenuItemMark : noMark;
- SetItemMark(menuH, kUseLargeIcon, itemMark);
- itemMark = ((**globH).currentFeatures & (1L<<sdevHasDragHandlers)) ? sdevMenuItemMark : noMark;
- SetItemMark(menuH, kUseDragNDrop, itemMark);
-
- // disable what Control/Desktop Strip doesn't support
- if (!(**globH).hasExtensionsStrip) {
- DisableItem(menuH, kSafeFinderQuit2);
- SetItemMark(menuH, kCheckKeyDowns, noMark);
- }
-
- // (ammon 000730) setup the hierarchial menu
- InsertMenu(hierMenuH, -1);
-
- // show our popup menu
- menuItem = SBTrackPopupMenu(statusRect, menuH);
-
- // (ammon 000730) take down the hierarchial menu and find out what menu was selected
- DeleteMenu(rHierMenuID);
- menuResult = MenuChoice();
- // Note, MenuChoice() would not be needed if we used ES 2's API call SBTrackHierMenu(),
- // though then we wouldn't be compatible with Control Strip and the like.
-
- switch ((menuResult & 0xFFFF0000) >> 16) // (ammon 000730) switch on the menu id
- {
- case rHierMenuID: // (ammon 000730)
- for (index=0; index<menuItem; index++)
- {
- SysBeep(0);
- }
- break;
- default: // NOTE: do not rely on the menu id of the menu passed to
- // SBTrackPopupMenu(). It may have changed behind your back
- // if there was a conflict with another menu resource.
- // (This is more likely to occur under pre-8.5 systems where
- // modules are run in the front app's context.)
- switch (menuItem)
- {
-
- case kBeepIfPPC:
- #ifdef powerc
- SysBeep(0);
- #endif
- break;
-
- case kHiliteClicks:
- theBit = sdevWantMouseClicks;
- // pass on
-
- case kCustomBalloons:
- if (menuItem == kCustomBalloons)
- theBit = sdevHasCustomHelp;
- // pass on
-
- case kCheckKeyDowns:
- if (menuItem == kCheckKeyDowns)
- theBit = sdevInterceptAllEvents;
- // pass on
-
- case kUseDragNDrop:
- if ((**globH).hasExtensionsStrip) {
- if (menuItem == kUseDragNDrop) {
- theBit = sdevHasDragHandlers;
- // Install/remove handlers for fun. We can also now
- // unlock our code, all for demonstration purposes.
- if ((**globH).currentFeatures & (1L<<sdevHasDragHandlers)) {
- (**globH).currentFeatures -= (1L<<sdevKeepModuleLocked);
- RemoveDragHandlers(statusPort, globH);
- DisableItem(menuH, kDragFiles);
- DisableItem(menuH, kDragTextClippings);
- } else {
- (**globH).currentFeatures += (1L<<sdevKeepModuleLocked);
- InstallDragHandlers(statusPort, globH);
- EnableItem(menuH, kDragFiles);
- EnableItem(menuH, kDragTextClippings);
- }
- }
-
- // handle the passed bit
- if ((**globH).currentFeatures & (1L<<theBit))
- (**globH).currentFeatures -= (1L<<theBit);
- else
- (**globH).currentFeatures += (1L<<theBit);
- result += (1L<<sdevFeaturesChange); // request a sdevFeatures call
- }
- break;
-
- case kUseLargeIcon:
- (**globH).useLargeIcon = !(**globH).useLargeIcon;
- // request to be asked our dimensions again
- result = (1L<<sdevResizeDisplay);
- break;
- case kDragFiles:
- (**globH).acceptFiles = !(**globH).acceptFiles;
- itemMark = (**globH).acceptFiles ? sdevMenuItemMark : noMark;
- SetItemMark(menuH, kDragFiles, itemMark);
- break;
-
- case kDragTextClippings:
- (**globH).acceptText = !(**globH).acceptText;
- itemMark = (**globH).acceptText ? sdevMenuItemMark : noMark;
- SetItemMark(menuH, kDragTextClippings, itemMark);
- break;
-
- case kSafeFinderQuit1: {
- ProcessSerialNumber finderPSN;
- ProcessInfoRec infoRec;
-
- infoRec.processInfoLength = sizeof(ProcessInfoRec);
- infoRec.processName = nil; // no name wanted processName;
- infoRec.processAppSpec = nil; // no spec wanted &procSpec;
-
- if (FindAProcess(kFinderType, kSysCreator, &finderPSN, &infoRec) == noErr)
- QuitProcess(finderPSN, (**globH).hasExtensionsStrip);
- break;
- }
-
- case kSafeFinderQuit2:
- // request sdevInAppContext to be called once within Extensions Strip's context
- result = (1L<<sdevQueueModule);
- break;
-
- case kCloseDown:
- result = (1L<<sdevCloseNow);
- break;
- } // end switch menuItem
- } // end switch menu id
-
- return(result);
- }
-
- /******************************************************************************
- sdevDraw: draw our icon and arrow pict
- ******************************************************************************/
- void sdevDraw(MyGlobalHandle globH, Rect *statusRect, WindowRef statusPort)
- {
- Rect viewRect = *statusRect;
- short arrowHeight = 0;
- PicHandle myArrowPict = (**globH).myArrowPict; // local copy to save deferencing
-
- //
- // update the drag area (only required for Control/Desktop Strip)
- //
- viewRect.right = viewRect.left + ( (**globH).useLargeIcon ?
- kLargeIconWidth : kSmallIconWidth );
- (**globH).myBox = viewRect;
-
- //
- // Draw our icon
- //
- DrawMyIcon(globH, false);
-
- //
- // Draw our right-arrow pict to show that we have a popup menu
- //
- if (myArrowPict)
- {
- short arrowHeight;
-
- arrowHeight = height((*myArrowPict)->picFrame);
- viewRect.left = viewRect.right;
- viewRect.right += width((*myArrowPict)->picFrame);
- viewRect.top += ((height(viewRect) - arrowHeight) >> 1);
- viewRect.bottom = viewRect.top + arrowHeight;
- DrawPicture(myArrowPict, &viewRect);
- }
- }
-
- void DrawMyIcon(MyGlobalHandle globH, Boolean selected)
- {
- Rect viewRect;
-
- if ((**globH).iconSuite)
- {
- // Get our icon's area
- if ((**globH).hasExtensionsStrip) {
- SBGetModuleBounds(&viewRect, (**globH).myReferenceNum);
- viewRect.right = viewRect.left + ( (**globH).useLargeIcon ?
- kLargeIconWidth : kSmallIconWidth );
- } else
- viewRect = (**globH).myBox;
-
- // Draw our icon
- PlotIconSuite(&viewRect, atNone, selected ? ttSelected : ttNone,
- (**globH).iconSuite);
- }
- }
-
- /* The gestalt code: */
- #pragma mark -
-
- /******************************************************************************
- HasDragMgr: determine if the Drag Manager exists, and supports floaters
- ******************************************************************************/
- Boolean HasDragMgr(void)
- {
- long gestaltResponse;
-
- return( (Gestalt(gestaltDragMgrAttr, &gestaltResponse) == noErr) &&
- (gestaltResponse & (1L << gestaltDragMgrPresent)) &&
- (gestaltResponse & (1L << gestaltDragMgrFloatingWind)) );
- }
-
- /******************************************************************************
- HasExtensionsStrip: determine if Extensions Strip is installed and running
- ******************************************************************************/
- Boolean HasExtensionsStrip(void)
- {
- long gestaltResponse;
-
- return( (Gestalt(gestaltExtensionsStripAttr, &gestaltResponse) == noErr) &&
- (gestaltResponse & (1L << gestaltExtensionsStripExists)) );
- }
-
- /* The apple event code: */
- #pragma mark -
-
- /******************************************************************************
- FindAProcess: run through the process list looking for the indicated program
- ******************************************************************************/
- OSErr FindAProcess(OSType typeToFind, OSType creatorToFind,
- ProcessSerialNumberPtr processSN,
- ProcessInfoRecPtr infoRecToFill)
- {
- OSErr myErr = noErr;
-
- processSN->lowLongOfPSN = kNoProcess;
- processSN->highLongOfPSN = 0;
- do
- {
- myErr = GetNextProcess(processSN);
- if (myErr == noErr)
- GetProcessInformation(processSN, infoRecToFill);
- }
- while ( (myErr == noErr) && ((infoRecToFill->processSignature != creatorToFind) ||
- (infoRecToFill->processType != typeToFind)) );
- return(myErr);
- }
-
- /******************************************************************************
- QuitProcess: Send a quit event to the specified process. If you are using the
- program Extensions Strip the event will be sent safely from within
- its Apple Event aware context.
- ******************************************************************************/
- void QuitProcess (ProcessSerialNumber PSN, Boolean hasExtensionsStrip)
- {
- AEAddressDesc applicationAddress;
- AppleEvent theEvent, returnEvent;
- OSErr err;
-
- AECreateDesc(typeProcessSerialNumber, &PSN, sizeof(ProcessSerialNumber), &applicationAddress);
- AECreateAppleEvent(kCoreEventClass, kAEQuitApplication, &applicationAddress,
- kAutoGenerateReturnID, kAnyTransactionID, &theEvent);
- AEDisposeDesc(&applicationAddress);
- if (hasExtensionsStrip) {
- err = SBSimpleAESend(&theEvent);
- } else {
- err = AESend(&theEvent, &returnEvent,
- kAENoReply + kAEAlwaysInteract + kAECanSwitchLayer,
- kAENormalPriority,
- kAEDefaultTimeout, nil, nil);
- }
- if (err) {
- // better error handling goes here
- SysBeep(0);
- }
- AEDisposeDesc(&theEvent);
- }
-
- /* The drag manager code: */
- #pragma mark -
-
- /******************************************************************************
- InstallDragHandlers: install & create everything having to do with drag handlers
- ******************************************************************************/
- void InstallDragHandlers(WindowRef statusPort, MyGlobalHandle globH)
- {
- // local copies
- DragTrackingHandlerUPP myTrackingUPP;
- DragReceiveHandlerUPP myReceiveUPP;
-
- if (HasDragMgr()) {
- myTrackingUPP = NewDragTrackingHandlerProc(DragTrackingHandler);
- myReceiveUPP = NewDragReceiveHandlerProc(DragReceiveDropHandler);
-
- if (myTrackingUPP && myReceiveUPP) { // got UPPs successfully
- InstallTrackingHandler(myTrackingUPP, statusPort, (void*) globH);
- InstallReceiveHandler(myReceiveUPP, statusPort, (void*) globH);
- }
-
- (**globH).myTrackingUPP = myTrackingUPP;
- (**globH).myReceiveUPP = myReceiveUPP;
- } else {
- // disable the drag-related menu items
- DisableItem((**globH).myMenuH, kUseDragNDrop);
- DisableItem((**globH).myMenuH, kDragFiles);
- DisableItem((**globH).myMenuH, kDragTextClippings);
- }
- }
-
- /******************************************************************************
- RemoveDragHandlers: remove & dispose everything having to do with drag handlers
- ******************************************************************************/
- void RemoveDragHandlers(WindowRef statusPort, MyGlobalHandle globH)
- {
- // local copies
- DragTrackingHandlerUPP myTrackingUPP = (**globH).myTrackingUPP;
- DragReceiveHandlerUPP myReceiveUPP = (**globH).myReceiveUPP;
-
- if (myTrackingUPP) {
- RemoveTrackingHandler(myTrackingUPP, statusPort);
- DisposeRoutineDescriptor(myTrackingUPP);
- (**globH).myTrackingUPP = 0L;
- }
-
- if (myReceiveUPP) {
- RemoveReceiveHandler(myReceiveUPP, statusPort);
- DisposeRoutineDescriptor(myReceiveUPP);
- (**globH).myReceiveUPP = 0L;
- }
- }
-
- /******************************************************************************
- IsMouseInMyBounds: returns true if the mouse is over my total clickable area
- ******************************************************************************/
- Boolean IsMouseInMyBounds(MyGlobalHandle globH, WindowRef win, DragReference theDrag)
- {
- Boolean result = false;
- Point theMouse;
- Rect hotBounds;
-
- if (GetDragMouse(theDrag, &theMouse, 0L) == noErr) {
- GlobalToLocal(&theMouse);
- if ((**globH).hasExtensionsStrip)
- SBGetTotalModuleBounds(&hotBounds, win, (**globH).myReferenceNum);
- else
- hotBounds = (**globH).myBox;
-
- result = PtInRect(theMouse, &hotBounds);
- }
-
- return(result);
- }
-
- /******************************************************************************
- DragTrackingHandler: called by the Drag Manager during drags on the strip
- ******************************************************************************/
- pascal OSErr DragTrackingHandler(short message, WindowRef win, void *handlerRefCon,
- DragReference theDrag)
- {
- MyGlobalHandle globH = (MyGlobalHandle) handlerRefCon;
- ItemReference theItem;
- FlavorType theType;
- unsigned short count, index, numFlavors, i;
-
- switch (message)
- {
- case kDragTrackingEnterHandler:
- // do special global initialization here
- break;
-
- case kDragTrackingEnterWindow:
- // determine if we can support at least one of the drag items
- (**globH).canAcceptDrag = false; // default to rejection
- if (CountDragItems(theDrag, &count) == noErr)
- {
- for (index = 1; index <= count; index++) // check all the items
- {
- if ((GetDragItemReferenceNumber(theDrag, index, &theItem) == noErr) &&
- (CountDragItemFlavors(theDrag, theItem, &numFlavors) == noErr)) {
-
- for (i = 1; i <= numFlavors; i++) // check all the flavors
- {
- if ((GetFlavorType(theDrag, theItem, i, &theType) == noErr) &&
- (((**globH).acceptFiles ? (theType == flavorTypeHFS) : 0) ||
- ((**globH).acceptText ? (theType == 'TEXT') : 0)))
- {
- (**globH).canAcceptDrag = true; // I like this flavor
- }
- }
- }
- }
- }
- break;
-
- case kDragTrackingInWindow:
- // check if the mouse is over me
- if ((**globH).canAcceptDrag)
- if ((**globH).hasEntered != IsMouseInMyBounds(globH, win, theDrag))
- {
- (**globH).hasEntered = !(**globH).hasEntered;
- DrawMyIcon(globH, (**globH).hasEntered);
- }
- break;
-
- case kDragTrackingLeaveWindow:
- // if dragTrackingInWindow didn't handle the mouse leaving our area, do it here.
- if ((**globH).hasEntered)
- {
- (**globH).hasEntered = false;
- DrawMyIcon(globH, false);
- }
- break;
-
- case kDragTrackingLeaveHandler:
- break;
- }
-
- return((**globH).canAcceptDrag ? noErr : dragNotAcceptedErr);
- }
-
- /******************************************************************************
- DragReceiveDropHandler: called by the Drag Manager after a drag was dropped on the strip
- ******************************************************************************/
- pascal OSErr DragReceiveDropHandler(WindowRef win, void *handlerRefCon,
- DragReference theDrag)
- {
- MyGlobalHandle globH = (MyGlobalHandle) handlerRefCon;
- OSErr result = dragNotAcceptedErr; // default to cancel (do zoom-back animation)
-
- if ((**globH).hasEntered)
- {
-
- //
- // process the drag here:
- //
- SysBeep(0);
-
- result = noErr; // accept the drag (so there won't be any zoom-back animation)
- }
-
- return(result);
- }
-