/*
    fColorPalette 039
    ---------------------------------------------------------------
        word    pCount          must be 2, 7 or 8
        point   Loc             input or 0,0
        word    Color           input/output
        word    Row             input
        word    Col             input
        word    Mode            input   0, 1 (msb set to get default pict)
        long    resID           input
        word    resFileID       input
        handle  picture         output

    Mark T. Collins & Marc Wolfgram,  3/6/92 23:50:21
    Revised & Greatly Extended        10/28/92 11:12
*/
word remColorPalette(fColorRecPtr p)
{
word        retVal, mHit, done, Row, Col, lastRow, lastCol, hOffset, hOrigin;
word        vOffset;
Rect        *trans, winRect, theFrame;
long        curFile;
GrafPortPtr winP, oldPort;
Point   	mLoc, oldPenSize;

    if (p->pCount == 2) {
        p->pCount = 7;
        p->Row = 4;
        p->Col = 4;
        p->Mode = 0;
        p->resID = 2L;  /* make sure this is our picture */
        p->resFileID = fResID;
    }

    if (p->pCount != 7 && p->pCount != 8)
        return SetToolError(invalidPcount);

    if (p->Color >= (p->Row * p->Col))
        return SetToolError(0x53);

    curFile = SetResFile2(p->resFileID, -1);     /* Load our picture */
    PalettePic = LoadResource(rPicture, p->resID);
    DetachResource(rPicture,p->resID);
    SetResFile1(curFile);

    (byte *) trans = (byte *) deref(PalettePic) + 2L;

    winRect.v1 = PaletteR1.v1 = PaletteR2.v1 = trans->v1;
    winRect.h1 = PaletteR1.h1 = PaletteR2.h1 = trans->h1;
    winRect.v2 = PaletteR1.v2 = PaletteR2.v2 = trans->v2;
    PaletteR2.h2 = trans->h2;
    winRect.h2 = PaletteR1.h2 = vMode ? trans->h2 : trans->h2/2;
    InsetRect(&winRect, vMode ? 4 : 2, 2);

    oldPort = GetPort();
    GetPenPat(&pattern);
    GetPenSize(&oldPenSize);

    winP = NewWindow2(0L, 0L, 0L, 0L, 0, &PaletteWin, 0x800e);

    SetPort(winP);

    if (!p->Loc.v && !p->Loc.h) {
        asm {
            pha
            pha
            pha
            ldx #0x1703
            jsl 0xe10000
            pla
            pla
            sta mLoc
            pla
            sta mLoc+2
        }
        p->Loc.v = mLoc.v;
        p->Loc.h = mLoc.h;
    }

    if (p->Loc.v < 15)  /* bound the window location if user point invalid */
        p->Loc.v = 15;
    else if (p->Loc.v > (195 - PaletteR1.v2))
        p->Loc.v = 195 - PaletteR1.v2;

    if (vMode) {
        if (p->Loc.h < 10)
            p->Loc.h = 10;
        else if (p->Loc.h > (630 - PaletteR1.h2))
            p->Loc.h = 630 - PaletteR1.h2;
        hOrigin = 2;
        hOffset = ((PaletteR1.h2 - 4) /p->Col);
    }
    else {
        if (p->Loc.h < 5)
            p->Loc.h = 5;
        else if (p->Loc.h > (315 - PaletteR1.h2))
            p->Loc.h = 315 - PaletteR1.h2;
        hOrigin = 1;
        hOffset = ((PaletteR1.h2 - 2) /p->Col);
    }
    SetPenSize(hOrigin, 1);


    MoveWindow(p->Loc, winP);

    if (p->Color == 0)
        lastRow = lastCol = Row = Col = 0;
    else {
        lastRow = Row = p->Color / p->Col;
        lastCol = Col = p->Color % p->Col;
    }
    vOffset = ((trans->v2 - 2)/p->Row);

/*    if (!(p->Mode & 0x8000)) */
        ShowWindow(winP);
    DrawOneCtl(GetCtlHandleFromID(winP, 1L));
    setupFrame(&theFrame, hOffset, vOffset, Col, Row, hOrigin);
    twiddleRect(&theFrame, p->Mode);

/*    if (p->Mode & 0x8000) {
        p->picture = (handle) getPicture(&theFrame, &PaletteR1, p->Mode);
        SetPenSize(oldPenSize);
        SetPenPat(&pattern);
	    CloseWindow(winP);
	    SetPort(oldPort);
        SetResFile1(curFile);

        return SetToolError(retVal);
    }
*/
    mHit = done = 0;
    do {
        asm {
null:       pha
            pha
            pha
            ldx #0x1703
            jsl 0xe10000
            pla
            plx
            ply
            and #0x8000
            bne trak
            lda mHit
            beq null
            inc done
trak:       sta mHit
            stx mLoc
            sty mLoc+2
        }

        GlobalToLocal(&mLoc);

        if (PtInRect(&mLoc, &winRect)) {
            Row = (mLoc.v - 1) / vOffset;
            Col = (mLoc.h - hOrigin) / hOffset;
        }
        else {
            Row = p->Color / p->Col;
            Col = p->Color % p->Col;
        }
        if (Row != lastRow || Col != lastCol) {
            twiddleRect(&theFrame, p->Mode ? 1 : 15);
            setupFrame(&theFrame, hOffset, vOffset, Col, Row, hOrigin);
            twiddleRect(&theFrame, p->Mode);
            lastRow = Row;
            lastCol = Col;
        }
	} while (!done);

    p->Color = (p->Col * Row) + Col;

    SetPenSize(oldPenSize);
    SetPenPat(&pattern);

/*    if (p->pCount == 8)
        p->picture = (handle) getPicture(&theFrame, &PaletteR1, p->Mode);
  */
	CloseWindow(winP);

	SetPort(oldPort);
    SetResFile1(curFile);

    return SetToolError(retVal);
}

/*
    twiddleRect used by remColorPalette

    Marc Wolfgram, 10/29/92  5:13:34
*/
void twiddleRect(RectPtr rect, word mode)
{
    mode &= 0x7FFF;
    if (mode == 1)
        InvertRect(rect);
    else {
        SetSolidPenPat(mode);
        FrameRect(rect);
    }
}

/*
    setupFrame used by remColorPalette

    Marc Wolfgram, 10/31/92 13:05:56
*/
void setupFrame(RectPtr frame, word hDelta, word vDelta, word Col, word Row, word hOrigin)
{
    frame->v1 = 1 + (vDelta * Row);
    frame->v2 = frame->v1 + vDelta;

    frame->h1 = hOrigin + (hDelta * Col);
    frame->h2 = frame->h1 + hDelta;
}
/*
PicHndl getPicture(RectPtr rect, RectPtr winRect, word mode)
{
long            picSize;
RegionHndl      theRegion;
PicHndl         pictHndl, retHndl;
Rect            newRect;

    if ((mode & 0x7fff) == 1)
        InvertRect(rect);
    InsetRect(rect, vMode ? 4 : 2, 2);

    theRegion = NewRgn();
    RectRgn(theRegion, winRect);

    GetPortLoc (&theLoc);

    HideCursor();

    newRect.h1 = 0;
    newRect.v1 = 0;
    newRect.h2 = rect->h2 - rect->h1;
    newRect.v2 = rect->v2 - rect->v1;


    pictHndl = OpenPicture(&newRect);
    CopyPixels(&theLoc, &theLoc, rect, &newRect, 0, theRegion);
    ClosePicture ();

    ShowCursor();

    picSize = GetHandleSize(pictHndl);
    (handle) retHndl = NewHandle(picSize, fMemID, 0x8018, 0L);
    HandToHand(pictHndl, retHndl, picSize);

    KillPicture(pictHndl);
    DisposeRgn(theRegion);

    return retHndl;
}


word AddPixelMap(word width, word height)
{
	LocInfo	    locInfo;
    Handle      pixImageH;
	word	    err;
	
    locInfo.portSCB = 0x80;
    locInfo.boundsRect.h1 = 0;
	locInfo.boundsRect.h2 = width;
	locInfo.boundsRect.v1 = 0;
	locInfo.boundsRect.v2 = height;
    locInfo.width = ((width / 4) + 7) & 0xfff8;

    pixImageH = NewHandle((long) locInfo.width * height, fMemID, 0x8018, 0L);

	if (!(err = toolerror())) {
		locInfo.ptrToPixImage = *pixImageH;
		SetPortLoc(&locInfo);
		SetPortRect(&locInfo.boundsRect);

		ClipRect(&locInfo.boundsRect);
        SetVisRgn(GetClipHandle());

		EraseRect(&locInfo.boundsRect);
		}

	return err;
}

word CreateOffPort(word width, word height, GrafPort ***pMapH)
{
	GrafPort	*oPort, **portH;
    word		err;

    oPort = GetPort();

    portH = *pMapH = 0;

    (Handle) portH = NewHandle(sizeof(GrafPort), fMemID, 0x8018, 0L);
    if (err = toolerror())
        return err;

    OpenPort(*portH);
	if (!(err = toolerror())) {
        if (!(err = AddPixelMap(width, height))
		    *pMapH = portH;
    }
    if (err)
	    DisposeHandle(portH);
    SetPort(oPort);

	return err;
}

word AdjustOffPort(GrafPort **pMapH, word width, word height)
{
	GrafPort	*oPort, *pMapP;
	LocInfo		locInfo;
	word		err;

	oPort = GetPort();
	HLock(pMapH);
	pMapP = *pMapH;
	SetPort(pMapP);

    DisposeHandle(FindHandle(pMapP->portInfo.ptrToPixImage));

	err = AddPixelMap(width, height);

    SetPort(oPort);
	HUnlock((Handle) pMapH);

    return err;
}

word DisposeOffscreen(GrafPort **pMapH)
{
    DisposeHandle(FindHandle((**pMapH).portInfo.ptrToPixImage));
	ClosePort(*pMapH);
    DisposeHandle(pMapH);
}





PicHndl getPicture(RectPtr rect, RectPtr winRect, word mode)
{
long            picSize;
RegionHndl      theRegion;
PicHndl         pictHndl, retHndl;
Rect            newRect;
GrafPort		**imageCache;	/* offscreen image image */
GrafPort		**maskCache;	/* offscreen mask image */

    if ((mode & 0x7fff) == 1)
        InvertRect(rect);
    InsetRect(rect, vMode ? 4 : 2, 2);

	err = CreateOffPort(width, height, &imageH);
	if (err == 0) {
		err = CreateOffPort(width, height, &maskH);
		if (err == 0) {
    		dataP = *dataH;
		    dataP->imageCache = imageH;
		    dataP->maskCache = maskH;

  			DrawFatImage(dataH);
			DrawFatMask(dataH);
			}
		else
			DisposeOffscreen(imageH);
		}




    HideCursor();

    newRect.h1 = 0;
    newRect.v1 = 0;
    newRect.h2 = rect->h2 - rect->h1;
    newRect.v2 = rect->v2 - rect->v1;


    pictHndl = OpenPicture(&newRect);
    CopyPixels(&theLoc, &theLoc, rect, &newRect, 0, theRegion);
    ClosePicture ();

    ShowCursor();

    picSize = GetHandleSize(pictHndl);
    (handle) retHndl = NewHandle(picSize, fMemID, 0x8018, 0L);
    HandToHand(pictHndl, retHndl, picSize);

    KillPicture(pictHndl);
    DisposeRgn(theRegion);

    return retHndl;
}
