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

    Mark & Marc,  5/31/93 12:51:50
    And here's Icon Editor Hell
*/

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

extern EventRecordPtr   fEventPtr;
extern word             fUserID;
extern long             remHelpID;
extern fColorRec        ColorPB;
extern word			    edResFileID, shResFileID, fdResFileID;
extern handle           toolIcn[6];
extern handle           cursor[6];

void PutColor2(word, word, word, privateDataPtr, word);
word PickOldColor2(word, word, privateDataPtr, word);


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;
char			tempStr[8];
Pattern         tempPattern;
Point           xyPoint;



segment "icon_stuff";

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

	privP->flag = 0x8000;
	sizeH = GetHandleSize(privP->resData);

    privP->winP = winP;
	privP->editH = (QDIconRecord **) NewHandle(sizeH, fUserID, 0x0018, 0L);
	HandToHand(privP->resData, privP->editH, sizeH);

	privP->undoH = (QDIconRecord **) NewHandle(sizeH, fUserID, 0x0018, 0L);
	HandToHand(privP->resData, privP->undoH, sizeH);

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

    MakeGlobalRect(&privP->fatIRect, &privP->gFatIRect);
    MakeGlobalRect(&privP->fatMRect, &privP->gFatMRect);
    MakeGlobalRect(&privP->sizeRect, &privP->gSizeRect);

    ShowWindow(winP);
}

/*--------------------------------------
    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 + 2);

    /*  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 = 0x8000;
	privP->imageCache = nil;
	privP->maskCache = nil;

    /* allocate the offscreen pixelmaps: */
	w = privP->fatIRect.h2 - privP->fatIRect.h1 + (4 * pixWid);
	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;
	DrawFatImage(&privP);
	DrawFatMask(&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();

		ColorPB.pCount = 7;
		ColorPB.Loc.h = 0;
		ColorPB.Loc.v = 0;
		ColorPB.Color = privP->tool & 0x0007;
		ColorPB.Row= 2;
		ColorPB.Col = 3;
		ColorPB.Mode = 0;
		ColorPB.resID = 0x10L;
		ColorPB.resFileID = edResFileID;
		err = fColorPalette(&ColorPB);
		privP->tool = ColorPB.Color | 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)) {
    	ColorPB.pCount = 2;
		ColorPB.Loc.h = 0;
		ColorPB.Loc.v = 0;
        if (PtInRect(&pt, &frg)) {
    		ColorPB.Color = privP->color;
    		fColorPalette(&ColorPB);
	    	privP->color = ColorPB.Color;
        }
		else {
            ColorPB.Color = privP->maskColor;
    		fColorPalette(&ColorPB);
            privP->maskColor = ColorPB.Color;
        }
		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(1, 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(1, rWindParam1);
        return 0;
	}
	return 0;
}

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

    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);

	r = mask ? &(privP->fatMRect) : &(privP->fatIRect);
	InsetRect(r, 2, 1);
	InvalRect(r);
	if (mask) {
		DrawFatMask(&privP);
	}
	else
		DrawFatImage(&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 = port->portInfo.width;
    p1width = port->portInfo.boundsRect.h2 / 4;

    p0 = (char *) &iconP->iconImage;
    p1 = (char *) port->portInfo.ptrToPixImage;
    if (inMask) {
        p0 += iconP->iconSize;
        p1 += 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 = port->portInfo.width;
    p1width = port->portInfo.boundsRect.h2 / 4;
    p0 = (char *) &iconP->iconImage;
    p1 = (char *) port->portInfo.ptrToPixImage;
    if (inMask) {
        p0 += iconP->iconSize;
        p1 += iconP->iconSize;
    }
    copyRows(p1, p0, iconP->iconHeight, p1width, p0width);
}

#pragma debug -1

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;
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[privP->color], &leakTable);
		err = toolerror();
		Pixmap2Icon(tempPort, *iconH, inMask);
		DisposeSource(tempPort);
        DisposeHandle((Handle) tpH);
		SetPort(oPort);

        BlockMove(&privP->fatIRect, &r, 8L);

		InsetRect(&r, 2, 1);
		InvalRect(&r);
		DrawFatImage(&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;
	rowBytes = (w - 1) / 2 + 1;

	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), 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;
}

#pragma debug 0
void MakeMask(privateDataPtr privP)
{
GrafPort		tempPort, *oPort;
QDIconRecord	**iconH;
Cursor		    *oCurs;
LocInfo		    portInfo;
word			leakTable[2];
word			err;

	oCurs = GetCursorAdr();
	oPort = GetPort();
	err = CopyUndoIcon(privP);
	iconH = privP->editH;
	err = FillSource(&tempPort, iconH);
	if (err == 0) {
		Icon2Pixmap(*iconH, &tempPort, -1);
		leakTable[0] = 1;
		leakTable[1] = 0xffff;	/* leak color is white */
		CalcMask(&tempPort.portInfo, &tempPort.portRect,
			 &tempPort.portInfo, &tempPort.portRect,
			 destModeClrToOnes + resMode640DMask, 0L, &leakTable);
		err = toolerror();
		Pixmap2Icon(&tempPort, *iconH, true);

		RedrawFatbits(privP, true);
        privP->flag = 0x8001;
	}
	DisposeSource(&tempPort);
	SetPort(oPort);
}

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, word deltaX, word deltaY)
{
word			iSize, iHeight, iWidth, iWBytes, 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;
word		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 = 0x8001;
		RedrawFatbits(privP, true);
		DrawFatImage(&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 SetPixelColor(word x, word y, word color, QDIconRecord *iconP, word inMask)
{
char		*p;

	p = (char *) &iconP->iconImage + (iconP->iconWidth * y + x) / 2;
	asm {
		lda	x
		lsr	a
		lda	#0x000f
		bcs	useLo
		lda	#0x00f0
useLo:	tax
		and	color
		pha
		txa
		eor	#0xffff
		and	[p]
		ora	1,s
		sta	[p]
		plx
	}
}

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

	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;
	iconH = privP->editH;
	iconP = *iconH;
	if (newHt != iconP->iconHeight || newWd != iconP->iconWidth) {
		CopyUndoIcon(privP);
		err = ResizeIt(privP, newWd, newHt);
		SetWindowSize(privP);
        MakeGlobalRect(&privP->fatIRect, &privP->gFatIRect);
        MakeGlobalRect(&privP->fatMRect, &privP->gFatMRect);
        MakeGlobalRect(&privP->sizeRect, &privP->gSizeRect);
		RedrawFat(privP);
	}
}

void FatClick(EventRecord *event)
{
privateDataHndl	    privH;
privateDataPtr      privP;
GrafPortPtr         winP, oPort;

Point		pt, ptG;
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 = 0x8001;
                updateInfoIcon(privP);
				break;
			case ShifterTool:						/* shift */
				CopyUndoIcon(privP);
				ShiftIcon(privP, pt);
                privP->flag = 0x8001;
				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 = 0x8001;
                updateInfoIcon(privP);
				break;
			}
	}
	else if (PtInRect(&pt, &privP->sizeRect)) {
		GrowFat(privP, pt);
        privP->flag = 0x8001;
	}
	SetOrigin(0, 0);
	SetPort(oPort);
}

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;
Rect		r;

	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 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);
	DrawFatImage(&privP);
	DrawFatMask(&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);
	DrawIcon(*(privP->editH), 0, r.h1, r.v1);
    EndInfoDrawing();
}

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

    temp = inMask ? privP->maskColor : privP->color;
    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);

        temp = *p;

        if (!(x & 0x1))
            temp >>= 4;
        temp &= 0x0f;
    }
	return temp;
}

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 = (QDIconRecord **) 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;
        }
    }
}
