home *** CD-ROM | disk | FTP | other *** search
- /* MacFloater.cpp
- *
- * This is the implementation of the floating window stuff. This
- * requires the routine 'DoActivate' to be a valid subroutine which can
- * be called to activate the window's contents, and this also requires
- * that the 'activeEvt' of the event loop gets ignored...
- */
-
- #include "MacFloater.h" /* Float library support */
- #include <LowMem.h> /* LMGetMBarHeight() */
-
- /************************************************************************/
- /* */
- /* Search Routines */
- /* */
- /************************************************************************/
-
- /* MFrontWindow
- *
- * Find the frontmost non-floater. This searches down the linked
- * list of windows that is maintained internaly by the Macintosh OS
- * (the linked list kept through the WindowRecord field 'nextWindow')
- * until I find a window which has the proper type.
- */
-
- WindowPtr MFrontWindow(void)
- {
- WindowPeek w;
-
- w = (WindowPeek)FrontWindow();
- for (;;) {
- if (w == NULL) break;
- if (w->windowKind != KFloatingWindow) {
- if (w->visible) break;
- }
- w = w->nextWindow; /* Nope, this ain't it. Go on. */
- }
- return (WindowPtr)w;
- }
-
- /* MLastFloater
- *
- * Get the last floater window position. This is not similar to
- * anything in the Macintosh OS, but is very useful for figuring out
- * where new non-floater windows go.
- */
-
- WindowPtr MLastFloater(void)
- {
- WindowPeek w;
- WindowPeek prev;
-
- prev = NULL;
- w = (WindowPeek)FrontWindow();
- while (w && (w->windowKind == KFloatingWindow)) {
- prev = w;
- w = w->nextWindow;
- }
- return (WindowPtr)prev;
- }
-
- /************************************************************************/
- /* */
- /* Selection Routines */
- /* */
- /************************************************************************/
-
- /* MSelectWindow
- *
- * Like select window, except for floating windows. If this is called
- * with a floating window, it brings the floating window to the front of
- * all of the floating windows. If called on a non-floater, this brings
- * the non-floating window frontmost.
- */
-
- void MSelectWindow(WindowPtr w)
- {
- short isFloater;
- WindowPtr current;
- WindowPtr last;
-
- /*
- * Based on what kind of window this is (floating, nonfloating)
- * initialize some interesting variables for later
- */
-
- if (((WindowPeek)w)->windowKind == KFloatingWindow) {
- current = FrontWindow();
- isFloater = 1;
- } else {
- isFloater = 0;
- current = MFrontWindow();
- last = MLastFloater();
- }
-
- /*
- * Now if we are not the current window, do the selection
- */
-
- if (current != w) {
- if (isFloater) {
- /*
- * Bringing a floater forward can be done by bringing the
- * thing all the way to the front.
- */
-
- BringToFront(w);
- } else {
- if (last == NULL) {
- /*
- * This is a standard window, but there are no floaters
- */
-
- HiliteWindow(current,0); /* Unhilite this window */
- DoActivate(current,0); /* And deactivate it */
- BringToFront(w); /* Bring this one frontmost */
- HiliteWindow(w,1);
- DoActivate(w,1); /* ###6 Need System 6 tests.*/
- } else {
- HiliteWindow(current,0); /* Unhilite this window */
- DoActivate(current,0); /* And deactivate it */
- SendBehind(w,last);
-
- #ifdef PREVERSION7
- /*
- * The following two routines are only needed if this
- * were to run under an operating system earlier than
- * System 7. But as we are not going to do that, well,
- * these routines simply are not needed; the routine
- * 'SendBehind' does the right thing.
- */
-
- PaintOne((WindowPeek)w,((WindowPeek)w)->strucRgn);
- CalcVis((WindowPeek)w);
- #endif
-
- HiliteWindow(w,1);
- DoActivate(w,1); /* ###6 Need System 6 tests.*/
- } /* PaintOne & CalcVis */
- }
- }
- }
-
- /* MDragWindow
- *
- * Do the drag window thing
- */
-
- void MDragWindow(WindowPtr windowToDrag, Point startPoint, const Rect *draggingBounds)
- {
- Rect dragRect;
- KeyMap keyMap;
- GrafPtr savePort;
- GrafPtr windowManagerPort;
- RgnHandle dragRegion;
- RgnHandle windowContentRegion;
- long dragResult;
- short topLimit;
- short newHorizontalWindowPosition;
- short newVerticalWindowPosition;
- short horizontalOffset;
- short verticalOffset;
- Boolean commandKeyDown = false;
-
- if (WaitMouseUp()) {
- /*
- * Adjust the top of the dragging rectangle so that it’s below
- * the menu bar
- */
-
- topLimit = LMGetMBarHeight() + 4;
- dragRect = *draggingBounds;
- if (dragRect.top < topLimit) dragRect.top = topLimit;
-
- /* Set up the Window Manager port. */
-
- GetPort(&savePort);
- GetWMgrPort(&windowManagerPort);
- SetPort(windowManagerPort);
- SetClip(GetGrayRgn());
-
- /*
- * Check to see if the command key is down. If it is, don’t bring the window to the
- * front after the move. Trying to do Pascal stuff in C is so much fun. GetKeys()
- * is a total pain to try to use properly from C, so I’m going to hard code where the
- * command key is in the KeyMap array.
- */
-
- GetKeys(keyMap);
- if (keyMap[1] & 0x8000) commandKeyDown = true;
- if ((commandKeyDown == true) ||
- (((WindowPeek)windowToDrag)->windowKind != KFloatingWindow)) {
-
- if (commandKeyDown == false)
-
- /*
- * If there are floating windows, clip the dragging outline
- * to draw behind the floaters.
- */
-
- ClipAbove(MFrontWindow());
- else
-
- /*
- * If the command key was down, clip the outline to draw behind any windows above
- * the window being dragged.
- */
-
- ClipAbove(windowToDrag);
- }
-
- /* Create a region to drag */
-
- dragRegion = NewRgn();
- CopyRgn(((WindowPeek)windowToDrag)->strucRgn, dragRegion);
-
- /* Drag the window around */
-
- dragResult = DragGrayRgn(dragRegion, startPoint, &dragRect, &dragRect, noConstraint, nil);
-
- /* Restore the port for coordinate conversion. */
-
- SetPort(savePort);
-
- if (dragResult != 0) {
- horizontalOffset = dragResult & 0xFFFF;
- verticalOffset = dragResult >> 16;
-
- /* Only move it if it stayed inside the dragging box. */
-
- if (verticalOffset != -32768) {
- windowContentRegion = ((WindowPeek)windowToDrag)->contRgn;
- newHorizontalWindowPosition = (**windowContentRegion).rgnBBox.left + horizontalOffset;
- newVerticalWindowPosition = (**windowContentRegion).rgnBBox.top + verticalOffset;
-
- MoveWindow((WindowPtr) windowToDrag, newHorizontalWindowPosition, newVerticalWindowPosition, false);
-
- }
- }
-
- /* Bring the window forward if the command key wasn’t down */
-
- if (commandKeyDown == false)
- MSelectWindow(windowToDrag);
-
- /* Get rid of the dragging region */
-
- DisposeRgn(dragRegion);
- }
- }
-
- /* MGetWindowList
- *
- * Get the window list top
- */
-
- static WindowPtr MGetWindowList(void)
- {
- return (*(WindowPtr *)0x09D6);
- }
-
- /* MValidateWindowList
- *
- * Validation of the window list's order
- */
-
- static void MValidateWindowList(void)
- {
- WindowPtr currentWindow = MGetWindowList();
- WindowPtr lastFloatingWindow = MLastFloater();
- WindowPtr firstFloatingWindow = nil;
- WindowPtr documentWindowsToMove = nil;
- WindowPtr lastDocumentWindowAdded = nil;
- WindowPtr previousWindow = nil;
-
- if (currentWindow) {
-
- /*
- * First, gather up all the document windows in front of floating windows. We iterate
- * through the window list until a floating window is encountered.
- */
- do {
- if (((WindowPeek)currentWindow)->windowKind == KFloatingWindow) {
- firstFloatingWindow = currentWindow;
- break;
- }
- else {
- ((WindowPeek)previousWindow)->nextWindow = ((WindowPeek)currentWindow)->nextWindow;
-
- if (documentWindowsToMove == nil)
- documentWindowsToMove = currentWindow;
- else
- ((WindowPeek)lastDocumentWindowAdded)->nextWindow = (WindowPeek)currentWindow;
- lastDocumentWindowAdded = currentWindow;
-
- previousWindow = currentWindow;
- currentWindow = (WindowPtr)(((WindowPeek)currentWindow)->nextWindow);
- }
- } while (currentWindow);
-
- /* Now put them back in their place. */
-
- if (documentWindowsToMove && firstFloatingWindow) {
- ((WindowPeek)lastDocumentWindowAdded)->nextWindow = ((WindowPeek)lastFloatingWindow)->nextWindow;
- ((WindowPeek)lastFloatingWindow)->nextWindow = (WindowPeek)documentWindowsToMove;
-
- /*
- * If the first window in the window list was a document window, and there are
- * floating windows, then make the floating window the first window in the window
- * list.
- */
- if (documentWindowsToMove == MGetWindowList())
- (*(WindowPtr *)0x09D6) = firstFloatingWindow;
- }
- }
- }
-
- /* MShowWindow
- *
- * How to show this window and make it visible
- */
-
- void MShowWindow(WindowPtr windowToShow)
- {
- WindowPtr windowBehind;
- WindowPtr frontNonFloatingWindow;
- short windowClass;
- Boolean windowIsInFront = false;
-
- if (((WindowPeek)windowToShow)->visible != false) return;
-
- windowClass = ((WindowPeek)windowToShow)->windowKind;
-
- /* Handle special case of movable modal dialog. */
-
- if (windowClass == dialogKind) {
- /* Unhilite the frontmost document window */
- windowBehind = MFrontWindow();
- if (windowBehind != NULL) {
- HiliteWindow(windowBehind,0);
- DoActivate(windowBehind,0);
- }
-
- ((WindowPeek)windowToShow)->hilited = true; /* Hilite this */
- ShowHide((WindowPtr)windowToShow,true); /* Show this */
- DoActivate(windowToShow,1); /* Activate this */
- return;
- }
-
- /*
- * If the window behind the window to show is currently the frontmost document window,
- * unhighlight it, and highlight the new front window.
- */
-
- if (windowClass != KFloatingWindow) {
- windowBehind = (WindowPtr)(((WindowPeek)windowToShow)->nextWindow);
- if (windowBehind == MFrontWindow()) {
- if (windowBehind != NULL) {
- HiliteWindow(windowBehind,0);
- DoActivate(windowBehind,0);
- }
-
- /* Set the highlight state so the window appears highlighted from the start. */
-
- ((WindowPeek)windowToShow)->hilited = true;
- windowIsInFront = true;
- }
- } else {
-
- /*
- * A floating window is about to be shown. Make sure the windows in the
- * window list are all in the right place.
- */
-
- MValidateWindowList();
-
- frontNonFloatingWindow = MFrontWindow();
- ((WindowPeek)windowToShow)->hilited = true;
- windowIsInFront = true;
- }
-
- /* Show the window */
-
- ShowHide((WindowPtr) windowToShow, true);
-
- /* If this is the new frontmost document window or a floating window, send it an activate event */
-
- if (windowIsInFront) {
- DoActivate(windowToShow,1);
- }
- }
-
- /* MHideWindow
- *
- * How to hide this window
- */
-
- void MHideWindow(WindowPtr windowToHide)
- {
- WindowPtr frontFloater;
- WindowPtr frontNonFloater;
- WindowPtr lastFloater;
- WindowPtr windowBehind;
- short windowClass;
-
- /* Don’t do anything if the window is already invisible. */
-
- if (((WindowPeek)windowToHide)->visible == false) return;
-
- /* Handle special case of movable modal dialog */
-
- windowClass = ((WindowPeek)windowToHide)->windowKind;
- if (windowClass == dialogKind) {
- /* Hide the window */
- ShowHide(windowToHide,false);
-
- /* Hilite the frontmost document window */
- frontNonFloater = MFrontWindow();
- if (frontNonFloater != NULL) {
- HiliteWindow(frontNonFloater,1);
- DoActivate(frontNonFloater,1);
- }
- return;
- }
-
- /* Get the first visible floating window, if any. */
-
- frontFloater = FrontWindow();
- if (((WindowPeek)frontFloater)->windowKind != KFloatingWindow) frontFloater = nil;
-
- /* Get the first visible document window, if any. */
-
- frontNonFloater = MFrontWindow();
-
- /* Hide the window. */
-
- ShowHide((WindowPtr) windowToHide, false);
-
- /*
- * If the frontmost floating window is being hidden, move it behind the floating window
- * behind it, if there is one.
- */
- if (windowToHide == frontFloater) {
- windowBehind = (WindowPtr)(((WindowPeek)windowToHide)->nextWindow);
-
- /* Only do the rearrangement if there’s another floating window. */
-
- if ((windowBehind != nil) && (((WindowPeek)windowBehind)->windowKind == KFloatingWindow)) {
- ((WindowPeek)windowToHide)->nextWindow = ((WindowPeek)windowBehind)->nextWindow;
- ((WindowPeek)windowBehind)->nextWindow = (WindowPeek)windowToHide;
- (*(WindowPtr *)0x09D6) = windowBehind;
- }
- }
- else {
-
- /* If the frontmost document window is behind hidden, send it behind the window
- * behind it.
- */
- if (windowToHide == frontNonFloater) {
- windowBehind = (WindowPtr)(((WindowPeek)windowToHide)->nextWindow);
-
- if (windowBehind != nil) {
- ((WindowPeek)windowToHide)->nextWindow = ((WindowPeek)windowBehind)->nextWindow;
- ((WindowPeek)windowBehind)->nextWindow = (WindowPeek)windowToHide;
-
- /* Set the next link of the last floating window to point to the previously second
- * to front document window. If there was no floating window, change the beginning
- * of the window list.
- */
- lastFloater = MLastFloater();
- if (lastFloater != nil)
- ((WindowPeek)lastFloater)->nextWindow = (WindowPeek)windowBehind;
- else
- (*(WindowPtr *)0x09D6) = windowBehind;
-
- /* The window behind it is now the front document window. Highlight it and send it
- * and activate event.
- */
- HiliteWindow(windowBehind,1);
- DoActivate(windowBehind,1);
- }
- }
- }
- }
-
- /************************************************************************/
- /* */
- /* Window Creation */
- /* */
- /************************************************************************/
-
- /* MNewWindow
- *
- * Do the same thing as the NewWindow call, but open the window
- * right behind the floater
- */
-
- WindowPtr MNewWindow(Ptr st, Rect *bounds, unsigned char *title, Boolean vis, short wDef, WindowPtr behind, Boolean goAway, long refCon)
- {
- WindowPtr w;
-
- /* Reset the behind pointer depending on the order of this thing */
-
- if ((wDef >= 2048) && (wDef <= 2063)) {
- /*
- * If the 'wDef' parameter (the window definition) is between
- * 2048 and 2063, this is a floating window definition function.
- * (This coorisponds to a 'WDEF' resource of 128
- */
-
- if (behind == NULL) {
- behind = MLastFloater();
- if (behind == NULL) behind = (WindowPtr)-1L;
- }
- } else if ((wDef == 1) || (wDef == 5)) {
- behind = (WindowPtr)-1L; /* always in front. */
- } else {
- if (behind == (WindowPtr)-1L) {
- behind = MLastFloater();
- if (behind == NULL) behind = (WindowPtr)-1L;
- }
- }
-
- /* Get the current front window for deactivation, and create it */
-
- w = NewWindow(st,bounds,title,false,wDef,behind,goAway,refCon);
- if (w == NULL) return NULL;
-
- /* Do the activation/deactivation if this window is visible */
- if ((wDef >= 2048) && (wDef <= 2063)) {
- ((WindowPeek)w)->windowKind = KFloatingWindow;
- } else {
- ((WindowPeek)w)->windowKind = KNormalWindow;
- }
- if (vis) MShowWindow(w);
- return w;
- }
-
- /* MNewCWindow
- *
- * Do the same thing as the NewWindow call, but open the window
- * right behind the floater
- */
-
- WindowPtr MNewCWindow(Ptr st, Rect *bounds, unsigned char *title, Boolean vis, short wDef, WindowPtr behind, Boolean goAway, long refCon)
- {
- WindowPtr w;
-
- /* Reset the behind pointer depending on the order of this thing */
-
- if ((wDef >= 2048) && (wDef <= 2063)) {
- /*
- * If the 'wDef' parameter (the window definition) is between
- * 2048 and 2063, this is a floating window definition function.
- * (This coorisponds to a 'WDEF' resource of 128
- */
-
- if (behind == NULL) {
- behind = MLastFloater();
- if (behind == NULL) behind = (WindowPtr)-1L;
- }
- } else if ((wDef == 1) || (wDef == 5)) {
- behind = (WindowPtr)-1L; /* always in front. */
- } else {
- if (behind == (WindowPtr)-1L) {
- behind = MLastFloater();
- if (behind == NULL) behind = (WindowPtr)-1L;
- }
- }
-
- /* Get the current front window for deactivation, and create it */
-
- w = NewCWindow(st,bounds,title,false,wDef,behind,goAway,refCon);
- if (w == NULL) return NULL;
-
- /* Do the activation/deactivation if this window is visible */
- if ((wDef >= 2048) && (wDef <= 2063)) {
- ((WindowPeek)w)->windowKind = KFloatingWindow;
- } else {
- ((WindowPeek)w)->windowKind = KNormalWindow;
- }
- if (vis) MShowWindow(w);
- return w;
- }
-
- /* MCloseWindow
- *
- * This handles closing the window.
- */
-
- void MCloseWindow(WindowPtr w)
- {
- if (((WindowPeek)w)->visible) MHideWindow(w);
- CloseWindow(w);
- }
-
- /* MDisposeWindow
- *
- * This handles closing the window.
- */
-
- void MDisposeWindow(WindowPtr w)
- {
- if (((WindowPeek)w)->visible) MHideWindow(w);
- DisposeWindow(w);
- }
-
-