home *** CD-ROM | disk | FTP | other *** search
- /*
- 11/17/95
-
- Source code taken very "liberally" from Jorg Brown's sample
- INIT code from Ultimate Mac Programming. Without it, writing
- the SmartDragWindow extension would have been much more work.
- */
-
-
- #include <OSUtils.h>
- #include "SmartDragWindow INIT.h"
- #include "SmartDragWindow.h"
-
- enum {
- uppDragWindowProcInfo = kPascalStackBased
- | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(WindowPtr)))
- | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(Point)))
- | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(Rect*)))
- };
-
- // ---------------------------------------------------------------------------
-
- // Globals
-
- SmartDragGlobals gSmartDragData = {
- true, // smartDrag on/off
- 10, // snap-to-distance
- true, // snap to monitor
- true, // snap to window
- false, // snap to grid
- 10, // snap grid size
- false, // snap when growing window
-
- 0 // reserved
- };
-
- // Address of old DragWindow() trap
- pascal void (*gOldDragWindow)(WindowPtr theWindow, Point startPt, Rect *limitRect);
- // Address of gestalt selector function
- SelectorFunctionUPP gSmartDragGestaltUPP;
-
- // ---------------------------------------------------------------------------
-
- pascal void SmarterDragWindow(WindowPtr w, Point pt, Rect *bounds);
- static pascal OSErr SmartDragGestalt(OSType selector, long *_response);
-
- // ---------------------------------------------------------------------------
-
- void main(void) {
- long oldA4;
- THz oldZone;
- SmartDragGlobals **dragGlobals;
- UniversalProcPtr newDragWindow;
-
- // Setup A4 to access globals
- oldA4 = SetCurrentA4();
-
- // Set current zone to system heap zone.
- oldZone = GetZone();
- SetZone(SystemZone());
-
- // Since we rely on Gestalt we have to make sure it's available
- if (GetOSTrapAddress(kGestaltTrapNumber) == UnimplementedTrapAddress) {
- goto exitSection;
- }
-
- // Get gestalt selector function
- gSmartDragGestaltUPP = NewSelectorFunctionProc(SmartDragGestalt);
- if (gSmartDragGestaltUPP == NULL) {
- goto exitSection;
- }
-
- // Install selector to allow us to communicate with the control
- // panel & to make sure we don't load twice.
- if (NewGestalt(kSmartDragSignature, gSmartDragGestaltUPP) != noErr) {
- goto exitSection;
- }
-
- newDragWindow = NewRoutineDescriptor((ProcPtr)
- &SmarterDragWindow, uppDragWindowProcInfo, GetCurrentISA());
- if (newDragWindow == NULL) {
- goto exitSection;
- }
-
- DetachResource(GetResource('INIT', kSmartDragRsrcID));
-
- // Remember old implementation of DragWindow
- gOldDragWindow = (void*)GetToolTrapAddress(kDragWindowTrapNumber);
-
- // Patch ourselves in
- SetToolTrapAddress(newDragWindow, kDragWindowTrapNumber);
-
- // Load in preferences
- dragGlobals = (SmartDragGlobals**)Get1Resource(kSmartDragPrefRsrcType,
- kSmartDragRsrcID);
- if (dragGlobals != NULL && GetHandleSize((Handle)dragGlobals) ==
- sizeof(SmartDragGlobals)) {
- gSmartDragData = **dragGlobals;
- }
-
- exitSection:
- SetZone(oldZone);
- SetA4(oldA4);
- } // END main entrypoint
-
- // ---------------------------------------------------------------------------
-
- static void SnapProc(WindowPtr windowToDrag, short snapToDistance, Rect *snapRect);
-
- pascal void SmarterDragWindow(WindowPtr w, Point pt, Rect *bounds) {
- long oldA4;
-
- oldA4 = SetCurrentA4();
-
- // Hot key: control key to turn off smart dragging
- if (IsControlKeyDown() || !gSmartDragData.smartDragOn) {
- // Call original DragWindow() trap
- #ifdef powerc
- CallUniversalProc((UniversalProcPtr)gOldDragWindow,
- uppDragWindowProcInfo, w, pt, bounds);
- #else
- gOldDragWindow(w, pt, bounds);
- #endif
- }
- else {
- // Call our own routine
- SuperSmartDragWindow(w, pt, bounds,
- gSmartDragData.snapToDistance, SnapProc);
- }
-
- SetA4(oldA4);
- } // END SmarterDragWindow
-
- void SnapProc(WindowPtr windowToDrag, short snapToDistance, Rect *snapRect) {
- if (gSmartDragData.snapToGrid)
- GridSnapProc(windowToDrag, gSmartDragData.snapGridSize, snapRect);
- if (gSmartDragData.snapToWindows)
- WindowSnapProc(windowToDrag, snapToDistance, snapRect);
- if (gSmartDragData.snapToMonitor)
- MonitorSnapProc(windowToDrag, snapToDistance, snapRect);
- } // END SnapProc
-
- // ---------------------------------------------------------------------------
-
- pascal OSErr SmartDragGestalt(OSType selector, long *_response) {
- long oldA4;
- OSErr err = noErr;
-
- // Setup A4 to access globals
- oldA4 = SetCurrentA4();
-
- switch(selector) {
- case kGestaltGetSmartDragGlobals:
- // Caller (control panel) wants access to our globals
- *_response = (long)&gSmartDragData;
- break;
-
- case kSmartDragSignature:
- // Caller wants address of gestalt selector
- *_response = (long)gSmartDragGestaltUPP;
- break;
-
- case gestaltVersion:
- // Caller (control panel) wants the INIT version
- // to make sure it matches that of the control panel
- *_response = kSmartDragVersion;
- break;
-
- default:
- // We don't handle any other gestalt selectors
- err = gestaltUnknownErr;
- break;
- }
-
- SetA4(oldA4);
- return(err);
- } // END SmartDragGestalt