💾 Archived View for mirrors.apple2.org.za › archive › apple.cabi.net › Graphics › PICT.and_QT.INFO ›… captured on 2024-05-10 at 15:25:42.

View Raw

More Information

⬅️ Previous capture (2023-01-29)

-=-=-=-=-=-=-

/******************************************************************************\

\******************************************************************************/


/******************************************************************************\

\******************************************************************************/

/* System header files needed by MPW C */
#ifndef THINK_C
#include <Errors.h>
#include <Menus.h>
#include <Resources.h>
#include <Windows.h>
#endif

#include <GestaltEqu.h>
#include <Palettes.h>
#include <Picker.h>
#include <QDOffscreen.h>

/* Header files specific to this program */
#include "PictDocument.h"
#include "EmergMem.h"
#include "Exceptions.h"
#include "ColorReset.h"
#include "MenuHandler.h"
#include "WindowPositioner.h"


/******************************************************************************\

\******************************************************************************/

/* Picture Document window constants */
#define rPictDocWindID 128 /* Resource ID of Picture Document WIND resource */
#define rScrollBarID   128 /* Resource ID of scroll bar CNTL resource */
#define kDocWKind      128 /* windowKind field of Picture Document windows */
#define kMinWindowSize 64  /* Minimum size of the window in pixels */

/* PICT file constants */
#define kPictFileHeaderSize 512    /* Number of bytes in PICT file header */
#define kFileCreator        'CLIM' /* Creator code for this application */
#define kFileType           'PICT' /* File type for this app.s documents */

/* Off-screen Constants */
#define kMaxRowBytes 0x3FFE     /* Maximum number of bytes in a row of pixels */
#define kDefaultRes  0x00480000 /* Default resolution is 72 DPI; Fixed type */
#define kITabRes     4          /* Inverse-table resolution */

/* Miscellaneous constants */
#define kPaintRadius 8 /* Radius of a drop of paint in pixels */


/******************************************************************************\

\******************************************************************************/

/* Picture Document information */
typedef struct
{
	GWorldPtr     image;      /* Pointer to image in off-screen GWorld */
	Rect          windowRect; /* Rectangle of window except for scroll bars */
	Rect          destRect;   /* Rectangle of image in window */
	RGBColor      foreground; /* Color of foreground */
	RGBColor      background; /* Color of background */
	ControlHandle vScrollBar; /* Horizontal scroll bar */
	ControlHandle hScrollBar; /* Vertical scroll bar */
	FSSpec        file;       /* File spec of Picture Document.s PICT file */
	short         fileRef;    /* File ref # of Picture Document.s PICT file */
	Boolean       dithering;  /* True if image should be dithered */
} PictDocInfoRec, *PictDocInfoPtr, **PictDocInfoHnd;

/* Basic picture information */
typedef struct
{
	CTabHandle colors; /* Handle to color table of deepest pixel map */
	short      depth;  /* Max depth for all pixmaps (in the picture) */
	Rect       frame;  /* Picture frame rect (contains entire picture) */
} PictureInfoRec;


/******************************************************************************\

\******************************************************************************/

static OSErr CreatePictDoc(
	Rect       *pictureRect,
	short      pictureDepth,
	CTabHandle pictureClut,
	WindowPtr  *retDoc);

pascal void ScrollActionProc(
	ControlHandle control,
	short         part);

static void ScrollPictDoc(
	WindowPtr docWindow,
	short     hScrollDelta,
	short     vScrollDelta);

void ResizePictDoc(
	WindowPtr docWindow);

OSErr CreateOffScreen(
	Rect       *bounds,
	short      depth,
	CTabHandle colors,
	CGrafPtr   *retPort,
	GDHandle   *retGDevice);

OSErr SetUpPixMap(
	short        depth,
	Rect         *bounds,
	CTabHandle   colors,
	short        bytesPerRow,
	PixMapHandle aPixMap);

OSErr CreateGDevice(
	PixMapHandle basePixMap,
	GDHandle     *retGDevice);

void DisposeOffScreen(
	CGrafPtr doomedPort,
	GDHandle doomedGDevice);

OSErr GetPictureInfo(
	short          pictFileRef,
	PictureInfoRec *retPictInfo);

pascal void InfoBits(
	BitMapPtr srcBits,
	Rect      *srcRect,
	Rect      *dstRect,
	short     mode,
	RgnHandle maskRgn);

OSErr DrawFilePicture(
	short pictFileRef,
	Rect  *destRect);

pascal void FileGetPic(
	Ptr   dataPtr,
	short byteCount);

OSErr OpenFilePicture(
	short pictFileRef,
	Rect  *sourceRect);

OSErr CloseFilePicture(void);

pascal void FilePutPic(
	Ptr   dataPtr,
	short byteCount);


/******************************************************************************\

\******************************************************************************/

PictureInfoRec gPictureInfo;  /* Information about a PICT file */
PicHandle      gSpoolPicture; /* Temporary picture used to spool from PICT file */
QDProcsPtr     gSavedProcs;   /* Saves existing QDProcs; used when spooling out */
CQDProcs       gCustomProcs;  /* Customized bottlenecks to spool to PICT file */
short          gPictFileRef;  /* File reference number of a PICT file */
short          gPictureSize;  /* Size of picture in bytes */


/******************************************************************************\

\******************************************************************************/

WindowPtr FindPictDoc(
	FSSpecPtr fileSpec) /* Specification of file to search for */
{
	WindowPtr      pictDocWindow; /* Pointer to Picture Document being tested */
	PictDocInfoHnd pictDocInfo;   /* Handle to Picture Document info rec */
	Boolean        foundDoc;      /* True if found Pict Doc w/ same FSSpec */

	/* Get a pointer to the first Picture Document window in the window list */
	pictDocWindow = NextPictDocWindow( nil );

	/* Keep searching until found or at end of list */
	foundDoc = false;
	while (pictDocWindow != nil && !foundDoc)
	{
		/* Only have to check FSSpecs if document has a corresponding file */
		pictDocInfo = (PictDocInfoHnd)GetWRefCon( pictDocWindow );
		if ((**pictDocInfo).fileRef != 0)
		{
			/* See if the Picture Document.s file is same as fileSpec */
			HLock( (Handle)pictDocInfo );
			foundDoc = EqualFSSpec( fileSpec, &(**pictDocInfo).file );
			HUnlock( (Handle)pictDocInfo );

			/* If FSSpecs aren.t the same, then go to next Picture Document */
			if (!foundDoc)
				pictDocWindow = NextPictDocWindow( pictDocWindow );
		}
	}

	return pictDocWindow;
}


/******************************************************************************\

\******************************************************************************/

WindowPtr NextPictDocWindow(
	WindowPtr aWindow) /* Window to start search from, or nil if front */
{
	/* Start search from next window, or front window if aWindow is nil */
	if (aWindow == nil)
		aWindow = FrontWindow();
	else
		aWindow = (WindowPtr)((WindowPeek)aWindow)->nextWindow;

	/* Search until Picture Document wind found or end of wind list reached */
	while (aWindow != nil && !IsPictDocWindow( aWindow ))
		aWindow = (WindowPtr)((WindowPeek)aWindow)->nextWindow;

	return aWindow;
}


/******************************************************************************\

\******************************************************************************/

Boolean IsPictDocWindow (
	WindowPtr aWindow) /* Pointer to the window being tested */
{
	return ((WindowPeek)aWindow)->windowKind == kDocWKind;
}


/******************************************************************************\

\******************************************************************************/

void DrawPictDoc(
	WindowPtr docWindow) /* Ptr to Picture Document window being drawn */
{
	PictDocInfoHnd pictDocInfo; /* Handle to Picture Document information rec */
	GWorldPtr      image;       /* Pointer to the off-screen image */
	Rect           destRect;    /* Rectangle to copy image into */
	Rect           sourceRect;  /* Rectangle to copy image from */
	Rect           windowRect;  /* Rect of the window except for scroll bars */
	short          mode;        /* Drawing mode to use */

	/* Get a pointer to the off-screen image and the window rectangle */
	pictDocInfo = (PictDocInfoHnd)GetWRefCon( docWindow );
	image = (**pictDocInfo).image;
	windowRect = (**pictDocInfo).windowRect;

	/* Calculate the rectangle to copy the image to */
	destRect = (**pictDocInfo).destRect;
	(void)SectRect( &destRect, &windowRect, &destRect );

	/* Calculate the rectangle to copy the image from */
	sourceRect = destRect;
	OffsetRect( &sourceRect, -(**pictDocInfo).destRect.left,
			-(**pictDocInfo).destRect.top );

	/* Specify the drawing mode to use */
	mode = srcCopy;
	if ((**pictDocInfo).dithering)
		mode |= ditherCopy;

	/* Draw the off-screen image to the screen */
	EraseRect( &docWindow->portRect );
	CopyBits( &((GrafPtr)image)->portBits, &docWindow->portBits,
			&sourceRect, &destRect,
			mode, nil );

	/* Draw the grow box */
	DrawGrowIcon( docWindow );

	/* Draw the scroll bars */
	DrawControls( docWindow );
}


/******************************************************************************\

\******************************************************************************/

void ClickPictDoc(
	WindowPtr   docWindow,   /* Picture Document window that was clicked */
	EventRecord *clickEvent) /* Mouse click event */
{
	PictDocInfoHnd pictDocInfo;     /* Handle to Picture Document info rec */
	GWorldPtr      image;           /* Pointer to the off-screen image */
	GDHandle       savedDevice;     /* Saves default GDevice */
	Rect           paintRect;       /* Rectangle to draw paint into */
	Rect           windowPaintRect; /* Rectangle to draw paint into */
	Rect           windowRect;      /* Window rect except for scroll bars */
	Rect           destRect;        /* Rectangle of image in window */
	Point          newPosition;     /* New pos of mouse click; local coords */
	Point          oldPosition;     /* Old pos of mouse click; local coords */
	ControlHandle  scrollBar;       /* Handle to the clicked scroll bar */
	short          partNumber;      /* Part # of clicked part of control */
	short          scrollDelta;     /* Number of pixels to scroll */

	savedDevice = GetGDevice();

	/* Get information about the Picture Document */
	pictDocInfo = (PictDocInfoHnd)GetWRefCon( docWindow );
	image = (**pictDocInfo).image;
	windowRect = (**pictDocInfo).windowRect;
	destRect = (**pictDocInfo).destRect;

	/* Get the mouse click position */
	SetPort( docWindow );
	newPosition = clickEvent->where;
	GlobalToLocal( /*.*/&newPosition );

	/* Find whether the mouse was in a control */
	partNumber = FindControl( newPosition, docWindow, /*<*/&scrollBar );
	switch (partNumber)
	{
		case 0:
			/* Clicked outside of any control; see if it was in the image */
			if (PtInRect( newPosition, &windowRect ))
			{
				/* Click in image; paint while mouse button is held down */
				oldPosition.v = oldPosition.h = -32767;
				while (StillDown())
				{
					/* Only do something if the mouse moved */
					if (!EqualPt( newPosition, oldPosition ))
					{
						/* Need to offset paint brush for scrolled position */
						SubPt( topLeft( destRect ), /*.*/&newPosition );
						SetRect( /*<*/&paintRect, newPosition.h - kPaintRadius,
								newPosition.v - kPaintRadius,
								newPosition.h + kPaintRadius,
								newPosition.v + kPaintRadius );

						/* Drop some paint into the off-screen image */
						SetGWorld( image, nil );
						PaintOval( &paintRect );

						/* Offset brush back to window position */
						AddPt( topLeft( destRect ), /*.*/&newPosition );

						/* Calc rect in window for to brush rect in image */
						windowPaintRect = paintRect;
						OffsetRect( &windowPaintRect, destRect.left,
								destRect.top );

						/* Only copy if some part of brush within image */
						if (SectRect( &windowPaintRect, &windowRect,
								&windowPaintRect ))
						{
							/* Make clipped paint rect in off-screen image */
							paintRect = windowPaintRect;
							OffsetRect( &paintRect, -destRect.left,
									-destRect.top );

							/* Copy painted off-screen image to the screen */
							SetGWorld( (CGrafPtr)docWindow, nil );
							CopyBits( &((GrafPtr)image)->portBits, &docWindow->portBits,
									&paintRect, &windowPaintRect,
									srcCopy, nil );
						}

						/* Remember the new mouse position */
						oldPosition = newPosition;
					}

					/* Get the new position of the mouse */
					SetPort( docWindow );
					GetMouse( /*<*/&newPosition );
				}
			}
			break;
		case inThumb:
			/* Mouse in thumb of scroll bar; get existing control value */
			scrollDelta = GetCtlValue( scrollBar );

			/* Track mouse in thumb until mouse button is released */
			partNumber = TrackControl( scrollBar, newPosition, nil );
			if (partNumber != 0)
			{
				/* Find diff between old and new scroll bar values */
				scrollDelta -= GetCtlValue( scrollBar );
				if (scrollDelta != 0)
				{
					if (scrollBar == (**pictDocInfo).vScrollBar)
						ScrollPictDoc( docWindow, 0, scrollDelta );
					else
						ScrollPictDoc( docWindow, scrollDelta, 0 );
				}
			}
			break;
		case inUpButton:
		case inDownButton:
		case inPageUp:
		case inPageDown:
			(void)TrackControl( scrollBar, newPosition, (ProcPtr)ScrollActionProc );
			break;
		default:
			break;
	}
}


/******************************************************************************\

\******************************************************************************/

static pascal void ScrollActionProc(
	ControlHandle control, /* Handle to clicked control */
	short         part)    /* Part number of clicked control part */
{
	PictDocInfoHnd pictDocInfo; /* Handle to Picture Document info rec */
	WindowPtr      docWindow;   /* Clicked Picture Document window */
	Rect           windowRect;  /* Window rect except for scroll bars */
	Rect           destRect;    /* Rectangle of image in window */
	short          scrollDelta; /* Number of pixels to scroll by */
	short          oldValue;    /* Value of scroll bar before scrolling */
	short          newValue;    /* Value of scroll bar after scrolling */
	short          maxValue;    /* Maximum value of the scroll bar */

	/* Get information about the Picture Document */
	docWindow = (**control).contrlOwner;
	pictDocInfo = (PictDocInfoHnd)GetWRefCon( docWindow );
	windowRect = (**pictDocInfo).windowRect;
	destRect = (**pictDocInfo).destRect;

	/* Only process if the part # isn.t zero */
	if (part != 0)
	{
		/* Decide scroll amount based on part of control that was clicked */
		switch (part)
		{
			case inUpButton:
				scrollDelta = 1;
				break;
			case inDownButton:
				scrollDelta = -1;
				break;
			case inPageUp:
				scrollDelta = 32;
				break;
			case inPageDown:
				scrollDelta = -32;
				break;
			default:
				scrollDelta = 0;
				break;
		}

		/* Only do something if we.re actually scrolling */
		if (scrollDelta != 0)
		{
			/* Get the current scroll bar state */
			maxValue = GetCtlMax( control );
			oldValue = GetCtlValue( control );

			/* Calculate the new scroll bar value pinned to the limits */
			newValue = oldValue - scrollDelta;
			if (newValue < 0)
				newValue = 0;
			else if (newValue > maxValue)
				newValue = maxValue;

			/* Only scroll if the old and new values are different */
			if (oldValue != newValue)
			{
				/* Set the new value of the scroll bar */
				SetCtlValue( control, newValue );

				/* Scroll by difference between old and new scroll bar values */
				scrollDelta = oldValue - newValue;
				if (control == (**pictDocInfo).vScrollBar)
					ScrollPictDoc( docWindow, 0, scrollDelta );
				else
					ScrollPictDoc( docWindow, scrollDelta, 0 );
			}
		}
	}
}


/******************************************************************************\

\******************************************************************************/

static void ScrollPictDoc(
	WindowPtr docWindow,    /* Pointer to document window to scroll */
	short     hScrollDelta, /* Number of pixels to scroll horizontally */
	short     vScrollDelta) /* Number of pixels to scroll vertically */
{
	PictDocInfoHnd pictDocInfo;  /* Handle to Picture Document info rec */
	RgnHandle      updateRegion; /* Region covering scrolled-in area */
	Rect           windowRect;   /* Rect of window except for scroll bars */
	Rect           destRect;     /* New destination rectangle */
	GWorldPtr      image;        /* Off-screen document image */

	/* Get the window rectangle and destination rectangle */
	pictDocInfo = (PictDocInfoHnd)GetWRefCon( docWindow );
	windowRect = (**pictDocInfo).windowRect;
	destRect = (**pictDocInfo).destRect;
	image = (**pictDocInfo).image;

	/* Scroll the image by the specified amount */
	updateRegion = NewRgn();
	ScrollRect( &windowRect, hScrollDelta, vScrollDelta, updateRegion );

	/* Update the destination rectangle to the new scrolled position */
	OffsetRect( &destRect, hScrollDelta, vScrollDelta );
	(**pictDocInfo).destRect = destRect;

	/* Update the scrolled-in part of the window */
	CopyBits( &((GrafPtr)image)->portBits, &docWindow->portBits,
			&image->portRect, &destRect,
			srcCopy, updateRegion );

	/* Get rid of the update region */
	DisposeRgn( updateRegion );
}


/******************************************************************************\

\******************************************************************************/

void GrowPictDoc(
	WindowPtr   docWindow,   /* Picture Document window that.s to be grown */
	EventRecord *clickEvent) /* Mouse down event */
{
	PictDocInfoHnd pictDocInfo; /* Handle to Picture Document info rec */
	Rect           growBounds;  /* Window can be dragged over this rectangle */
	Point          newSize;     /* New size of the new window */

	pictDocInfo = (PictDocInfoHnd)GetWRefCon( docWindow );

	growBounds = (**pictDocInfo).image->portRect;
	growBounds.left = growBounds.top = kMinWindowSize;
	growBounds.right += kScrollBarWidth;
	growBounds.bottom += kScrollBarWidth;

	/* Let the user resize the window to any size */
	*((long *)&newSize) = GrowWindow( docWindow, clickEvent->where,
			&growBounds );

	/* If the user actually changed the size of the window, resize the window */
	if (*((long *)&newSize) != 0)
	{
		SizeWindow( docWindow, newSize.h, newSize.v, true );
		ResizePictDoc( docWindow );
	}
}


/******************************************************************************\

\******************************************************************************/

static void ResizePictDoc(
	WindowPtr docWindow) /* Picture document window that was resized */
{
	PictDocInfoHnd pictDocInfo;   /* Handle to Picture Document information rec */
	ControlHandle  vScrollBar;    /* Vertical scroll bar */
	ControlHandle  hScrollBar;    /* Horizontal scroll bar */
	Rect           windowRect;    /* Covers part of window that contains image */
	Rect           newWindowRect; /* Covers all of window except scroll bars */
	Rect           scrollRect;    /* Rectangle of scroll bar */
	Rect           destRect;      /* Rectangle of to draw image into */
	Rect           newDestRect;   /* Rec