/*--------------------------------------
	iconstuff.c		The Icon specific cesspool

	Mark Collins
*/

#include "icon.h"
#include <string.h>

extern EventRecordPtr		fEventPtr;
extern word				fUserID;
extern word				mod;
extern word				isInitCurs;
extern long				remHelpID;
extern word				edResFileID, shResFileID, fdResFileID;
extern handle				toolIcn[6];
extern handle				cursor[6];
extern char				tempStr[255];

Pattern patts[16] = {   {	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
						0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
						0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
						0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
					{	0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
						0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
						0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
						0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
					{	0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
						0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
						0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
						0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22},
					{	0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
						0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
						0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
						0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33},
					{	0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
						0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
						0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
						0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44},
					{	0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
						0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
						0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
						0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55},
					{	0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
						0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
						0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
						0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66},
					{	0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
						0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
						0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
						0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77},
					{	0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
						0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
						0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
						0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88},
					{	0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
						0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
						0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
						0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99},
					{	0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
						0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
						0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
						0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa},
					{	0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
						0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
						0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
						0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb},
					{	0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
						0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
						0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
						0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc},
					{	0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
						0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
						0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
						0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd},
					{	0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
						0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
						0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
						0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee},
					{	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
						0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
						0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
						0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};

Rect toolRect[3] = {{0, 0, 0, 0}, { 1,  2, 17, 20 }, { 1,  4, 17, 40 }};
Rect backRect[3] = {{0, 0, 0, 0}, { 1, 24, 17, 42 }, { 1, 48, 17, 84 }};
Rect foreRect[3] = {{0, 0, 0, 0}, { 6, 28, 12, 38 }, { 6, 56, 12, 76 }};

Rect					trg, frg, brg, irg, tr, fr, br, ir;
PenState					thePen;
word					OldX, OldY, DestX, DestY, pixWid, pixDepth;
GrafPort					*TheImage;
Pattern					tempPattern;
Point					xyPoint;
fileIconArrayPtr			arrayPtr;
Handle					button[255];
EventRecord				theEvent;

segment "icon_stuff";

word iconOpen(privateDataPtr privP, GrafPortPtr winP)
{
long				sizeH;

	privP->flag = 0x0000;
	sizeH = GetHandleSize(privP->resData);
	privP->winP = winP;
	privP->editH = (QDIconRecord **) NewHandle(sizeH, fUserID, 0x0018, 0L);
	HandToHand(privP->resData, privP->editH, sizeH);
	if (privP->resType == rCursor) {
		extractCursor (privP);
	}
	privP->undoH = (QDIconRecord **) NewHandle(sizeH, fUserID, 0x0018, 0L);
	HandToHand(privP->editH, privP->undoH, sizeH);

	privP->color = 0xF;
	privP->maskColor = 0x0;
	privP->tool = 0x8002;
	pixWid = getVid();
	pixDepth = (getVid() == 2) ? 1 : 2;
	SetInfoDraw(&DrawInfoBarProc, winP);
	SetWindowSize(privP);
	InitFatIcon(privP);
	SetContentDraw(&DrawEditor, winP);
	ShowWindow(winP);
}

word iconEvent(fEventRecPtr p)
{
word				retErr;
privateDataHndl		privH;
privateDataPtr		privP;
GrafPortPtr			winP, oldP;
Rect				icn, msk;
RegionHndl			theRegion;
Point				pt;
word				inImage;
word				inMask;
word				tool;

	tool = 0;
	oldP = GetPort();
	switch (p->taskCode) {
		case nullEvt:
			winP = FrontWindow();
			theRegion = GetContentRgn(winP);
			privH = getPrivate(winP);
			privP = *privH;
			pt.h = fEventPtr->where.h;
			pt.v = fEventPtr->where.v;
			StartDrawing(winP);
			GlobalToLocal(&pt);
			inImage = PtInRect(&pt, &privP->fatIRect);
			inMask  = PtInRect(&pt, &privP->fatMRect);

			if (inImage || inMask) {
				drawCoords(privP, pt.h, pt.v, inMask);
				if (privP->tool & 0x8000) {
					privP->tool &= 0x0007;
					if (!tool)
						tool = privP->tool;
					SetCursor(*cursor[tool]);
					isInitCurs = 0;
				}
			}
			else if (!isInitCurs) {
				InitCursor();
				isInitCurs = -1;
				privP->tool |= 0x8000;
			}
			break;

		case updateEvt:
			retErr = UpdateEditor((GrafPortPtr) fEventPtr->wmTaskData);
			break;

		case wInInfo:
			retErr = InEditorInfo(fEventPtr);
			break;

		case wInContent:
			FatClick(fEventPtr);
			break;

		case wInSpecial:
		case wInMenuBar:
			retErr = EditorMenu(fEventPtr);
			break;

		case app3Evt:
			winP = (GrafPortPtr) fEventPtr->wmTaskData;
			setTitle(p->resType, p->resID, winP);
			break;

		default:
			break;
	}
	return 0;
}

/*--------------------------------------
    SetWindowSize - guess what this does

    Mark
*/
void SetWindowSize(privateDataPtr privP)
{
QDIconRecord			*iconP;
word				h, w, retErr, winDataHeight, winDataWidth;
morph				trix;

	iconP = *(privP->editH);

/* first- get the height of the InfoBar */
	privP->infoHeight = setMaxOf(iconP->iconHeight, 16) + 4;

/* then set up the local coordinates of the icon rect */
	stuffRect(&privP->iconRect, backRect[pixWid].h2 + 120, 1,
				(iconP->iconWidth + 2) * pixWid ,iconP->iconHeight);

/*  next set up our fatbits screens */
	w = (iconP->iconWidth  * (4 * pixWid)) + 2 + 4;
	h =  (iconP->iconHeight * 4) + 3;
	stuffRect(&(privP->fatIRect), pixWid, 1, w, h);
	stuffRect(&(privP->fatMRect), privP->fatIRect.h2 + (10 * pixWid), 1, w, h);
	stuffRect(&(privP->sizeRect), privP->fatIRect.h2 - pixWid, privP->fatIRect.v2 - 1,
				5 * pixWid, 5);

/* then get our Window Data Height & Width */
	winDataHeight = privP->sizeRect.v2 + 2;
	winDataWidth = setMaxOf(privP->fatMRect.h2 + (pixWid * 2), privP->iconRect.h2);
/* size the bugger */
	h = setMinOf(winDataHeight, 161 - privP->infoHeight);
	w = setMinOf(setMaxOf(privP->fatMRect.h2 + (2 * pixWid),
				privP->iconRect.h2 + (2 * pixWid)), 306 * pixWid);
	ResizeInfoBar(0, privP->infoHeight, privP->winP);
	SizeWindow(w, h, privP->winP);
	trix.lng = GetDataSize(privP->winP);
	trix.wrd[0] = setMinOf(winDataWidth, 316 * pixWid);
	trix.wrd[1] = setMinOf(winDataHeight, 186);
	SetDataSize(trix.wrd[0], trix.wrd[1], privP->winP);
	MoveWindow(10 * pixWid, 25 + privP->infoHeight, privP->winP);
}

#pragma toolparms 1
#pragma databank 1
/*--------------------------------------
	DrawInfoBarProc - Handles filling the silly info area

	Mark Collins,  5/31/93 17:05:19
*/
void DrawInfoBarProc(GrafPortPtr winP, long infoRefCon, Rect *infoRect)
{
word				h1, h2, v1, v2;
privateDataHndl		privH;
privateDataPtr		privP;
QDIconRecord			*iconP;
Rect				r, r1;
Point				p;

	privH = getPrivate(winP);
	privP = *privH;
	iconP = *privP->editH;
	BlockMove(infoRect, &privP->infoRect, 8L);
	flopRect(infoRect, &toolRect[pixWid], &r);
	FrameRect(&r);
	DrawIcon(*toolIcn[privP->tool & 0x0007], 0, r.h1 + (pixWid * 3), r.v1 + 3);
	GetPenState(&thePen);
	SetPenPat(&patts[privP->maskColor]);
	flopRect(infoRect, &backRect[pixWid], &r);
	PaintRect(&r);
	SetPenPat(&tempPattern);
	SetPenSize(pixWid, 1);
	FrameRect(&r);
	PenNormal();
	SetPenPat(&patts[privP->color]);
	flopRect(infoRect, &foreRect[pixWid], &r1);
	PaintRect(&r1);
	SetPenState(&thePen);
	p.h = r.h2 + 4 * pixWid;
	p.v = r.v1 + 7;
	xyPoint.h = p.h + 60;
	xyPoint.v = p.v;
	MoveTo(p);
	sprintf(tempStr, "W = %u", iconP->iconWidth);
	DrawCString(tempStr);
	p.v += 9;
	MoveTo(p);
	sprintf(tempStr, "H = %u", iconP->iconHeight);
	DrawCString(tempStr);
	flopRect(infoRect, &(privP->iconRect), &r);
	DrawIcon(iconP, 0, r.h1, r.v1);
}
#pragma databank  0
#pragma toolparms 0

void InitFatIcon(privateDataPtr privP)
{
GrafPort				**imageH, **maskH;
word				w, h, err;

	privP->flag = 0x0000;
	privP->imageCache = nil;
	privP->maskCache = nil;

    /* allocate the offscreen pixelmaps: */
	w = privP->fatIRect.h2 - privP->fatIRect.h1 - (pixWid * 4);
	h = privP->fatIRect.v2 - privP->fatIRect.v1 - 4;
	err = CopyUndoIcon(privP);
	CreateOffPort(w, h, &imageH);
	CreateOffPort(w, h, &maskH);
	privP->imageCache = imageH;
	privP->maskCache = maskH;
	DrawFatImage2(privP);
	DrawFatMask2(privP);
}

word InEditorInfo(EventRecord *event)
{
GrafPortPtr			oldP, winP, showP;
word				x, y, iconHt, err, retErr;
QDIconRecord			*iconP;
privateDataHndl		privH;
privateDataPtr		privP;
Point				pt;
Handle				tempHan;
Rect				perry;

	oldP = GetPort();
	winP = (WindowPtr) event->wmTaskData;
	privH = getPrivate(winP);
	privP = *privH;
	iconP = (QDIconRecord *) *privP->editH;
	pt = event->where;

	StartInfoDrawing(&privP->infoRect, winP);
	flopRect(&privP->infoRect, &toolRect[pixWid], &tr);
	MakeGlobalRect(&tr, &trg);
	flopRect(&privP->infoRect, &foreRect[pixWid], &fr);
	MakeGlobalRect(&fr, &frg);
	flopRect(&privP->infoRect, &backRect[pixWid], &br);
	MakeGlobalRect(&br, &brg);
	flopRect(&privP->infoRect, &(privP->iconRect), &ir);
	MakeGlobalRect(&ir, &irg);
	EndInfoDrawing();

	if (PtInRect(&pt, &trg)) {
		InitCursor();
		privP->tool = (sPalette2(privP->tool & 0x0007, 0x11L) | 0x8000);
		StartInfoDrawing(&(privP->infoRect), winP);
		EraseRect(&tr);
		DrawIcon(*toolIcn[privP->tool & 0x0007], 0, tr.h1 + (pixWid * 3), tr.v1 + 3);
		FrameRect(&tr);
		EndInfoDrawing();
		return 0;
	}

	if (PtInRect(&pt, &brg)) {
		if (PtInRect(&pt, &frg)) {
			privP->color = sPalette1(privP->color);
		}
		else {
			privP->maskColor = sPalette1(privP->maskColor);
		}
		GetPenState(&thePen);
		StartInfoDrawing(&(privP->infoRect), winP);
		EraseRect(&br);
		SetPenPat(&patts[privP->maskColor]);
		PaintRect(&br);
		SetPenPat(&patts[0]);
		SetPenSize(pixWid, 1);
		FrameRect(&br);
		SetPenPat(&patts[privP->color]);
		PaintRect(&fr);
		SetPenState(&thePen);
		EndInfoDrawing();
		return 0;
	}

	if (PtInRect(&pt, &irg)) {
		tempHan = loadEdRes(1L, rWindParam1);
		showP = NewWindow2(0L, 0L, 0L, 0L, 1, tempHan, rWindParam1);
		SetPort(showP);
		x = (iconP->iconWidth + 4) * pixWid;
		y = iconP->iconHeight + 2;
		SizeWindow(x * 2, (y * 4) + 1, showP);
		MoveWindow(irg.h1, irg.v1, showP);
		perry.h1 = (x - pixWid) & 0xfffe;
		perry.h2 = perry.h1 * 2;
		if (pixWid == 1)
			perry.h2 += 2;
		perry.v1 = 1;
		perry.v2 = y * 4;
		GetPenPat(&tempPattern);
		SetPenPat(&patts[(pixWid == 2) ? 0xd : 0xb]);
		ShowWindow(showP);
		PaintRect(&perry);
		SetPenPat(&tempPattern);
		x += pixWid;
		DrawIcon(iconP, 0, pixWid, 1);
		DrawIcon(iconP, 1, pixWid, y);
		DrawIcon(iconP, 2, pixWid, y * 2);
		DrawIcon(iconP, 4, pixWid, y * 3);
		DrawIcon(iconP, 0, x, 1);
		DrawIcon(iconP, 1, x, y);
		DrawIcon(iconP, 2, x, y * 2);
		DrawIcon(iconP, 4, x, y * 3);
		while (StillDown(0)) {  }
		SetPort(winP);
		CloseWindow(showP);
		unloadEdRes(tempHan, rWindParam1);
		return 0;
	}
	return 0;
}

word CopyUndoIcon(privateDataPtr privP)
{
long				size;
word				fail;

	fail = 0;
	size = GetHandleSize((Handle) privP->editH);
	if (GetHandleSize((Handle) privP->undoH) < size) {
		HUnlock((Handle) privP->undoH);
		SetHandleSize(size, (Handle) privP->undoH);
		fail = toolerror();
	}
	HandToHand(privP->editH, privP->undoH, size);
	HLock((Handle) privP->undoH);
	return fail;
}

void RedrawFatbits(privateDataPtr privP, word mask)
{
GrafPortPtr			oPort;
Cursor	    			*oCurs;
Rect				r;

	oCurs = GetCursorAdr();
	oPort = GetPort();
	StartDrawing(privP->winP);
	BlockMove(&privP->fatMRect, &r, 8L);
	InsetRect(&r, 2, 1);
	InvalRect(&r);
	DrawFatMask2(privP);
	BlockMove(&privP->fatIRect, &r, 8L);
	InsetRect(&r, 2, 1);
	InvalRect(&r);
	DrawFatImage2(privP);
	updateInfoIcon(privP);
	SetOrigin(0, 0);
	SetPort(oPort);
}

void DisposeSource(GrafPortPtr port)
{
Handle				h;
word				err;

	ClosePort(port);
	h = FindHandle(port->portInfo.ptrToPixImage);
	err = toolerror();
	if (err == 0) {
		DisposeHandle(h);
		err = toolerror();
	}
}

void copyRows(char *p0, char *p1, word cnt, word l0, word l1)
{
word				bytes;

	bytes = setMinOf(l0, l1);
	for (; cnt; cnt--) {
		BlockMove(p0, p1, (long) bytes);
		p0 += l0;
		p1 += l1;
	}
}

void Icon2Pixmap(QDIconRecord *iconP, GrafPortPtr port, word inMask)
{
word				h, p0width, p1width;
char				*p0, *p1;

	p0width = (iconP->iconWidth - 1) / 2 + 1;
	p1width = port->portInfo.width;

	p0 = (char *) &iconP->iconImage;
	p1 = (char *) port->portInfo.ptrToPixImage;
	if (inMask) {
		p0 += iconP->iconSize;
	}
	copyRows(p0, p1, iconP->iconHeight, p0width, p1width);
}

void Pixmap2Icon(GrafPortPtr port, QDIconRecord *iconP, word inMask)
{
word				h, p0width, p1width;
char				*p0, *p1;

	p0width = (iconP->iconWidth - 1) / 2 + 1;
	p1width = port->portInfo.width;
	p0 = (char *) &iconP->iconImage;
	p1 = (char *) port->portInfo.ptrToPixImage;
	if (inMask) {
		p0 += iconP->iconSize;
	}
	copyRows(p1, p0, iconP->iconHeight, p1width, p0width);
}

word GetPixelColor(word x, word y, QDIconRecord *iconP, word inMask)
{
char				*p;
word				color;

	p = (char *) &iconP->iconImage + (iconP->iconWidth * y + x) / 2;
	if (inMask)
	    p += iconP->iconSize;
	asm {       /* so we never have to figure out what this does... */
		lda	x        /* get h pos in row / 2 */
		lsr	a
		lda	[p]      /* get color */
		bcs	useLo    /* br = x ops on odd pixel so use low nibble */
		and	#0x00f0  /*      else use hi nibble */
		pha
		lsr	a
		lsr	a
		lsr	a
		lsr	a
		bra	skip
useLo:	and	#0x000f
		pha
		asl	a
		asl	a
		asl	a
		asl	a
skip:	ora	1,s
		sta 1,s
		xba
		ora 1,s
		plx
		sta	color
		}
	return color;
}

word PickColor(word ox, word oy, privateDataPtr privP, word inMask)
{
word				x, y;

	Pt2Pixel(ox, oy, privP, inMask, &x, &y);
	return GetPixelColor(x, y, *privP->editH, inMask);
}

void Pt2Pixel(word ox, word oy, privateDataPtr privP, word inMask, word *x, word *y)
{
word				h, v;

	h = inMask ? privP->fatMRect.h1 : privP->fatIRect.h1;
	v = inMask ? privP->fatMRect.v1 : privP->fatIRect.v1;
	*x = (ox - h - 4) / (4 * pixWid);
	*y = (oy - v - 2) / 4;
}

void FillIcon(privateDataPtr privP, Point pt, word inMask)
{
GrafPort				**tpH, *tempPort, *oPort;
Pointer				temp;
QDIconRecord			**iconH;
Cursor				*oCurs;
word				leakTable[2];
word				x, y, err, h, v;
Rect				r;

	tpH = (GrafPort **) NewHandle(sizeof(GrafPort), fUserID, 0x0018, 0L);
	tempPort = *tpH;
	temp = memset((char *) tempPort, 0x00, (size_t) sizeof(GrafPort));

	oCurs = GetCursorAdr();
	oPort = GetPort();
	CopyUndoIcon(privP);
	iconH = privP->editH;
	leakTable[0] = 1;
	leakTable[1] = PickColor(pt.h, pt.v, privP, inMask);
	Pt2Pixel(pt.h, pt.v, privP, inMask, (word *) &x, (word *) &y);
	err = FillSource(tempPort, iconH);
	if (err == 0) {	
/* make sure the extra space in the background is _not_ the leak color: */
		FillRect(&tempPort->portRect, &patts[leakTable[1]]);
		err = toolerror();
		Icon2Pixmap(*iconH, tempPort, inMask);  /* copy icon image into the offscreen pixelmap */
		SeedFill(&tempPort->portInfo, &tempPort->portRect, &tempPort->portInfo,
			&tempPort->portRect, x * 2, y, pixWid ? 1001 : 1002,
			&patts[inMask ? privP->maskColor : privP->color], &leakTable);
		err = toolerror();
		Pixmap2Icon(tempPort, *iconH, inMask);
		DisposeSource(tempPort);
		DisposeHandle((Handle) tpH);
		SetPort(oPort);

		if (inMask) {
			BlockMove(&privP->fatMRect, &r, 8L);
			InsetRect(&r, 2, 1);
			InvalRect(&r);
			DrawFatMask2(privP);
		}
		else {
			BlockMove(&privP->fatIRect, &r, 8L);
			InsetRect(&r, 2, 1);
			InvalRect(&r);
			DrawFatImage2(privP);
		}
		privP->flag &= 0x0001;
	}
	else
		SetPort(oPort);
}

word FillSource(GrafPortPtr tempPort, QDIconRecord **iconH)
{
word				w, h, rowBytes, err;
LocInfo				portInfo;
Handle				tHand;

	w = (**iconH).iconWidth;
	h = (**iconH).iconHeight;
	w = (w * 2 + 7) & 0xfff8;
	rowBytes = (w / 4 + 7) & 0xfff8;

	portInfo.boundsRect.h1 = 0;
	portInfo.boundsRect.h2 = (rowBytes * 4);
	portInfo.boundsRect.v1 = 0;
	portInfo.boundsRect.v2 = h;
	portInfo.width = rowBytes;
	tHand = NewHandle((long) (h * (rowBytes * 4)), fUserID, 0x8018, 0L);
	err = toolerror();
	portInfo.ptrToPixImage = *tHand;
	if (err == 0) {
		OpenPort(tempPort);
		err = toolerror();
		portInfo.portSCB = GetMasterSCB();
		SetPortLoc(&portInfo);
		err = toolerror();
		SetPortRect(&portInfo.boundsRect);
		err = toolerror();
		EraseRect(&portInfo.boundsRect);
		err = toolerror();
		}
	return err;
}

void MakeMask(privateDataPtr privP)
{
GrafPortPtr			oPort;
char				iHi, iLo, mHi, mLo, *iPtr, *mPtr, hiColor, loColor;
word				i, iSize, err;
QDIconRecord			*iconP, **iconH;
Cursor				*oCurs;
Rect				r;

	oCurs = GetCursorAdr();
	oPort = GetPort();
	err = CopyUndoIcon(privP);
	iconH = privP->editH;
	iconP = *iconH;
	iSize = iconP->iconSize;
	iPtr = &(iconP->iconImage[0]);
	mPtr = iPtr + iSize;
	hiColor = privP->maskColor << 4;
	loColor = privP->maskColor;
	for (i = 0; i < iSize; i++) {
		iHi = *iPtr & 0xf0;
		if (iHi == 0xf0) {
			mHi = 0;
		}
		else {
			mHi = hiColor;
		}
		iLo = *iPtr & 0x0f;
		if (iLo == 0x0f) {
			mLo = 0;
		}
		else {
			mLo = loColor;
		}
		*mPtr = mHi + mLo;
		iPtr++;
		mPtr++;
	}
	BlockMove(&privP->fatMRect, &r, 8L);
	InsetRect(&r, 2, 1);
	InvalRect(&r);
	DrawFatMask2(privP);
	updateInfoIcon(privP);
}

void ShiftDraw2(word x, word y, GrafPortPtr image)
{
	x += DestX + 4;
	y = (y & 0xfffc) + DestY + 2;
	PPToPort(&image->portInfo, &image->portRect, x, y, notXOR);
}

#pragma databank  0
#pragma toolparms 0

void ShiftIt(privateDataPtr privP, integer deltaX, integer deltaY)
{
word				iSize, iHeight, iWidth, iWBytes;
integer				sLine, dLine;
QDIconRecord			*iconP;
char				*ptr0, *ptr1, *ptr2, *ptr3;

	iconP = *privP->editH;
	iSize = iconP->iconSize;
	iHeight = iconP->iconHeight;
	iWidth = iconP->iconWidth;
	iWBytes = (iWidth - 1) / 2 + 1;
/* move each line, shifting it into place: */
	if (deltaY < 0) {
		dLine = 0;
		sLine = -deltaY;
		if (sLine >= iHeight)
			return;
	}
	else {
		dLine = iHeight - 1;
		sLine = dLine - deltaY;
		if (sLine < 0)
			return;
	}
	do {
		ptr0 = (char *) &iconP->iconImage + (sLine * (iWidth / 2));
		ptr2 = ptr0 + iSize;
		ptr1 = (char *) &iconP->iconImage + (dLine * (iWidth / 2));
		ptr3 = ptr1 + iSize;
		asm {
			ldx	sLine
			bmi	clrRow
			cpx	iHeight
			bcs	clrRow
			lda	deltaX		/* first shift the row horizontally */
			beq	noShift
			bpl	goRight
			eor	#0xffff
			pha
			tax
			sep	#0x20
shlLoop1:	ldy	iWBytes
			dey
			sec
loop1:		lda	[ptr0],y
			rol	a
			sta	[ptr0],y
			dey
			bpl	loop1
			dex
			bne	shlLoop1
			plx				/* shift the mask left X bits */
shlLoop2:	ldy	iWBytes
			dey
			clc
loop2:		lda	[ptr2],y
			rol	a
			sta	[ptr2],y
			dey
			bpl	loop2
			dex
			bne	shlLoop2
			bra	noShift
goRight:		ldx	deltaX		/* shift the image right X bits */
			sep	#0x20
shrLoop1:	phx
			ldy	#0
			ldx	iWBytes
			sec
loop3:		lda	[ptr0],y
			ror	a
			sta	[ptr0],y
			iny
			dex
			bne	loop3
			plx
			dex
			bne	shrLoop1
			ldx	deltaX		/* shift the mask right X bits */
shrLoop2:	phx
			ldy	#0
			ldx	iWBytes
			clc
loop4:		lda	[ptr2],y
			ror	a
			sta	[ptr2],y
			iny
			dex
			bne	loop4
			plx
			dex
			bne	shrLoop2
			bra	noShift
clrRow:		sep	#0x20
			ldy	iWBytes		/* clear remaining rows */
			dey
			ldx	#0xffff
clrLoop:	txa
			sta	[ptr1],y
			inc	a
			sta	[ptr3],y
			dey
			bpl	clrLoop
			bra	cleared
noShift:	sep	#0x20
			ldy	iWBytes		/* now copy the newly shifted row into new place */
			dey
cLoop:		lda	[ptr0],y
			sta	[ptr1],y
			lda	[ptr2],y
			sta	[ptr3],y
			dey
			bpl	cLoop
cleared:	rep	#0x20
		}
	} while (deltaY < 0 ? (++sLine, ++dLine < iHeight) : (--sLine, --dLine >= 0));
}

void ShiftIcon(privateDataPtr privP, Point pt)
{
Rect		dragRect, r;
Region		**oClip;
GrafPort		**image;
long		result;
integer		deltaX, deltaY;

	dragRect = r = privP->fatIRect;
	DestX = r.h1;
	DestY = r.v1;
	image = privP->imageCache;
	HLock((Handle) image);
	TheImage = *image;
	InsetRect(&r, r.h1 - r.h2, r.v1 - r.v2);
	InsetRect(&dragRect, 2, 2);
	oClip = NewRgn();				/* clip to the drag rect */
	GetClip(oClip);
	ClipRect(&dragRect);
	EraseRect(&dragRect);			/* erase the image first */
	result = DragRect(ShiftDraw, patts[12], pt, &dragRect, &r, &r, 0x0888);
	asm {
		lda	result
		sta	deltaY
		lda	result+2
		sta	deltaX
	}
	ShiftDraw2(deltaX, deltaY, TheImage);	/* redraw the icon image */
	HUnlock((Handle) image);
	SetClip(oClip);					/* restore the original clip rgn */
	deltaX = deltaX >= 0 ? deltaX / 2 : deltaX / 2 - 1;
	deltaY = deltaY >= 0 ? deltaY / 4 : deltaY / 4 - 1;
	if (deltaX != 0 || deltaY != 0) {
		CopyUndoIcon(privP);
		ShiftIt(privP, deltaX, deltaY);
		privP->flag = 0x0001;
		RedrawFatbits(privP, true);
		DrawFatImage2(privP);
	}
}

void UpdateColor(privateDataPtr privP)
{
Rect    r;

	StartInfoDrawing(&privP->infoRect, privP->winP);
	GetPenPat(&tempPattern);
	SetPenPat(&patts[privP->maskColor]);
	flopRect(&privP->infoRect, &backRect[pixWid], &r);
	PaintRect(&r);
	SetPenPat(&patts[privP->color]);
	flopRect(&privP->infoRect, &foreRect[pixWid], &r);
	PaintRect(&r);
	SetPenPat(&tempPattern);
	flopRect(&privP->infoRect, &backRect[pixWid], &r);
	SetPenSize(pixWid, 1);
	FrameRect(&r);
	PenNormal();
	EndInfoDrawing();
}

void GetPixelRect(word x, word y, Rect *r)
{
	r->h1 = x * (pixWid * 4);
	r->h2 = r->h1 + (pixWid * 3);
	r->v1 = y * 4;
	r->v2 = r->v1 + 3;
}

void DoBit(word ox, word oy, word color, word inMask, privateDataPtr privP)
{
GrafPort					*oPort, **cacheH;
QDIconRecord				*iconP;
word					x, y;
Rect					*baseRect, r;

	iconP = *(privP->editH);
	baseRect = inMask ? &privP->fatMRect : &privP->fatIRect;

	GetPix(ox, oy, &x, &y, inMask, privP);

	if (x == 0xffff)
		return;

	if (x == OldX && y == OldY)
		return;

	OldX = x;
	OldY = y;

	GetPixelRect(x, y, &r);

	oPort = GetPort();			/* update the cache */
	cacheH = inMask ? privP->maskCache : privP->imageCache;
	HLock((Handle) cacheH);
	SetPort(*cacheH);
	FillRect(&r, &patts[color & 0xf]);
	SetPort(oPort);
	HUnlock((Handle) cacheH);

/* update the fatbits window: */
	OffsetRect(&r, (inMask ? privP->fatMRect.h1 : privP->fatIRect.h1) + (2 * pixWid),
	    privP->fatIRect.v1 + 2);
	FillRect(&r, &patts[color & 0xf]);
/* update the icon itself: */
	PutColor2(x, y, color, privP, inMask);
}

word ResizeIt(privateDataPtr privP, word newWd, word newHt)
{
QDIconRecord				**iconH, *iconP, **tempIconH, *tempIconP;
char					*p0, *p1, *p2, *p3;
long					hSize;
word					newSize, oldSize, oldWd, oldHt, x, y, err;

	iconH = privP->editH;
	hSize = GetHandleSize(iconH);
	tempIconH = (QDIconRecord **) NewHandle(hSize, fUserID, 0x8018, 0L);
	HandToHand((Handle) iconH, (Handle) tempIconH, hSize);
	tempIconP = *tempIconH;
	newSize = (newWd / 2) * newHt;
	HUnlock((Handle) iconH);
	SetHandleSize((long) newSize * 2 + sizeof(Word) * 4, (Handle) iconH);
	HLock((Handle) iconH);
	iconP = *iconH;
/* put in new size info for icon (saving old): */
	oldSize = iconP->iconSize;
	oldHt = iconP->iconHeight;
	oldWd = iconP->iconWidth;

	iconP->iconSize = newSize;
	iconP->iconHeight = newHt;
	iconP->iconWidth = newWd;

	p3 = (char *) &iconP->iconImage;
	p3 = memset(p3, 0xff, (size_t) newSize);
	p3 += newSize;
	p3 = memset(p3, 0x00, (size_t) newSize);

/* copy resized image back in: */
	y = setMinOf(newHt, oldHt);
	x = setMinOf(newWd, oldWd) / 2;
	p0 = (char *) &tempIconP->iconImage;
	p1 = (char *) &iconP->iconImage;
	p2 = p0 + oldSize;
	p3 = p1 + newSize;
	for(; y; y--) {
		BlockMove(p0, p1, (long) x);
		BlockMove(p2, p3, (long) x);
		p0 += oldWd / 2;
		p1 += newWd / 2;
		p2 += oldWd / 2;
		p3 += newWd / 2;
	}
	DisposeHandle((Handle) tempIconH);
	return 0;
}

void GrowFat(privateDataPtr privP, Point pt)
{
GrafPortPtr				oPort;
QDIconRecord				*iconP, **iconH;
Rect					limits, slop;
long					newSize;
word					newHt, newWd, h, v, err;

	h = privP->fatIRect.h1 - privP->fatIRect.h2 + 4;
	v = privP->fatIRect.v1 - privP->fatIRect.v2;

	limits.h1 = (16 * pixWid) + h;
	limits.v1 = 18 + v;                 /* (4 * 4) + 2 + v */
	limits.h2 = (1280 * pixWid) + h;
	limits.v2 = 402 + v;                /* 4 * 100 + 2 + v */
/* use the window manager's portRect for the slop rect: */
	oPort = GetPort();
	SetPort(GetWMgrPort());
	GetPortRect(&slop);
	SetPort(oPort);
/* interact: */
	newSize = DragRect(0L, patts[12], pt, &privP->fatIRect, &limits, &slop, 0x0014);
	asm {
		lda	newSize
		sta	newHt
		lda	newSize+2
		sta	newWd
	}
	newHt = (newHt + privP->fatIRect.v2 - privP->fatIRect.v1 - 2) / 4;
	newWd = (((newWd + privP->fatIRect.h2 - privP->fatIRect.h1 - 4) / (4 * pixWid))
            + 1) & 0xfffe;

	if (privP->resType == rCursor)
		newWd = ((newWd + 2) / 4) * 4;
	iconH = privP->editH;
	iconP = *iconH;
	if (newHt != iconP->iconHeight || newWd != iconP->iconWidth) {
		CopyUndoIcon(privP);
		err = ResizeIt(privP, newWd, newHt);
		SetWindowSize(privP);
		RedrawFat(privP);
	}
}

void FatClick(EventRecord *event)
{
privateDataHndl			privH;
privateDataPtr			privP;
GrafPortPtr				winP, oPort;
Point					pt;
word					x, y, color, tool, inImage, inMask;

	oPort = GetPort();
	winP = (GrafPortPtr) event->wmTaskData;
	privH = getPrivate(winP);
	privP = *privH;
	tool = privP->tool & 0x0007;
	pt.h = event->where.h;
	pt.v = event->where.v;

	StartDrawing(winP);
	GlobalToLocal(&pt);
	inImage = PtInRect(&pt, &privP->fatIRect);
	inMask = PtInRect(&pt, &privP->fatMRect);
    GetPix(pt.h, pt.v, &x, &y, inMask, privP);

	if (inImage || inMask) {
		switch (tool) {
			case PickerTool:						/* pick color */
				color = PickColor2(x, y, privP, inMask);
				privP->color = inImage ? color : privP->color;
				privP->maskColor = inMask ? color : privP->maskColor;
				UpdateColor(privP);
				break;

			case BucketTool:						/* fill */
				CopyUndoIcon(privP);
				FillIcon(privP, pt, inMask);
				privP->flag = 0x0001;
				updateInfoIcon(privP);
				break;

			case ShifterTool:						/* shift */
				CopyUndoIcon(privP);
				ShiftIcon(privP, pt);
				privP->flag = 0x0001;
				break;

			case PencilTool:						/* draw */
				CopyUndoIcon(privP);
				OldX = OldY = -1;     /* image support */
				color = GetColor(inMask ? privP->maskColor : privP->color, x, y, privP, inMask);
				do {
					DoBit(pt.h, pt.v, color, inMask, privP);
					GetMouse(&pt);
				} while (StillDown(0));
				privP->flag = 0x0001;
				updateInfoIcon(privP);
				break;
			}
	}
	else if (PtInRect(&pt, &privP->sizeRect)) {
		GrowFat(privP, pt);
		privP->flag = 0x0001;
	}
	SetOrigin(0, 0);
	SetPort(oPort);
}

void RedrawFat2(privateDataPtr privP)
{
word					width, height;

	width = privP->fatIRect.h2 - privP->fatIRect.h1 - (4 * pixWid);
	height = privP->fatIRect.v2 - privP->fatIRect.v1 - 4;
	AdjustOffPort(privP->imageCache, width, height);
	AdjustOffPort(privP->maskCache, width, height);
	DrawFatImage2(privP);
	DrawFatMask2(privP);
}

void RedrawFat(privateDataPtr privP)
{
Rect					r;

	GetPortRect(&r);
	InvalRect(&r);
	EraseRect(&r);
	RedrawFat2(privP);
}

word GetColor(word color, word x, word y, privateDataPtr privP, word inMask)
{
word					curColor, oldColor;

	curColor = PickColor2(x, y, privP, inMask);
	oldColor = PickOldColor2(x, y, privP, inMask);
	return (color == curColor) ? oldColor : color;
}

#pragma databank	1
#pragma toolparms	1
void ShiftDraw(word deltaY, word deltaX, word parm)
{
word					L00C0, L60B4, x, y;

	x = L00C0;
	if (parm & 1)
		++x;
	L60B4 = x & 1;
	if (parm & 1)
		if ((L00C0 & 1) != L60B4) {
			++L00C0;
			ShiftDraw2(deltaX, deltaY, TheImage);
		}
}

void PaintImage(GrafPort **src, word x, word y)
{
	HLock((Handle) src);
	PPToPort(&(**src).portInfo, &(**src).portRect, x, y, modeCopy);
	HUnlock((Handle) src);
}

void DrawEditor(void)
{
privateDataHndl			privH;
privateDataPtr			privP;
QDIconRecord				**iconH, *iconP;
WindowPtr				wp;

	wp = GetPort();
	privH = getPrivate(wp);
	privP = *privH;
	iconH = privP->editH;
	SetPenSize(2, 1);
/* draw the fat icon image: */
	PaintImage(privP->imageCache, privP->fatIRect.h1 + 4, privP->fatIRect.v1 + 2);
/* draw the fat icon mask: */
	PaintImage(privP->maskCache, privP->fatMRect.h1 + 4, privP->fatMRect.v1 + 2);
	FrameRect(&privP->fatIRect);
	FrameRect(&privP->fatMRect);
	FrameRect(&privP->sizeRect);
	PenNormal();
}
#pragma databank	0
#pragma toolparms	0

void flopRect(Rect *infoRect, Rect *inR, Rect *outR)
{
    outR->h1 = infoRect->h1 + inR->h1;
    outR->v1 = infoRect->v1 + inR->v1;
    outR->h2 = infoRect->h1 + inR->h2;
    outR->v2 = infoRect->v1 + inR->v2;
}

void GetPix(word h0, word v0, word *h1, word *v1, word inMask, privateDataPtr privP)
{
word					wd, ht;
Rect					*baseRect;
QDIconRecord				**iconH, *iconP;

	iconH = (QDIconRecord **) privP->editH;
	iconP = *iconH;
	wd = iconP->iconWidth;
	ht = iconP->iconHeight;
	baseRect = inMask ? &privP->fatMRect : &privP->fatIRect;
	*h1 = ((h0 - baseRect->h1) - pixWid) / (4 * pixWid);
	*v1 = ((v0 - baseRect->v1) - 2) / 4;
	if ((*h1 >= wd) || (*v1 >= ht)) {
		*h1 = 0xffff;
	}
}

/* PutPix translates the fatbit coordinates into a global location.  It then
    draws a pixel rect in the appropriate fatbits rect. If the Fatbit
    coordinate is -1,-1, it returns doing nothing.  */
void PutPix(word h0, word v0, word inMask, privateDataPtr privP)
{
word				wd, ht, color;
Rect				*baseRect, pixRect;
QDIconRecord			**iconH, *iconP;

	if (h0 != 0xffff) {
		baseRect = inMask ? &privP->fatMRect : &privP->fatIRect;
		color = inMask ? privP->maskColor : privP->color;
		stuffRect(&pixRect, baseRect->h1 + (h0 * (pixWid * 4)) + pixWid,
					baseRect->v1 + (v0 * 4) + 1, pixWid  * 4, 4);
		FillRect(&pixRect, &patts[color]);
    }
}

void drawCoords(privateDataPtr privP, word h0, word v0, word inMask)
{
word				h1, v1;
Point				p;
GrafPortPtr			oldP;

	oldP = GetPort();
	SetPort(privP->winP);
	GetPix(h0, v0, &h1, &v1, inMask, privP);
	SetPort(oldP);

	if (h1 != 0xffff) {
		StartInfoDrawing(&privP->infoRect, privP->winP);
		MoveTo(xyPoint);
		sprintf(tempStr, "x = %0.2u", h1);
		DrawCString(tempStr);
		p.v = xyPoint.v + 9;
		p.h = xyPoint.h;
		MoveTo(p);
		sprintf(tempStr, "y = %0.2u", v1);
		DrawCString(tempStr);
		EndInfoDrawing();
	}
}

void updateInfoIcon(privateDataPtr privP)
{
Rect				r;

	StartInfoDrawing(&privP->infoRect, privP->winP);
	flopRect(&privP->infoRect, &(privP->iconRect), &r);
	EraseRect(&r);
	DrawIcon(*(privP->editH), 0, r.h1, r.v1);
	EndInfoDrawing();
}

word PickColor2(word x, word y, privateDataPtr privP, word inMask)
{
Byte				*p;
QDIconRecord	    **iconH, *iconP;

	if (x == 0xffff)
	    return (inMask ? privP->maskColor : privP->color);

    iconH = (QDIconRecord **) privP->editH;
	iconP = *iconH;

    p = &(iconP->iconImage[0]);

    if (inMask)
	    p += iconP->iconSize;

	p += (y * (iconP->iconWidth - 1) / 2 + 1) + (x / 2);

	return (word) (x & 0x1) ? *p & 0x0f : *p >> 4;

}

word PickColor3(word x, word y, Byte *p)
{

    p = &(iconP->iconImage[0]);

    if (inMask)
	    p += iconP->iconSize;

	p += (y * (iconP->iconWidth - 1) / 2 + 1) + (x / 2);

	return (word) (x & 0x1) ? *p & 0x0f : *p >> 4;

}



word PickOldColor2(word x, word y, privateDataPtr privP, word inMask)
{
word					w, temp;
char					*p;
QDIconRecord				**iconH, *iconP;

	temp = inMask ? privP->maskColor : privP->color;
	iconH = privP->undoH;
	iconP = *iconH;

	if (x != 0xffff) {
		p = (char *) &(iconP->iconImage[0]);
		if (inMask)
			p += iconP->iconSize;
		w = (iconP->iconWidth - 1) / 2 + 1;
		p += (y * w) + (x / 2);
		temp = *p;
		if (!(x & 0x1))
			temp >>= 4;
		temp &= 0x0f;
	}
	return temp;
}

void PutColor2(word x, word y, word color, privateDataPtr privP, word inMask)
{
word					w;
char					*p;
QDIconRecord				**iconH, *iconP;

	iconH = (QDIconRecord **) privP->editH;
	iconP = *iconH;

	if (x != 0xffff) {
		p = (char *) &(iconP->iconImage[0]);
		if (inMask)
			p += iconP->iconSize;

		w = (iconP->iconWidth - 1) / 2 + 1;
		p += (y * w) + (x / 2);

		if (!(x & 0x1)) {
			*p &= 0x0f;
			*p += color << 4;
		}
		else {
			*p &= 0xf0;
			*p += color;
		}
	}
}

void flipIcon(privateDataPtr privP)
{
word				i, j, icnHt, err;
QDIconRecord			**iconH, *iconP;
long				sizeH, rowBytes;
char				*i0, *i1, *m0, *m1, *tempIconPtr, *tempMaskPtr;
Handle				tempIcon;
Rect				r;

	err = CopyUndoIcon(privP);
	iconH = privP->editH;
	iconP = *iconH;
	rowBytes = (iconP->iconWidth - 1) / 2 + 1;
	sizeH = iconP->iconSize * 2;
	tempIcon = NewHandle(sizeH, fUserID, 0x8018, 0L);
	tempIconPtr = *tempIcon;
	tempMaskPtr = tempIconPtr + iconP->iconSize;

	i0 = &(iconP->iconImage[0]);
	m0 = i0 + iconP->iconSize;

	j = iconP->iconHeight - 1;
	for (i = 0; i < iconP->iconHeight; i++) {
		i1 = tempIconPtr + (rowBytes * j);
		m1 = tempMaskPtr + (rowBytes * j);
		BlockMove(i0, i1, rowBytes);
		BlockMove(m0, m1, rowBytes);
		i0 += rowBytes;
		m0 += rowBytes;
		j--;
	}
	BlockMove(tempIconPtr, &(iconP->iconImage[0]), sizeH);
	BlockMove(&privP->fatMRect, &r, 8L);
	InsetRect(&r, 2, 1);
	InvalRect(&r);
	DrawFatMask2(privP);
	BlockMove(&privP->fatIRect, &r, 8L);
	InsetRect(&r, 2, 1);
	InvalRect(&r);
	DrawFatImage2(privP);
	updateInfoIcon(privP);
	DisposeHandle(tempIcon);
}

void flipHorizIcon(privateDataPtr privP)
{
word				err, totHt, i;
QDIconRecord			**iconH, *iconP;
long				rowBytes;
char				i0hi, i0lo, i1hi, i1lo, *i0, *i1, *baseP;
Rect				r;

	err = CopyUndoIcon(privP);
	iconH = privP->editH;
	iconP = *iconH;
	rowBytes = (iconP->iconWidth - 1) / 2 + 1;
	totHt = iconP->iconHeight * 2;
	baseP = &(iconP->iconImage[0]);

	for (i = 0; i < totHt; i++) {
		i0 = baseP + (i * rowBytes);
		i1 = i0 + (rowBytes - 1);
		while (i0 < i1) {
			i0hi = (*i0 & 0xf0) >> 4;
			i0lo = (*i0 & 0x0f) << 4;
			i1hi = (*i1 & 0xf0) >> 4;
			i1lo = (*i1 & 0x0f) << 4;
			*i0 = i1hi + i1lo;
			*i1 = i0hi + i0lo;
			i0++;
			i1--;
		}
	}
	BlockMove(&privP->fatMRect, &r, 8L);
	InsetRect(&r, 2, 1);
	InvalRect(&r);
	DrawFatMask2(privP);
	BlockMove(&privP->fatIRect, &r, 8L);
	InsetRect(&r, 2, 1);
	InvalRect(&r);
	DrawFatImage2(privP);
	updateInfoIcon(privP);
}

void fillMask(privateDataPtr privP)
{
word				err, tempColor;
QDIconRecord			*iconP;
char				*temp0, *temp1;
Rect				r;

	err = CopyUndoIcon(privP);
	iconP = *(privP->editH);
	temp0 = &(iconP->iconImage[0]) + iconP->iconSize;
	tempColor = privP->maskColor + (privP->maskColor << 4);
	temp1 = memset(temp0, tempColor, (size_t) iconP->iconSize);
	BlockMove(&privP->fatMRect, &r, 8L);
	InsetRect(&r, 2, 1);
	InvalRect(&r);
	DrawFatMask2(privP);
	updateInfoIcon(privP);
}

void fillImage(privateDataPtr privP)
{
word					err, tempColor;
QDIconRecord				*iconP;
char					*temp0, *temp1;
Rect					r;

	err = CopyUndoIcon(privP);
	iconP = *(privP->editH);
	temp0 = &(iconP->iconImage[0]);
	tempColor = privP->color + (privP->color << 4);
	temp1 = memset(temp0, tempColor, (size_t) iconP->iconSize);
	BlockMove(&privP->fatIRect, &r, 8L);
	InsetRect(&r, 2, 1);
	InvalRect(&r);
	DrawFatImage2(privP);
	updateInfoIcon(privP);
}

void doClear(privateDataPtr privP)
{
word            err, tempColor;
QDIconRecord    *iconP;
char            *temp0, *temp1;
Rect            r;

	err = CopyUndoIcon(privP);
	iconP = *(privP->editH);
	temp0 = &(iconP->iconImage[0]);
	temp1 = memset(temp0, 0xff, (size_t) iconP->iconSize);
	temp0 += iconP->iconSize;
	temp1 = memset(temp0, 0x00, (size_t) iconP->iconSize);
	BlockMove(&privP->fatIRect, &r, 8L);
	InsetRect(&r, 2, 1);
	InvalRect(&r);
	DrawFatImage2(privP);
	BlockMove(&privP->fatMRect, &r, 8L);
	InsetRect(&r, 2, 1);
	InvalRect(&r);
	DrawFatMask2(privP);
	updateInfoIcon(privP);
}

void copyIconToMask(privateDataPtr privP)
{
word					err, i, iSize;
QDIconRecord				*iconP;
char					*temp0, *temp1, temp;
Rect					r;

	err = CopyUndoIcon(privP);
	iconP = *(privP->editH);
	temp0 = &(iconP->iconImage[0]);
	iSize = iconP->iconSize;
	temp1 = temp0 + iSize;
	BlockMove(temp0, temp1, (long) iSize);
	for (i = 0; i < iSize; i++) {
		*temp1 ^= 0xff;
		temp1++;
	}
	BlockMove(&privP->fatMRect, &r, 8L);
	InsetRect(&r, 2, 1);
	InvalRect(&r);
	DrawFatMask2(privP);
	updateInfoIcon(privP);
}

void doUndo(privateDataPtr privP)
{
long					sizeH, undoSize;
Handle					tempHndl;
word					err;
QDIconRecord				*iconP;
char					*temp0, *temp1;
Rect					r;

	sizeH = GetHandleSize((Handle) privP->editH);
	tempHndl = NewHandle(sizeH, fUserID, 0x0018, 0L);
	HandToHand(privP->editH, tempHndl, sizeH);
	undoSize = GetHandleSize((Handle) privP->undoH);

	if (undoSize > sizeH) {
		HUnlock((Handle) privP->editH);
		SetHandleSize(undoSize, (Handle) privP->editH);
		err = toolerror();
		HLock((Handle) privP->editH);
	}
	HandToHand(privP->undoH, privP->editH, undoSize);
	if (sizeH > undoSize) {
		HUnlock((Handle) privP->undoH);
		SetHandleSize(sizeH, (Handle) privP->undoH);
		err = toolerror();
		HLock((Handle) privP->undoH);
	}
	HandToHand(tempHndl, privP->undoH, sizeH);
	SetWindowSize(privP);
	RedrawFat(privP);
	updateInfoIcon(privP);
}

Handle GetFileIcon(void)
{
fileIconArrayHndl		arrayHndl;
word				i, count, tempSize, repRecSize, maxWd, maxHt, iWd, iHt;
fileIconDataPtr		theFile;
long				hSize;
QDIconRecord			*tempPtr;
char				*bPtr;
Handle				promptHan, retHndl, fHndl;

/* first load in our icon file - 0L = no file loaded */
	fHndl = loadIconFileData();
	if (fHndl) {	/* if nothing here- go away */
/* prepare an array for stuffing- 255 members max for now */
		arrayHndl = (fileIconArrayHndl) NewHandle(2550L, fUserID, 0x8018, 0L);
		arrayPtr = *arrayHndl;
		bPtr = *fHndl;
		bPtr += 26;
		theFile = (fileIconDataPtr) bPtr;
		i = 0;
		maxWd = 0;
		maxHt = 0;

		while (theFile->dataLength) {
			repRecSize = theFile->dataLength;
			tempPtr = (QDIconRecord *) &(theFile->largeIcon);
			iWd = tempPtr->iconWidth;
			if ((iWd > 2) && (iWd < 321)) {
				arrayPtr->icn[i].icnPtr = tempPtr;
				arrayPtr->icn[i].width = iWd;
				iHt = tempPtr->iconHeight;
				arrayPtr->icn[i].height = iHt;
				maxWd = setMaxOf(maxWd, iWd);
				maxHt = setMaxOf(maxHt, iHt);
				tempSize = (tempPtr->iconSize * 2) + 8;
				arrayPtr->icn[i].size = tempSize;
				i++;
			}
			bPtr = ((char *) tempPtr);
			bPtr += tempSize;
			tempPtr = (QDIconRecord *) bPtr;
			iWd = tempPtr->iconWidth;
			if ((iWd > 2) && (iWd < 321)) {
				arrayPtr->icn[i].icnPtr = tempPtr;
				iWd = tempPtr->iconWidth;
				arrayPtr->icn[i].width = iWd;
				iHt = tempPtr->iconHeight;
				arrayPtr->icn[i].height = iHt;
				arrayPtr->icn[i].size = (tempPtr->iconSize * 2) + 8;
				maxWd = setMaxOf(maxWd, iWd);
				maxHt = setMaxOf(maxHt, iHt);
				arrayPtr->icn[i].size = (tempPtr->iconSize * 2) + 8;
				i++;
			}
			bPtr = (char *) theFile;
			bPtr += repRecSize;
			theFile = (fileIconDataPtr) bPtr;
		}
		arrayPtr->maxWidth = maxWd;
		arrayPtr->maxHeight = maxHt;
		arrayPtr->count = i;
		retHndl = GetIcon(arrayHndl);
		DisposeHandle(arrayHndl);
		DisposeHandle(fHndl);
		return retHndl;
	}
	return 0L;
}

Handle GetIcon(fileIconArrayHndl arrayHndl)
{
word				imageWidth, imageHeight, hCnt, i, tick, v, h, blockWd;
word				blockHt, err;
long				retVal;
Handle				dispWinTempH, tempHand;
Pointer				tempPtr, butnPtr;
GrafPortPtr			dispP, oldP;
IconButtonTemplate		theButton, **butnHndl;
morph				trix;


	imageWidth = 313 * pixWid;
	blockWd = arrayPtr->maxWidth * pixWid;
	blockHt = arrayPtr->maxHeight;
	hCnt = (imageWidth - 36)/ blockWd;
	imageHeight = ((arrayPtr->count / hCnt) + 1) * blockHt;
	dispWinTempH = loadEdRes(0x20L, rWindParam1);
	dispP = NewWindow2(0L, 0L, 0L, 0L, 1, dispWinTempH, rWindParam1);
	err = toolerror();
	SizeWindow((pixWid == 2) ? 630 : 315, 180, dispP);
	err = toolerror();
	trix.lng = GetDataSize(dispP);
	trix.wrd[0] = (pixWid == 2) ? 630 : 315;
	trix.wrd[1] = setMaxOf(trix.wrd[1], imageHeight);
	SetDataSize(trix.wrd[0], trix.wrd[1], dispP);
	oldP = GetPort();
	SetPort(dispP);
	tick = 0;
	v = 8;
	h = 12 * pixWid;
	for (i = 0; i < arrayPtr->count; i++) {
		butnHndl = (IconButtonTemplate **) NewHandle(sizeof(IconButtonTemplate), fUserID, 0x8018, 0L);
		theButton = **butnHndl;
		theButton.ctlTemplate.pCount = 7;
		theButton.ctlTemplate.ID = (long) i + 1;
		theButton.ctlTemplate.rect.h1 = h;
		theButton.ctlTemplate.rect.h2 = h + arrayPtr->icn[i].width;
		theButton.ctlTemplate.rect.v1 = v;
		theButton.ctlTemplate.rect.v2 = v + arrayPtr->icn[i].height;
		theButton.ctlTemplate.procRef = 0x07ff0001;
		theButton.ctlTemplate.flag = 6;
		theButton.ctlTemplate.moreFlags = 0x1000;
		theButton.ctlTemplate.refCon = 0L;
		theButton.iconRef = (Ref) arrayPtr->icn[i].icnPtr;
		button[i] = (Handle)NewControl2(dispP, 0, &theButton);
		h += blockWd;
		tick++;
		if (tick == hCnt) {
			h = 12 * pixWid;
			v += blockHt;
			tick = 0;
		}
	}
	do {
		retVal = DoModalWindow(&theEvent, 0L, 0L, 0L, 0x8010);
	} while (retVal == 0L);
/* prepare a copy of the selected icon for return */
	i = (retVal & 0xffff) - 1;
	retVal = (long) arrayPtr->icn[i].size;
	tempHand = NewHandle(retVal, fUserID, 0x8018, 0L);
	tempPtr = *tempHand;
	BlockMove(arrayPtr->icn[i].icnPtr, tempPtr, retVal);

/* now clean up our mess */
	SetPort(oldP);
	CloseWindow(dispP);
	unloadEdRes(dispWinTempH, rWindParam1);

/* last, but not least, return our icon handle */

	return tempHand;
}

void doImport(privateDataPtr privP)
{
long				sizeH, newSize;
Handle				tempHndl;
GrafPortPtr			oldP;
word				err;
QDIconRecord			*iconP;
char				*temp0, *temp1;
Rect				r;

	err = CopyUndoIcon(privP);
	oldP = GetPort();
	tempHndl = GetFileIcon();
	if (tempHndl == 0L) {
		return;
	}
	sizeH = GetHandleSize((Handle) privP->editH);
	newSize = GetHandleSize(tempHndl);

	if (newSize != sizeH) {
		HUnlock((Handle) privP->editH);
		SetHandleSize(newSize, (Handle) privP->editH);
		err = toolerror();
		HLock((Handle) privP->editH);
	}
	HandToHand(tempHndl, privP->editH, newSize);
	SetPort(oldP);
	SetWindowSize(privP);
	RedrawFat(privP);
	updateInfoIcon(privP);
}

void DrawFatImage2(privateDataPtr privP)
{
GrafPortPtr			oldPort;
word				h0, h1, v0, v1, i, j, rowBytes, hPos, theColor, pw3, pw4;
QDIconRecord			*iconP;
Rect				theRect;

	oldPort = GetPort();
	SetPort(*privP->imageCache);
	GetPortRect(&theRect);
	EraseRect(&theRect);
	iconP = *privP->editH;
	rowBytes = ((iconP->iconWidth - 1) / 2) + 1;
	theRect.v1 = 0;
	theRect.v2 = 3;
    pw4 = pixWid >> 2;
    pw3 = pw4 - pixWid;
	for (i = 0; i < iconP->iconHeight; i++) {
		theRect.h1 = 0;
		theRect.h2 = pw3;
		hPos = 0;
		for (j = 0; j < rowBytes; j++) {
			theColor = PickColor2(hPos, i, privP, false);
			FillRect(&theRect, &patts[theColor]);
			theRect.h1 += pw4;
			theRect.h2 += pw4;
			hPos++;
			theColor = PickColor2(hPos, i, privP, false);
			FillRect(&theRect, &patts[theColor]);
			theRect.h1 += pw4;
			theRect.h2 += pw4;
			hPos++;
		}
		theRect.v1 += 4;
		theRect.v2 += 4;
	}
	if (privP->resType == rCursor) {
		theRect.h1 = (4 * pixWid) * ((privP->hotSpot.h / 2));
		theRect.h2 = theRect.h1 + (3 * pixWid);
		theRect.v1 = 4 * (privP->hotSpot.v - 1);
		theRect.v2 = theRect.v1 + 3;
		GetPenPat(&tempPattern);
		SetPenPat(&patts[4]);
		InsetRect(&theRect, (pixWid == 2) ? -2 : -1,-1);
		FrameRect(&theRect);
		SetPenPat(&tempPattern);
	}
	SetPort(oldPort);
}

void DrawFatMask2(privateDataPtr privP)
{
GrafPortPtr			oldPort;
word				h0, h1, v0, v1, i, j, rowBytes, hPos, theColor, pw3, pw4;
QDIconRecord			*iconP;
Rect				theRect;

	oldPort = GetPort();
	SetPort(*privP->maskCache);
	GetPortRect(&theRect);
	EraseRect(&theRect);
	iconP = *privP->editH;
	rowBytes = ((iconP->iconWidth - 1) / 2) + 1;
	theRect.v1 = 0;
	theRect.v2 = 3;
    pw4 = pixWid >> 2;
    pw3 = pw4 - pixWid;
	for (i = 0; i < iconP->iconHeight; i++) {
		theRect.h1 = 0;
		theRect.h2 = pw3;
		hPos = 0;
		for (j = 0; j < rowBytes; j++) {
			theColor = PickColor2(hPos++, i, privP, true);
			FillRect(&theRect, &patts[theColor]);
			theRect.h1 += pw4;
			theRect.h2 += pw4;
			theColor = PickColor2(hPos++, i, privP, true);
			FillRect(&theRect, &patts[theColor]);
			theRect.h1 += pw4;
			theRect.h2 += pw4;
		}
		theRect.v1 += 4;
		theRect.v2 += 4;
	}
	SetPort(oldPort);
}
