/*--------------------------------------
	common.c

	Mark Collins
	contains utility routines for the entire unit
*/

#include "icon.h"

extern EventRecordPtr	fEventPtr;
extern word			fUserID;
extern word			edResFileID;
extern word			shResFileID;
extern word			fdResFileID;
extern long			remHelpID;
extern word			pixWid;
extern long			remHelpID;
extern handle			cursor[6];

fPrivateDataRec		PrivPB;
fResDataRec			DataPB;
fResData2Rec			Res2PB;
fResNameRec			NamePB;
fResRefRec			RefPB;
fColorRec			ColorPB;
fLoadFileRec			FilePB;
SFTypeList2			typeList;
SFReplyRec2			repRec;
char				tempStr[256];

void MakeGlobalRect(Rect *inR, Rect *outR)
{
	BlockMove(inR, outR, 8L);
	LocalToGlobal(&outR->v1);
	LocalToGlobal(&outR->v2);
}

word getVid(void)
{
	return (GetMasterSCB() & 0x80) ? 2 : 1;
}

word setMaxOf(word a, word b)
{
	return (a > b) ? a : b;
}

word setMinOf(word a, word b)
{
	return (a > b) ? b : a;
}

void stuffRect(Rect *r, word l, word t, word w, word h)
{
	r->h1 = l;
	r->v1 = t;
	r->h2 = l + w;
	r->v2 = t + h;
}


void FillLECtlWrd(word inVal, GrafPortPtr winP, long ctlID)
{
word				len;

	len = sprintf(tempStr, "*%0.4X", inVal);
	tempStr[0] = len - 1;
	SetLETextByID(winP, ctlID, tempStr);
}

void FillLECtlLng(long inVal, GrafPortPtr winP, long ctlID)
{
word				len;

	len = sprintf(tempStr, "*%0.4lX", inVal);
	tempStr[0] = len - 1;
	SetLETextByID(winP, ctlID, tempStr);
}

long setMatchFlags(long MatchFlags, Handle ctlH, long mask)
{
	if (GetCtlValue(ctlH))
		return MatchFlags |= mask;
	else {
		mask ^= 0xFFFFFFFFL;
		return MatchFlags &= mask;
	}
}

void setFlagCtl(long flags, Handle ctlH, long mask)
{
word				on;

	on = (flags & mask);
	SetCtlValue(on, ctlH);
}

void makeCursor (privateDataPtr privP)
{
word				i, j, *k;
long				sizeH, imageSize;
CursorPtr			cursorP;
QDIconRecord			*iconP;
Pointer				i0, o0, temp1;

	sizeH = GetHandleSize((Handle) privP->editH);
	HUnlock(privP->resData);
	SetHandleSize(sizeH + 10L, privP->resData);
	HLock(privP->resData);
	iconP = *(privP->editH);
	cursorP = (CursorPtr) *(privP->resData);
	cursorP->cursorHeight = iconP->iconHeight;
	cursorP->cursorWidth = iconP->iconWidth / 4;
	imageSize = (long) iconP->iconSize;
	i0 = (char *) &(iconP->iconImage[0]);
	o0 = (char *) &(cursorP->cursorData[0]);
	BlockMove(i0, o0, imageSize);
	temp1 = o0;
	for (i = 0; i < imageSize; i++) {
		*temp1 ^= 0xff;
		temp1++;
	}
	i0 += imageSize;
	o0 += imageSize;
	BlockMove(i0, o0, imageSize);
	o0 += imageSize;
	k = (word *) o0;
	*k = privP->hotSpot.v;
	o0++;
	o0++;
	k = (word *) o0;
	*k = privP->hotSpot.h;
	o0 += 4;
	*o0 = (pixWid == 2) ? 0x80 : 0x00;
	for (i = 0; i < 9; i++) {
		o0++;
		*o0 = 0x00;
	}
}

void extractCursor (privateDataPtr privP)
{
word				*k, i, j;
long				sizeH, imageSize;
CursorPtr			cursorP;
QDIconRecord			*iconP;
Pointer				i0, o0, temp1;

	if (!privP->editH) {
		privP->editH = (QDIconRecord **) NewHandle(100L, fUserID, 0x8018, 0L);
	}
	HUnlock((Handle) privP->editH);
	sizeH = GetHandleSize(privP->resData);
	SetHandleSize(sizeH, (Handle) privP->editH);
	HLock((Handle) privP->editH);
	iconP = *(privP->editH);
	cursorP = (CursorPtr) *(privP->resData);
	iconP->iconHeight = cursorP->cursorHeight;
	iconP->iconWidth = cursorP->cursorWidth * 4;
	imageSize = iconP->iconHeight * (iconP->iconWidth / 2);
	iconP->iconSize = imageSize & 0xffff;
	i0 = (char *) &(iconP->iconImage[0]);
	o0 = (char *) &(cursorP->cursorData[0]);
	BlockMove(o0, i0, imageSize);
	j = imageSize & 0xffff;
	temp1 = i0;
	for (i = 0; i < j; i++) {
		*temp1 ^= 0xff;
		temp1++;
	}
	i0 += imageSize;
	o0 += imageSize;
	BlockMove(o0, i0, imageSize);
	o0 += imageSize;
	k = (word *) o0;
	privP->hotSpot.v = *k;
	o0++;
	o0++;
	k = (word *) o0;
	privP->hotSpot.h = *k;
}

void CreateOffPort(word width, word height, GrafPort ***pMapH)
{
GrafPortPtr			oPort;
GrafPortHndl			portH;
LocInfo				locInfo;
Handle				pixImageHndl;
Ptr					pixImagePtr;

	oPort = GetPort();
	portH = *pMapH = 0L;
	portH = (GrafPortHndl) NewHandle(sizeof(GrafPort), fUserID, 0x8018, 0L);
	HLock((Handle) portH);
	OpenPort(*portH);
	locInfo.portSCB = GetMasterSCB();
	locInfo.boundsRect.h1 = 0;
	locInfo.boundsRect.h2 = width;
	locInfo.boundsRect.v1 = 0;
	locInfo.boundsRect.v2 = height;
	locInfo.width = ((width / 4) + 7) & 0xfff8;
	pixImageHndl = NewHandle((long) (locInfo.width * height), fUserID, 0x8018, 0L);
	pixImagePtr = *pixImageHndl;
	locInfo.ptrToPixImage = pixImagePtr;
	SetPortLoc(&locInfo);
	SetPortRect(&locInfo.boundsRect);
	ClipRect(&locInfo.boundsRect);
	SetVisRgn(GetClipHandle());
	EraseRect(&locInfo.boundsRect);
	SetPort(oPort);
	HUnlock((Handle) portH);
	*pMapH = portH;
}

void AdjustOffPort(GrafPort **pMapH, word width, word height)
{
GrafPortPtr			oPort, pMapP;
LocInfo				locInfo;
Handle				h, pixImageHndl;
Ptr					pixImagePtr;

	oPort = GetPort();
	pMapP = *pMapH;
	SetPort(pMapP);
	h = FindHandle(pMapP->portInfo.ptrToPixImage);
	if (h)
		DisposeHandle(h);
	locInfo.portSCB = GetMasterSCB();
	locInfo.boundsRect.h1 = 0;
	locInfo.boundsRect.h2 = width;
	locInfo.boundsRect.v1 = 0;
	locInfo.boundsRect.v2 = height;
	locInfo.width = ((width / 4) + 7) & 0xfff8;
	pixImageHndl = NewHandle((long) (locInfo.width * height), fUserID, 0x8018, 0L);
	pixImagePtr = *pixImageHndl;
	locInfo.ptrToPixImage = pixImagePtr;
	SetPortLoc(&locInfo);
	SetPortRect(&locInfo.boundsRect);
	ClipRect(&locInfo.boundsRect);
	SetVisRgn(GetClipHandle());
	EraseRect(&locInfo.boundsRect);
	SetPort(oPort);
	HUnlock((Handle) pMapH);
}

word UpdateEditor(GrafPortPtr winP)
{
	BeginUpdate(winP);
	EndUpdate(winP);
	return -1;
}

word EditorMenu(EventRecord *event)
{
word				done;
WindowPtr			winP;
privateDataHndl		privH;
privateDataPtr		privP;
long				temp;
MouseRec				theMouse;

	winP = FrontWindow();
	privH = getPrivate(winP);
	privP = *privH;
	temp = event->wmTaskData & 0x0000ffff;
	switch (temp) {
		case UNDOITEM:  /* undo */
			doUndo(privP);
			privP->flag = 0x0001;
			break;
		case COPYITEM:  /* copy */
		/* needs to be written */
			break;
		case PASTEITEM: /* paste */
		/* needs to be written */
			break;
		case CLEARITEM: /* clear */
			doClear(privP);
			privP->flag = 0x0001;
			break;
		case FLIPVERTITEM:
			flipIcon(privP);
			privP->flag = 0x0001;
			break;
		case FLIPHORZITEM:
			flipHorizIcon(privP);
			privP->flag = 0x0001;
			break;
		case FILLICONITEM:
			fillImage(privP);
			privP->flag = 0x0001;
			break;
		case FILLMASKITEM:
			fillMask(privP);
			privP->flag = 0x0001;
			break;
		case MAKEMASKITEM:			/* create mask */
			MakeMask(privP);
			privP->flag = 0x0001;
			break;
		case COPYMASKITEM:			/* copy icon to mask */
			copyIconToMask(privP);
			privP->flag = 0x0001;
			break;
		case IMPORTITEM:
			doImport(privP);
			privP->flag = 0x0001;
			break;
		case 0x0408L:               /* test item */
			checkData(winP);
			SetCursor(*privP->resData);
			done = false;
			do {
				theMouse = ReadMouse();
				if (theMouse.mouseStatus & 0x80) {
					done = true;
				}
			} while (!done);
			InitCursor();
			break;
		case HOTSPOTITEM:               /* set hot spot item */
			changeHotSpot(privP);
			privP->flag = 0x0001;
			break;
	}
	return 0;
}

#pragma databank  1
#pragma toolparms 1
void DrawProc(void) {
	DrawEditor();
}
#pragma databank  0
#pragma toolparms 0

void checkData(GrafPortPtr winP) {

privateDataHndl		privH;
privateDataPtr		privP;
long				size;
OneDocDataPtr			docP;
BundleStructPtr		structP;

	privH = getPrivate(winP);
	privP = *privH;

	switch (privP->resType) {
		case rIcon:
			if (privP->flag == 0) {
				return;
			}
			size = GetHandleSize(privP->editH);
			HUnlock(privP->resData);
			SetHandleSize(size, privP->resData);
			HandToHand((Handle) privP->editH, privP->resData, size);
			HLock(privP->resData);
			RefPB.pCount = 2;
			RefPB.resType = rIcon;
			RefPB.resID = privP->resID;
			fWriteResource(&RefPB);
			privP->flag = 0x0000;	/* set dirty flag to 0 */
			break;
		case rCursor:
			if (privP->flag == 0) {
				return;
			}
			makeCursor(privP);
			RefPB.pCount = 2;
			RefPB.resType = rCursor;
			RefPB.resID = privP->resID;
			fWriteResource(&RefPB);
			privP->flag = 0x0000;	/* set dirty flag to 0 */
			break;
        case rBundle:
			structP = *privP->structH;
			docP = *(structP->oneDocHndl[privP->curDoc]);
			StoreCtls(privP->curGroup, winP, docP);
			privP->resData = RebuildBundle(privP->structH);
			RefPB.pCount = 2;
			RefPB.resType = rBundle;
			RefPB.resID = privP->resID;
			fWriteResource(&RefPB);
			privP->flag = 0x0000;
			break;
		default:
			break;
	}
}

handle loadIconRes(long id)
{
word				retErr;

	DataPB.pCount = 3;
	DataPB.resType = rIcon;
	DataPB.resID = id;
	DataPB.resFileID = 0L;
	retErr = fLoadResource(&DataPB);
	RefPB.pCount = 2;
	RefPB.resType = rIcon;
	RefPB.resID = id;
	retErr = fDetachResource(&RefPB);
	return DataPB.resData;
}

privateDataHndl getPrivate(GrafPortPtr winP)
{
	PrivPB.pCount = 4;
	(GrafPortPtr) PrivPB.winPtr = winP;
	fGetPrivateData(&PrivPB);
	return (privateDataHndl) PrivPB.Data;
}

word verifyRes(word resType, long resID)
{
word				dummy;

	Res2PB.pCount = 3;
	Res2PB.resType = resType;
	Res2PB.resID = resID;
	dummy = fGetResourceSize(&Res2PB);
	return dummy;
}

long getIconID(long resID)
{
handle				resData;
word				retErr;

	if (verifyRes(rIcon, resID)) {
		resData = loadEdRes(0x18001L, rIcon);
		DataPB.pCount = 4;
		DataPB.resID = resID;
		DataPB.special = 0;
		retErr = fAddResource(&DataPB);
		return DataPB.resID;
	}
	return resID;
}

handle loadEdResource(word resType, long resID)
{
word				retErr;

	DataPB.pCount = 6;
	DataPB.resType = resType;
	DataPB.resID = resID;
	DataPB.resFileID = edResFileID;
	retErr = fLoadResource(&DataPB);
	RefPB.pCount = 3;
	RefPB.resType = resType;
	RefPB.resID = resID;
	RefPB.resFileID = edResFileID;
	retErr = fDetachResource(&RefPB);
	return DataPB.resData;
}

long sAddResource(word resType, long resID)
{
word				retErr;

	DataPB.pCount = 4;
	DataPB.resType = resType;
	DataPB.resID = resID;
	DataPB.special = 0;
	retErr = fAddResource(&DataPB);
	RefPB.pCount = 2;
	RefPB.resID = DataPB.resID;
	RefPB.resType = resType;
	retErr = fReleaseResource(&RefPB);
	return DataPB.resID;
}

handle loadRes(long resID, word resType)
{
word				retErr;

	DataPB.pCount = 3;
	DataPB.resType = resType;
	DataPB.resID = resID;
	retErr = fLoadResource(&DataPB);
	return DataPB.resData;
}

void releaseRes(word resType, long resID)
{
word				retErr;
	RefPB.pCount = 2;
	RefPB.resType = resType;
	RefPB.resID = resID;
	retErr = fReleaseResource(&RefPB);
}

handle loadEdRes(long resID, word resType)
{
word				retErr;

	DataPB.pCount = 5;
	DataPB.resType = resType;
	DataPB.resID = resID;
	DataPB.special = 0;
	DataPB.resFileID = edResFileID;
	retErr = fSpecialMagic(&DataPB);
	DataPB.special = 1;
	retErr = fSpecialMagic(&DataPB);
	return DataPB.resData;
}

void unloadEdRes(handle resData, word resType)
{
word				retErr;

	DataPB.pCount = 5;
	DataPB.resType = resType;
	DataPB.resData = resData;
	DataPB.special = 3;
	DataPB.resFileID = edResFileID;
	retErr = fSpecialMagic(&DataPB);
}

void setTitle(word resType, long resID, GrafPortPtr winP)
{
long				val;
handle				title;
word				retErr;

	title = NewHandle(128L, fUserID, 0x8018, 0L);
	NamePB.pCount = 3;
	NamePB.resType = resType;
	NamePB.resID = resID;
	NamePB.resName = (Pointer) *title;
	retErr = fGetWindowTitle(&NamePB);
	SetWTitle(*title, winP);
}

void sAddPrivateData(word resType, word resID, word signature, GrafPortPtr winP, long taskMask, handle data, word grpSign)
{
	PrivPB.pCount = 7;
	PrivPB.winPtr = (Pointer) winP;
	PrivPB.remTaskMask = taskMask;
	PrivPB.remSignature = signature;
	PrivPB.Data = data;
	PrivPB.groupSignature = grpSign;
	PrivPB.resType = resType;
	PrivPB.resID = resID;
	fAddPrivateData(&PrivPB);
}

word sPalette1(word color)
{
word				err;

	ColorPB.pCount = 2;
	ColorPB.Loc.h = 0;
	ColorPB.Loc.v = 0;
	ColorPB.Color = color;
	err = fColorPalette(&ColorPB);
	return ColorPB.Color;
}

word sPalette2(word color, long resID)
{
word				err;

	ColorPB.pCount = 7;
	ColorPB.Loc.h = 0;
	ColorPB.Loc.v = 0;
	ColorPB.Color = color;
	ColorPB.Row= 2;
	ColorPB.Col = 2;
	ColorPB.Mode = 0;
	ColorPB.resID = resID;
	ColorPB.resFileID = edResFileID;
	err = fColorPalette(&ColorPB);
	return ColorPB.Color;
}


handle loadIconFileData(void)
{
Handle				promptHan;
word				i;

	FilePB.pCount = 4;
	promptHan = loadEdRes(0x66, rPString);
	FilePB.sfGet2PromptRefPtr = (long) *promptHan;
	FilePB.sfGet2ReplyRecPtr = (long) &repRec;
	typeList.numEntries = 1;
	typeList.fileTypeEntries[0].flags = 0x8000;
	typeList.fileTypeEntries[0].fileType = 0xca;
	typeList.fileTypeEntries[0].auxType = 0L;
	FilePB.sfGet2FileTypeRecPtr = (long) &typeList;
	i = fLoadFileData(&FilePB);
	HLock(FilePB.fileData);
	return FilePB.fileData;
}

void changeHotSpot(privateDataPtr privP)
{
Rect				irg;
Point				thePoint;
word				x, y, done, ok;
MouseRec				theMouse;
GrafPortPtr			oldP;

	oldP = GetPort();
	StartDrawing(privP->winP);
	SetCursor(*cursor[4]);

	done = false;
	do {
		ok = false;
		theMouse = ReadMouse();
		thePoint.h = theMouse.xPos;
		thePoint.v = theMouse.yPos;
		GlobalToLocal(&thePoint);
		if (PtInRect(&thePoint, &privP->fatIRect)) {
			drawCoords(privP, thePoint.h, thePoint.v, false);
			ok = true;
		}
		if (theMouse.mouseStatus & 0x80) {
			done = true;
		}
	} while (!done);
	InitCursor();
	if (ok) {
		Pt2Pixel(thePoint.h, thePoint.v, privP, false, &x, &y);
		privP->hotSpot.h = x * 2;
		privP->hotSpot.v = y + 1;
		RedrawFatbits(privP, true);
	}
	SetPort(oldP);
	x = FlushEvents(6,0);
}
