/*
    Foundation Native Resource Editor Suite

    Marc Wolfgram,  8/ 1/92 14:49:48



    rControlList,
    rControlTemplate,
    rMenuBar,
    rMenu,
    rMenuItem,
    rCtlColorTbl,
    rWindParam1,
    rWindColor,
    rListRef,
    rItemStruct,

*/
#pragma noroot
#include <foundation.h>
#include <event.h>
#include <window.h>

/*
     8003 - Control List
     8004 - Control
     8008 - Menu Bar
     8009 - Menu
     800a - Menu Item
     800d - Control Color
     800e - Window
     8010 - Window Color
     801c - List Ref
     8028 - Item Struct

     8001 - Icon                external    Lunar
     8002 - Picture             external    Steve Chiang
     8005 - C1 Input String     script
     8006 - Pascal String       embedded
     800b - LETextBox2 String   external    Steve Bernacki
     8011 - Text Block          script
     8012 - Style Block         unknown?
     8016 - Text                script
     801d - C String            script
     8023 - C1 Output String    script
*/

/*
	Custom items
*/
struct privateData {
	word	dirty;
	handle  data;
    handle  winTitle;
    handle  winTempH;
};
typedef struct privateData **privateDataHndl;

/*
	Externals
*/
extern EventRecordPtr fEventPtr;

/*
	Globals
*/
extern word fUserID;	    /* editor's memory manager ID  			*/
extern long remHelpID;

word    edResFileID,		/* editor's resource file				*/
        shResFileID,		/* Foundation shell resource file 		*/
        fdResFileID;		/* user's Foundation.Data resource file */

fPrivateDataRec 	PrivPB;	/* callback parameter blocks...			*/
fResDataRec     	DataPB;
fResData2Rec    	Data2PB;
fResNameRec     	NamePB;
fResRefRec      	RefPB;	/*	 ___________________________________
fResCopyRec			CopyPB;		|									|
fResLinkRec			LinkPB;		|	these are not needed in the		|
fResConverterRec	ConvertPB;	|	Pascal String sample editor     |
fGetFileRec			FilePB;		|___________________________________| */

/*	========================================================================
    REM_OPEN initiates an editing session (or a selector session) and is the
    first resource specific call made to the editor.

	The editor must support four types of open, five if it has a selector.

	A new item needs to be created from scratch.
		fFlag bits 8 (F_OPENSILENT) and 9 (F_OPENDATA) are clear.
		The resID is NIL so the editor must assign the resource's new ID.
		The resource does not exist in the workfile and must be added.
		The editor MUST open an editing window.
		The editor can provide default data for the new item.

	A new item needs to be created with default data provided by another source.  The data is provided in a handle, and the new item may
		fFlag bit 8 is clear.
		fFlag bit 9 is set and default data for the new item is provided.
		The resID MIGHT be pre-assigned.
		The resource does not exist in the workfile and must be added.
		The editor MUST open an editing window.

	A new item needs to be created, but the REM should simply make it and return.
		fFlag bit 8 is set.
		fFlag bit 9 MAY BE set with default data for the new item provided.
		The resID MIGHT be pre-assigned.
		The resource does not exist in the workfile and must be added.
		The editor MUST NOT open an editing window.

	An existing resource needs to be edited.  This is the most common case.
		fFlag bits 8 and 9 are clear.
		The resID is a valid ID
		the resource to be edited exists in the workfile.
		The editor MUST open an editing window.

     The REM supports a resource selector (this sample doesn't have a selector)
     	fFlag bits 9 and 10 (F_REMSELECT) will be set.
        The list member record array that the shell would normally have used in
        the standard type window's item list is the provided data.
		The editor MUST open a selector window.

	Marc Wolfgram,  3/ 6/92 22:09:08
    ---------------------------------------------------------------
 */
word REM_OPEN(fOpenRecPtr p)
{
word            retVal,
                retErr;
Handle	        title;
privateDataHndl private;
GrafPortPtr     winP;

    /*
    	first see if we edit this type...
	    (multi-type editors will have to case those types it supports)
	*/

    if (p->resType != rPString)
        return resInvalidTypeOrID;

	/*
		First handle a "new resource" check.  First we will see if there
		is data provided and either load it or the editor's built-in
		default (ID 1).  Then we add the resource, posibly getting a new
		ID in the process.  Last, if the request was silent, we're done
		and hould just release the resource because something else needs
		needs it.
	*/

	if (p->resID || (p->fFlag & (F_OPENSILENT | F_OPENDATA))) {

		if (p->fFlag & F_OPENDATA) 		/* data is provided - handle is ours */
        	DataPB.resData = p->Data;

        else {							/* no data, load default from editor */
        	DataPB.pCount = 6;
			DataPB.resType = rPString;
			DataPB.resID = 0x00000001L;	    /* just an arbitrary value */
			DataPB.resFileID = edResFileID;
			retErr = fLoadResource(&DataPB);

        	RefPB.pCount = 3;				/* detach default so we own it		*/
			RefPB.resType = rPString;
			RefPB.resID = 0x00000001L;
			RefPB.resFileID = edResFileID;
			retErr = fDetachResource(&DataPB);
		}
        DataPB.pCount = 4;
		DataPB.resID = p->resID;		/* if null, then Add returns ID added */
		DataPB.special = 0;				/* no attributes assigned */
		retErr = fAddResource(&DataPB);

        p->resID = DataPB.resID;		/* this may change so pass it back */

        if (p->fFlag & F_OPENSILENT) {
        	RefPB.pCount = 2;
			RefPB.resType = rPString;
			RefPB.resID = DataPB.resID;
			retErr = fReleaseResource(&DataPB);

           	return 0;
        }
	}

	/*
    	If we get here, we have definitly got a valid resource to edit
	    in the workfile, and we move into "normal open" mode:
		    Load the editor's window converted to a handle reference
		    Get the official window title from the shell
			Open the editor's window (hidden for appearance only)
			Set the window's private data interface structure in the shell
		    Load the resource we're to edit
			Assign the resource and title handles in our private data handle
    */

    DataPB.pCount = 5;
	DataPB.resType = rWindParam1;
	DataPB.resID = 0x00000001L;
	DataPB.special = 0;
	DataPB.resFileID = edResFileID;
	retErr = fSpecialMagic(&DataPB);
	DataPB.special = 1;
	retErr = fSpecialMagic(&DataPB);
    (**private).winTempH = DataPB.resData;	/* is valid since we still have */

	title = NewHandle(128L, fUserID, 0x8018, 0L);

	NamePB.pCount = 3;
	NamePB.resType = rPString;
	NamePB.resID = p->resID;
	NamePB.resName = (Pointer) *title;
	retErr = fGetWindowTitle(&NamePB);
	(**private).winTitle = title;			/* private floating around here */

    winP = NewWindow2(*title, 0L, 0L, 0L, 1, DataPB.resData, rWindParam1);

    (Handle) private = NewHandle(10L, fUserID, 0x0018, 0L); /* or whatever size... */

	PrivPB.pCount = 7;
	(GrafPortPtr) PrivPB.winPtr = winP;
	PrivPB.remTaskMask = 0L;    /* use standard task mask */
	PrivPB.remSignature = 0;    /* my personal signature - no significance */
	PrivPB.Data = (Handle) private;
    PrivPB.groupSignature = 0x0020;
    PrivPB.resType = rPString;
    PrivPB.resID = p->resID;
    fAddPrivateData(&PrivPB);

    DataPB.pCount = 3;
	DataPB.resType = rPString;
	DataPB.resID = p->resID;
	retErr = fLoadResource(&DataPB);

    (**private).dirty = 0;				/* post-referencing this handle */
    (**private).data = DataPB.resData;	/* is valid since we still have */

	/*
		Now we set the data into the TE control, set the window colors,
		and show the window, completing the REM_OPEN call.
	*/

    return  0;
}

word REM_CLOSE(fCloseRecPtr p)
{
word            retErr;
GrafPortPtr     winP;
privateDataHndl private;

    winP = (GrafPortPtr) p->windowPtr;

    PrivPB.pCount = 3;
    (GrafPortPtr) PrivPB.winPtr = winP;
    fGetPrivateData(&PrivPB);
    (handle) private = PrivPB.Data;

    DataPB.pCount = 5;
	DataPB.resType = rWindParam1;
    DataPB.resData = (**private).winTempH;	/* is valid since we still have */
	DataPB.special = 3;
	DataPB.resFileID = edResFileID;
	retErr = fSpecialMagic(&DataPB);
    DisposeHandle((**private).winTitle);
    DisposeHandle((**private).data);
    DisposeHandle(PrivPB.Data);

    return  0;
}

word REM_WRITE(fCloseRecPtr p)
{
    return  0;
}

word REM_EVENT(fEventRecPtr p)
{
    return  0;
}

word REM_ACTIVATE(fActivateRecPtr p)
{
privateDataHndl private;

	PrivPB.pCount = 4;
	(long) PrivPB.winPtr = fEventPtr->wmTaskData;
	fGetPrivateData(&PrivPB);

	if (p->fFlag & F_ACTIVATE)
		p->fFlag |= (F_UNDO + F_CLIP + F_CLEAR + F_SELECT + F_MENUAPPLY);

    return  0;
}

/*	========================================================================
    REM_GETLINK is an extension to the shell's dependency knowlege.  Pascal
    Strings don't have dependents.  The supports REM_GETLINK rFlag bit 6 in
    the remStartRes is clear.

	Marc Wolfgram,  3/ 7/92  1:10:48
*/
word REM_GETLINK(fLinkRecPtr p)
{
    return  0;
}

/*	========================================================================
    REM_VIDMODE lets the editor know when it's world is changing.  We didn't
    see a valid reason for a 320 mode Pascal String editor, but decided to
    support one anyway.

	Marc Wolfgram,  3/ 7/92  1:03:41
*/
word REM_VIDMODE(fVidModeRecPtr p)
{
    return  0;
}

/*	========================================================================
    REM_PRINT must be supported entirely by the editor.  Why would we want
    to print a Pascal String?  We don't.

	Marc Wolfgram,  3/ 7/92  1:07:20
*/
word REM_PRINT(fCloseRecPtr p)
{
    return  0;
}

/*	========================================================================
    REM_STARTUP is called only when the REM is first loaded.

    The REM should do whatever it needs to do to setup globals, etc.

    This is the only time when the various Foundation and REM resource file
    ID's are passed to the REM.  Also, the REM's specific memory manager ID
    is passed here - READ THE WARNING IN REM_SHUTDOWN!

	Marc Wolfgram,  3/ 6/92 20:27:26
    ---------------------------------------------------------------
*/
word REM_STARTUP(fStartStopRecPtr p)
{
    fUserID = p->edUserID;
    edResFileID = p->edResFileID;
    shResFileID = p->shResFileID;
    fdResFileID = p->fdResFileID;

    remHelpID = 1L; /* stuff a rText ID into the editors header help field */

    return  0;
}

/*	========================================================================
    REM_SHUTDOWN is called when an editor is unloaded.

    WARNING: The REM must release any memory alloceated at startup during
             the shutdown call.  There is no guarantee that once the editor
             is released that it will be reloaded.

	Marc Wolfgram,  3/ 6/92 20:41:12
    ---------------------------------------------------------------
*/
word REM_SHUTDOWN(fStartStopRecPtr p)
{
	DisposeAll(fUserID);	/* before assuming that this simplicity is 	*/
    return  0;				/* all you need, read TBR-1, page 12-23!	*/
}
