/*********************************************************/
/* This source code copyright (c) 1991-2001, Aaron Giles */
/* See the Read Me file for licensing information.       */
/* Contact email: mac@aarongiles.com                     */
/*********************************************************/

//=====================================================================================
// Generic includes for Macintosh headers
//=====================================================================================

#if THINK_C
#include "THINK.Header"
#elif applec
#pragma load ":Headers:MPW.Header"
#elif __MWERKS__
//#include "MW.Header"
#else
#include "JPEGView.h"
#endif

//=====================================================================================
// Includes specific to this module
//=====================================================================================

#include "EventUtils.h"

//=====================================================================================
// Local variables
//=====================================================================================

static Pattern gAnimPatternT = { 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0 };
static Pattern gAnimPatternB = { 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0 };
static Pattern gAnimPatternL = { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 };
static Pattern gAnimPatternR = { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 };
static Pattern gSelPattern = { 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55 };

//=====================================================================================
// void UpdateCursor(RgnHandle theRgn)
//=====================================================================================
// Update the cursor according to where the mouse pointer is.
//=====================================================================================

extern void UpdateCursor(RgnHandle theRgn) 
{
	static RgnHandle gSizeRgn = nil, gHandRgn = nil, gCrossRgn = nil, gArrowRgn = nil;
	ImageHandle frontImage = FrontImage();
	Point theMouse, offset = { 0, 0 };
	Rect theRect;

	if (!gSizeRgn) 
		gSizeRgn = NewRgn(), gHandRgn = NewRgn(), gCrossRgn = NewRgn(), gArrowRgn = NewRgn();
	SetEmptyRgn(gSizeRgn);
	SetEmptyRgn(gHandRgn);
	SetEmptyRgn(gCrossRgn);
	SetRectRgn(gArrowRgn, -32767, -32767, 32767, 32767);
	if (frontImage && !IsAboutBox(frontImage) && !gSlideShow &&
				(!Full(frontImage) || (*frontImage)->dmon != gMainMonitor || !gMenuVisible)) {
		PushPort();
		MySetPort((CGrafPtr)(*frontImage)->window);
		GetMouse(&theMouse);
		LocalToGlobal(&theMouse);
		LocalToGlobal(&offset);
		PopPort();
		theRect = (*frontImage)->wrect;
		SetRectRgn(gSizeRgn, theRect.right - 16, theRect.bottom - 16, theRect.right, theRect.bottom);
		SectRgn(gSizeRgn, (*frontImage)->window->visRgn, gSizeRgn);
		OffsetRgn(gSizeRgn, offset.h, offset.v);
		RectRgn(gCrossRgn, &theRect);
		SectRgn(gCrossRgn, (*frontImage)->window->visRgn, gCrossRgn);
		OffsetRgn(gCrossRgn, offset.h, offset.v);
		GetAntsSelection((*frontImage)->ants, &theRect);
		RectRgn(gHandRgn, &theRect);
		SectRgn(gHandRgn, (*frontImage)->window->visRgn, gHandRgn);
		OffsetRgn(gHandRgn, offset.h, offset.v);
		DiffRgn(gArrowRgn, gCrossRgn, gArrowRgn);
		DiffRgn(gCrossRgn, gHandRgn, gCrossRgn);
		DiffRgn(gCrossRgn, gSizeRgn, gCrossRgn);
		DiffRgn(gHandRgn, gSizeRgn, gHandRgn);
	}
	if (PtInRgn(theMouse, gArrowRgn)) StopSpinning(&qd.arrow), CopyRgn(gArrowRgn, theRgn);
	if (PtInRgn(theMouse, gCrossRgn)) StopSpinning(*gCross), CopyRgn(gCrossRgn, theRgn);
	if (PtInRgn(theMouse, gHandRgn)) StopSpinning(*gHand), CopyRgn(gHandRgn, theRgn);
	if (PtInRgn(theMouse, gSizeRgn)) StopSpinning(*gSize), CopyRgn(gSizeRgn, theRgn);
}

//=====================================================================================
// Boolean TrackDragRect(Point theAnchor, ImageHandle theImage)
//=====================================================================================
// Tracks the mouse while the user drags an existing selection rectangle.
//=====================================================================================

extern Boolean TrackDragRect(Point theAnchor, ImageHandle theImage) 
{
	Boolean result, inRect, drew = true;
	Rect newRect, theRect, oldRect;
	Point lastPoint, newPoint;
	PenState oldState;
	short offset;

	GetAntsSelection((*theImage)->ants, &oldRect);
	newRect = oldRect;
	PushPort();
	MySetPort((CGrafPtr)(*theImage)->window);
	theRect = (*theImage)->wrect;
	ClipRect(&theRect);
	GetPenState(&oldState);
	PenNormal();
	PenMode(srcXor);
	PenPat(&gSelPattern);
	lastPoint = theAnchor;
	SubPt(TopLeft(newRect), &theAnchor);
	FrameRect(&newRect);
	while (StillDown()) {
		GetMouse(&newPoint);
		if (newPoint.h == lastPoint.h && newPoint.v == lastPoint.v) continue;
		lastPoint = newPoint;
		if (drew) FrameRect(&newRect);
		inRect = PtInRect(newPoint, &theRect);
		if (!inRect && gDragMgrPresent) {
			PopPort();
			return true;
		}
		GetAntsSelection((*theImage)->ants, &newRect);
		SubPt(theAnchor, &newPoint);
		OffsetRect(&newRect, newPoint.h - oldRect.left, newPoint.v - oldRect.top);
		if ((offset = theRect.left - newRect.left) > 0) {
			OffsetRect(&newRect, offset, 0);
			if (inRect) theAnchor.h -= offset;
		}
		if ((offset = theRect.right - newRect.right) < 0) {
			OffsetRect(&newRect, offset, 0);
			if (inRect) theAnchor.h -= offset;
		}
		if ((offset = theRect.top - newRect.top) > 0) {
			OffsetRect(&newRect, 0, offset);
			if (inRect) theAnchor.v -= offset;
		}
		if ((offset = theRect.bottom - newRect.bottom) < 0) {
			OffsetRect(&newRect, 0, offset);
			if (inRect) theAnchor.v -= offset;
		}
		if (drew = inRect) FrameRect(&newRect);
	}
	if (drew) FrameRect(&newRect);
	result = PtInRect(lastPoint, &theRect);
	if (result) SetAntsSelection((*theImage)->ants, &newRect);
	SetPenState(&oldState);
	PopPort();
	return false;
}

//=====================================================================================
// Boolean TrackGrowWindow(Point thePoint, ImageHandle theImage, Boolean constrain,
//			Rect *newRect)
//=====================================================================================
// Tracks the mouse while the user drags the grow region of a window; could probably
// use some cleaning up.
//=====================================================================================

extern Boolean TrackGrowWindow(Point thePoint, ImageHandle theImage, Boolean constrain,
	Rect *newRect)
{
	Rect drawRect, theRect, dragBounds, oldRect, rect1;
	short offsetH, offsetV, tempH, tempV;
	Point newPoint, lastPoint, realLast;
	GrafPort tempPort;
	PenState oldState;

	StopSpinning(*gSize);
	if (Full(theImage)) {
		drawRect = theRect = oldRect = (*theImage)->wrect;
		dragBounds = (*theImage)->window->portRect;
		InsetRect(&drawRect, -1, -1);
	} else {
		drawRect = (*GetStrucRgn((*theImage)->window))->rgnBBox;
		theRect = (*theImage)->window->portRect;
		GlobalRect(&theRect, (*theImage)->window);
		oldRect = theRect;
		dragBounds = (*GetGrayRgn())->rgnBBox;
	}
	PushPort();
	MySetPort((CGrafPtr)(*theImage)->window);
	LocalToGlobal(&thePoint);
	realLast = lastPoint = thePoint;
	OpenPort(&tempPort);
	CopyRgn(GetGrayRgn(), tempPort.visRgn);
	MySetPort((CGrafPtr)&tempPort);
	GetPenState(&oldState);
	PenNormal();
	PenMode(srcXor);
	PenPat(&gSelPattern);
	FrameRect(&drawRect);
	while (StillDown()) {
		newPoint = GlobalMouse();
		if ((newPoint.h == realLast.h) && (newPoint.v == realLast.v)) continue;
		FrameRect(&drawRect);
		offsetH = newPoint.h - lastPoint.h;
		offsetV = newPoint.v - lastPoint.v;
		theRect.right += offsetH;
		theRect.bottom += offsetV;
		lastPoint = newPoint;
		if (constrain) {
			if (abs(newPoint.v - drawRect.bottom) > abs(newPoint.h - drawRect.right)) {
				rect1 = theRect;
				rect1.bottom = rect1.top +
							((long)Height(&oldRect) * (long)Width(&rect1)) / 
							(long)Width(&oldRect);
			} else {
				rect1 = theRect;
				rect1.right = rect1.left +
							((long)Width(&oldRect) * (long)Height(&rect1)) / 
							(long)Height(&oldRect);
			}
			drawRect.right += offsetH;
			drawRect.bottom += offsetV;
			offsetH = rect1.right - theRect.right;
			offsetV = rect1.bottom - theRect.bottom;
			theRect = rect1;
		} else {
			drawRect.right += offsetH;
			drawRect.bottom += offsetV;
			offsetH = offsetV = 0;
		}
		if (theRect.bottom < (theRect.top + 32)) {
			offsetV += (theRect.top + 32) - theRect.bottom;
			theRect.bottom = theRect.top + 32;
			if (constrain) {
				tempH = theRect.left +
							((long)Width(&oldRect) * (long)Height(&theRect)) / 
							(long)Height(&oldRect);
				offsetH += tempH - theRect.right;
				theRect.right = tempH;
			}
		} else if (theRect.bottom > dragBounds.bottom) {
			offsetV += dragBounds.bottom - theRect.bottom;
			theRect.bottom = dragBounds.bottom;
			if (constrain) {
				tempH = theRect.left +
							((long)Width(&oldRect) * (long)Height(&theRect)) / 
							(long)Height(&oldRect);
				offsetH += tempH - theRect.right;
				theRect.right = tempH;
			}
		}
		if (theRect.right < (theRect.left + 32)) {
			offsetH += (theRect.left + 32) - theRect.right;
			theRect.right = theRect.left + 32;
			if (constrain) {
				tempV = theRect.top +
							((long)Height(&oldRect) * (long)Width(&theRect)) / 
							(long)Width(&oldRect);
				offsetV += tempV - theRect.bottom;
				theRect.bottom = tempV;
			}
		} else if (theRect.right > dragBounds.right) {
			offsetH += dragBounds.right - theRect.right;
			theRect.right = dragBounds.right;
			if (constrain) {
				tempV = theRect.top +
							((long)Height(&oldRect) * (long)Width(&theRect)) / 
							(long)Width(&oldRect);
				offsetV += tempV - theRect.bottom;
				theRect.bottom = tempV;
			}
		}
		drawRect.right += offsetH;
		drawRect.bottom += offsetV;
		lastPoint.h += offsetH;
		lastPoint.v += offsetV;
		if (Full(theImage)) {
			offsetH = ((Width(&dragBounds) - Width(&theRect)) >> 1) - theRect.left;
			offsetV = ((Height(&dragBounds) - Height(&theRect)) >> 1) - theRect.top;
			lastPoint.h += offsetH;
			lastPoint.v += offsetV;
			OffsetRect(&drawRect, offsetH, offsetV);
			OffsetRect(&theRect, offsetH, offsetV);
		}
		FrameRect(&drawRect);
		realLast = newPoint;
	}
	FrameRect(&drawRect);
	*newRect = theRect;
	SetPenState(&oldState);
	PopPort();
	ClosePort(&tempPort);
	return (Width(&theRect) != Width(&oldRect)) || (Height(&theRect) != Height(&oldRect));
}
