/*
    calls3.c - callbacks 030 through 039 (formerly in calls.c)

    Marc Wolfgram,  3/30/91 11:55:50
    ---------------------------------------------------------------
*/
#pragma noroot
#pragma keep "o/calls3"

#include "calls.h"
void DrawMenuBar2(void);
void setupFrame(RectPtr, word, word, word, word, word);
void twiddleRect(RectPtr, word);
PicHndl getPicture(RectPtr, RectPtr, word);

struct rScrap {
	word		scrapType;
	long		scrapID;
	GSString255	scrapPath;
};
typedef struct rScrap rScrap, *rScrapPtr, **rScrapHndl;

extern clipFileID;

word marqueeInit;
long marqueeTick;
byte marqueePatt[160] = {
    0xf0, 0xf0, 0xf0, 0xf0, /* 640 march patt 1 (i&4) */
    0x0f, 0x0f, 0x0f, 0x0f, /* 640 march patt 0 */
    0xf0, 0xf0, 0xf0, 0xf0,
    0x0f, 0x0f, 0x0f, 0x0f,
    0xf0, 0xf0, 0xf0, 0xf0,
    0x0f, 0x0f, 0x0f, 0x0f,
    0xf0, 0xf0, 0xf0, 0xf0,
    0x0f, 0x0f, 0x0f, 0x0f,
    0xf0, 0xf0, 0xf0, 0xf0,
    0x00, 0xff, 0x00, 0xff, /* 640 stop patt 3 (i+36) */
    0xf0, 0x0f, 0xf0, 0x0f, /* 640 stop patt 2 */
    0xff, 0x00, 0xff, 0x00, /* 640 stop patt 1 */
    0x0f, 0xf0, 0x0f, 0xf0, /* 640 start patt/stop patt 0 */
    0x00, 0xff, 0x00, 0xff,
    0xf0, 0x0f, 0xf0, 0x0f,
    0xff, 0x00, 0xff, 0x00,
    0x0f, 0xf0, 0x0f, 0xf0,
    0x00, 0xff, 0x00, 0xff,
    0xf0, 0x0f, 0xf0, 0x0f,
    0xff, 0x00, 0xff, 0x00,
    0xff, 0x00, 0xff, 0x00, /* 320 march patt 1 ((i&4)+80) */
    0x00, 0xff, 0x00, 0xff, /* 320 march patt 0 */
    0xff, 0x00, 0xff, 0x00,
    0x00, 0xff, 0x00, 0xff,
    0xff, 0x00, 0xff, 0x00,
    0x00, 0xff, 0x00, 0xff,
    0xff, 0x00, 0xff, 0x00,
    0x00, 0xff, 0x00, 0xff,
    0xff, 0x00, 0xff, 0x00,
    0x00, 0x00, 0xff, 0xff, /* 320 stop patt 3 (i+36+80) */
    0xff, 0x00, 0x00, 0xff, /* 320 stop patt 2 */
    0xff, 0xff, 0x00, 0x00, /* 320 stop patt 1 */
    0x00, 0xff, 0xff, 0x00, /* 320 start patt/stop patt 0 */
    0x00, 0x00, 0xff, 0xff,
    0xff, 0x00, 0x00, 0xff,
    0xff, 0xff, 0x00, 0x00,
    0x00, 0xff, 0xff, 0x00,
    0x00, 0x00, 0xff, 0xff,
    0xff, 0x00, 0x00, 0xff,
    0xff, 0xff, 0x00, 0x00
};

char pattern[32];
LocInfo     theLoc;

segment "F_CALLBACK";

/*
    fSpecialMagic 030
    ---------------------------------------------------------------
        word    pCount          5
        word    resType         input
        Long    resID           input (0) or ignored (1-3)
        Handle  resData         retval (1) or input (1-3)
        word    special         input...0 - load/convert to data handles
        word    resFileID       input    1 - lock all data
        Pointer resName         ignored   2 - unlock all data
                                           3 - dispose of all data
    Marc Wolfgram, 10/15/91 19:09:20
*/
word remSpecialMagic(fResDataRecPtr p)
{
word retVal, curFile, curDepth, action;
remTypeLinkPtr rPtr;

    curFile = GetCurResourceFile();
    curDepth = SetResourceFileDepth(-1);

    if (p->pCount != 5)
        retVal = invalidPcount;
    else {
        SetCurResourceFile(p->resFileID);
        retVal = toolerror();
        if (!retVal) {
            action = p->special;
            retVal = resNotFound;
            if (action) {
                if (p->resType && p->resData)
                    retVal = remTwiddleSpecial(p->resType, p->resData, action-1);
            }
            else if (p->resType && p->resID) {
                p->resData = remLoadSpecial(p->resType, p->resID);
                if (p->resData)
                    retVal = 0;
            }
        }
    }

    curDepth = SetResourceFileDepth(curDepth);
    SetCurResourceFile(curFile);

    return SetToolError(retVal);
}

/*
    fLoadScrap 031
    ---------------------------------------------------------------
        word    pCount          5
        word    resType         retval (primary type if scrap type ours)
        Long    resID           retval (if scrap type ours)
        Handle  resData         retval scrap (linkHndl if scrap type ours)
        word    special         retval scrap type
        word    resFileID       retval fork containing contents of linkHndl
        Pointer resName         ignored

    Marc Wolfgram, 10/19/91 21:16:33
*/
word remLoadScrap(fResDataRecPtr p)
{
rScrapHndl  scrapH;
fResLinkRec	linkPB;
word		curFile, retVal;

	p->resType = 0;
	p->resID = 0L;
	p->resData = 0L;
    p->resFileID = 0L;

    retVal = invalidPcount;
    if ((p->pCount == 5 && p->special == 0x8003) ||
        (p->pCount == 4 && p->special != 0x8003))
        retVal = 0;

    if (retVal)
        return SetToolError(retVal);

    (Handle) scrapH = GetScrapHandle(p->special);
    if (retVal = toolerror())
    	return(retVal);

	if (p->special != 0x8003) {
        p->resData = (Handle) scrapH;
	    return SetToolError(0);
    }
	curFile = GetCurResourceFile();
	clipFileID = p->resFileID = OpenResourceFile(0x8003, 0L, &(**scrapH).scrapPath);
	retVal = toolerror();
	SetCurResourceFile(curFile);
	if (retVal)
    	return SetToolError(fileNotFound);

	p->resType = (**scrapH).scrapType;
	p->resID = (**scrapH).scrapID;
	p->special = 0x8003;

	linkPB.pCount = 8;
	linkPB.hostType = p->resType;
	linkPB.hostID = p->resID;
	linkPB.resFileID = p->resFileID;
	remBuildLinkHand(&linkPB);
	p->resData = linkPB.linkHand;

    return SetToolError(0);
}

/*
    fSaveScrap 032
    ---------------------------------------------------------------
        word    pCount          4
        word    resType         input (parent type if scrap type ours)
        Long    resID           input (parent id scrap type ours)
        Handle  resData         input scrap (if scrap type standard)
        word    special         input scrap type
        word    resFileID       ignored
        Pointer resName         ignored

    Marc Wolfgram, 10/19/91 21:16:33
*/
word remSaveScrap(fResDataRecPtr p)
{
word            clipResFile, curResFile, retVal;
long            clipID;
NameRecGS 		KillPB;
rScrapPtr		scrapP;
rScrapHndl		scrapH;
ExpandPathRecGS expandPB;

    copyFlag = 9;
    if (p->pCount != 4)
    	return SetToolError(invalidPcount);

	if (GetScrapSize(p->special))
    	ZeroScrap();

    if (p->special == 0x8003) {
   		KillPB.pCount = 1;
    	KillPB.pathname = &clipFile;
    	DestroyGS(&KillPB);
    	curResFile = GetCurResourceFile();
    	CreateResourceFile(1L, 0x5e, 0xc3, &clipFile);
		clipResFile = OpenResourceFile(0x8003, 0L, &clipFile);
		if (retVal = toolerror()) {
			/* error opening scrap file */
			return SetToolError(retVal);
		}
 		clipID = CopyResource(workList[workIndex].resFileID, clipResFile, p->resType, p->resID);

		(Handle) scrapH = NewHandle((long) sizeof(struct rScrap), fMemID, 0x0018, 0L);
    	(Pointer) scrapP = deref((Handle) scrapH);

    	expandPB.pCount = 2;
    	expandPB.inputPath = &clipFile;
    	expandPB.outputPath = (ResultBuf255Ptr) &scrapP->scrapID;
    	asm {
    		inc expandPB+6		/* sorry for this, I'll worry */
			inc expandPB+6		/* about cleaning it up later */
		}
    	scrapP->scrapID = 0xff0000L;
		ExpandPathGS(&expandPB);

    	scrapP->scrapType = p->resType;
    	scrapP->scrapID = clipID;
    	PutScrap((long) sizeof(struct rScrap), p->special, scrapP);
    	DisposeHandle(scrapH);

    	CloseResourceFile(clipResFile);
    	SetCurResourceFile(curResFile);
		InitCursor();
	}
	else {
    	PutScrap(GetHandleSize(p->resData), p->special, *(p->resData));
    	DisposeHandle(p->resData);
	}
	return SetToolError(0);
}

/*
    fGetEditorStatus 033
    ---------------------------------------------------------------
        word    pCount          3
        word    resType         input
        Long    resID           input
        Long    result          retval
        word    resFileID       ignored
        Pointer resName         ignored

    Marc Wolfgram, 10/ 2/91 23:53:26
*/
word remGetEditorStatus(fResData2RecPtr p)
{
long found;
remTypeLinkPtr rPtr;

    if (p->pCount != 3)
        return SetToolError(invalidPcount);

    p->result = 0x0060L;    /* HexEdit - default */

    rPtr = getTypeLinkRef(p->resType);
    if (rPtr->resType == p->resType)
        p->result = 0x0020L;

    if (p->resID) {
        if (findSignature(REM_signature+0x0020+workIndex, 0, p->resType, p->resID))
            p->result |= 0x00200000L;
        else if (findSignature(REM_signature+0x0040+workIndex, 0, p->resType, p->resID))
            p->result |= 0x00400000L;
        else if (findSignature(REM_signature+0x0060+workIndex, 0, p->resType, p->resID))
            p->result |= 0x00600000L;
    }

    return SetToolError(0);
}

/*
    fSelectorRequest 034
    ---------------------------------------------------------------
        word    pCount          4
        word    resType         input
        Long    resID           input
        Handle  resData         ignored
        word    special         input...	0x2f0/0 - native edit
                                         	0x2f1/1 - script edit
                                          	0x2f2/2 - hex edit
        									0x2f3/3 - attributes
                                         	0x2f4/4 - delete
                                          	0x2f5/5 - export
                                          	0x2f6/6 - parents
                                          	0x2f7/7 - childern

    Marc Wolfgram, 10/22/91, 19:29:41
*/
word remSelectorRequest(fResDataRecPtr p)
{
word retVal;
remTypeLinkPtr rPtr;

    if (p->pCount != 4)
        retVal = invalidPcount;
    else {
        switch(p->special) {
        case 0:
        case 1:
        case 2:
		case 0x2f0:
		case 0x2f1:
		case 0x2f2:
            retVal = openEditor(p->resType, p->resID, p->special);
            break;

        case 3:
		case 0x2f3:
            retVal = editAttributes(p->resType, p->resID);
            break;

        case 4:
		case 0x2f4:
            retVal = deleteRequested(p->resType, p->resID);
            break;

        case 5:
		case 0x2f5:
            retVal = exportRequested(p->resType, p->resID);
            break;

       	case 6:
		case 0x2f6:
			retVal = dependentsRequested(p->resType, p->resID);
			break;

        default:
            retVal = fBadSelectorMode;
            break;
        }
    }
    return SetToolError(retVal);
}

/*
    fSelectorMenu 035
    ---------------------------------------------------------------
        word    pCount          5
        word    resType         input
        Long    resID           input or null
        Handle  resData         input or null
        word    special         input
        word    resFileID       input
        Pointer resName         ignored

	Marc Wolfgram, 12/10/91  1:40:52
*/
word remSelectorMenu(fResDataRecPtr p)
{
word i, retVal, curFile, curDepth;
long			*iList;
MenuRecHndl 	menuH;
MenuItemTemplate **iTemplateH;

    retVal = 0;

    curFile = GetCurResourceFile();
    curDepth = SetResourceFileDepth(1);
    SetCurResourceFile(fResID);

	if (p->pCount != 5)
        retVal = invalidPcount;

    else {
        menuH = GetMHandle(5);
        if (menuH)
            DeleteMenu(5);

        (Handle) selectorMenuH = remLoadSpecial(rMenu, 5L);
        remTwiddleSpecial(rMenu, (handle) selectorMenuH, 0);
        menuH = NewMenu2(1, selectorMenuH);
        InsertMenu(menuH, 4);
    	if (p->special) {
            InsertMItem2(1, 0x1ffL, -1, 5);
    		SetCurResourceFile(p->resFileID);
    		if (p->resType && p->resID)
				p->resData = LoadResource(p->resType, p->resID);

            (Handle) selectorItemH = p->resData;
        	(Pointer) iList = deref(p->resData);

        	for (i = 0; iList[i] != 0L; i++) {
            	(Handle) iTemplateH = remLoadSpecial(rMenuItem, iList[i]);
        		remTwiddleSpecial(rMenuItem, (handle) iTemplateH, 0);
            	InsertMItem2(2, iTemplateH, -1, 5);
            }
		}
		else
			(Long) selectorItemH = 0L;

        FixMenuBar();
        DrawMenuBar2();
        setupTypeMenu(p->resType, 0L);

    }
    curDepth = SetResourceFileDepth(curDepth);
    SetCurResourceFile(curFile);

    return SetToolError(retVal);
}

/*
    fFindHostLink 036
    ---------------------------------------------------------------
        word    pCount          6 or 7
        word    index           output
        Handle  linkHand        output
        word    hostType        output
        Long    hostID          output
        word    resType         input
        Long    resID           input
        Word    resCheck        output
        word    resFileID       (ignored)

    Marc Wolfgram,  5/18/91  8:56:21
*/
word remFindHostLink(fResLinkRecPtr p)
{
word retVal;
resLinkRecPtr lPtr;
resLinkRecHndl lHndl;

    p->linkHand = 0L;
    p->hostType = 0;
    p->hostID = 0L;

	switch (p->pCount) {
	case 7:
		p->resCheck = 0;
    case 6:
    	if (p->pCount == 6 || p->pCount == 7) {
			lHndl = remFindOwner(p->resType, p->resID);
    		p->linkHand = (Handle) lHndl;
        	if ((p->index = lPtr->count) == 1) {
				retVal = remQueryLinkHand(p);
				p->index++;
			}
		}
		break;

  	default:
       	retVal = invalidPcount;
		break;
    }
    HUnlock(lHndl);

    return SetToolError(retVal);
}

/*
    fSpinCursor 037
    ---------------------------------------------------------------
	Marc Wolfgram,  1/12/92 14:57:18
*/
word remSpinCursor(long p)
{
	MoonCursor();
    return SetToolError(0);
}

/*
    fMarquee 038
    ---------------------------------------------------------------
        word        pCount          3
        word        action          input   0 animate, 1 init, 2 kill regions
        GrafPortPtr windowPtr       input
        Handle      rgnListHand     input   Handle to rgnList structure
	
            NOTE: The high bit of the ArcRot field in the target
                  window must be set to use these 32-bit patterns.

    Jim Murphy & Marc Wolfgram  7/10/92  2:09:13 PM
*/
word remMarquee(fMarqueeRecPtr p)
{
word i;
long curTick;
PenState oldPenState;
GrafPortPtr oldP;
rgnListHndl rlH;

    if (p->pCount != 3)
        return SetToolError(invalidPcount);

    if (marqueeInit == 1)
        p->action = 1;

    rlH = p->rgnListHand;

    switch (p->action) {
    case 0:
        curTick = GetTick();
        if (curTick - marqueeTick < 8)
            return SetToolError(0);

        i = (**rlH).index;
        (**rlH).index = (!i) ? 12 : i - 4;
        i &= 4;
        marqueeTick = curTick;
        break;

    case 1:
        p->action = 0;
        (**rlH).index = 12;
        marqueeInit = 0;
        marqueeTick = GetTick();

    case 2:
        i = (**rlH).index + 36;
        break;

    default:
        return SetToolError(0x53);    			/* param range error */
        break;
    }

    oldP = GetPort();
    SetPort(p->windowPtr);
    GetPenState(&oldPenState);
    SetPenMode(notXOR);
    if (vMode)
        SetPenSize(2,1);
    else {
        SetPenSize(1,1);
        i += 80;
    }
    SetPenPat(&marqueePatt[i]);
    for (i = (**rlH).count; i; i--)
        FrameRgn((**rlH).list[i-1]);
    SetPenState(&oldPenState);
    SetPort(oldP);
    return SetToolError(0);
}

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

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

    ShowWindow(winP);
    DrawOneCtl(GetCtlHandleFromID(winP, 1L));

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