
/*
 *  SAVEC.C
 */

#include "defs.h"

Prototype void SaveProjectAsSrc(char *);
Prototype void DeclareHeaders(FILE *);
Prototype void DeclareNG(FILE *, short);
Prototype void DeclareWIN(FILE *);
Prototype void DeclareRG(FILE *, TplRegion *);
Prototype void DeclareInitGads(FILE *);
Prototype void DeclareFreeGads(FILE *);

static char *RgtKindAry[] = { "INVISIBLE", "BUTTON_KIND", "STRING_KIND", "LISTVIEW_KIND", "CYCLE_KIND" };

void
SaveProjectAsSrc(name)
char *name;
{
    FILE *fo;
    TplRegion *rg;

    if (fo = fopen(name, "w")) {
	short numRG = 0;

	fprintf(fo, "\n"
		    "/*\n"
		    " * %s\n"
		    " *\n"
		    " * MACHINE GENERATED\n"
		    " */\n\n",

		    name
		);

	DeclareHeaders(fo);

	for (rg = GetHead(&RegList); rg; rg = GetSucc(&rg->rg_Node)) {
	    if (rg->rg_Type)
		++numRG;
	}
	DeclareNG(fo, numRG);
	DeclareWIN(fo);

	for (rg = GetHead(&RegList); rg; rg = GetSucc(&rg->rg_Node)) {
	    if (rg->rg_Type) {
		DeclareRG(fo, rg);
	    }
	}
	DeclareInitGads(fo);
	DeclareFreeGads(fo);
	fclose(fo);
    }
}

void
DeclareHeaders(fo)
FILE *fo;
{
    fprintf(fo,
	"#ifndef NO_GAD_HEADERS\n"
	"#include <exec/types.h>\n"
	"#include <exec/lists.h>\n"
	"#include <intuition/intuition.h>\n"
	"#include <intuition/screens.h>\n"
	"#include <intuition/gadgetclass.h>\n"
	"#include <libraries/gadtools.h>\n"
	"#include <clib/gadtools_protos.h>\n"
	"#endif\n"
	"\n"
    );
}

void
DeclareNG(fo, nrg)
FILE *fo;
short nrg;
{
    TplRegion *rg;
    short i;

    for (i = 0, rg = GetHead(&RegList); rg; rg = GetSucc(&rg->rg_Node)) {
	if (rg->rg_Type) {
	    fprintf(fo, "#define NG_%s (NGAry + %d)\n", rg->rg_Node.ln_Name, i);
	    ++i;
	}
    }
    for (i = 0, rg = GetHead(&RegList); rg; rg = GetSucc(&rg->rg_Node)) {
	if (rg->rg_Type) {
	    fprintf(fo, "#define GAD_%s %d\n", rg->rg_Node.ln_Name, i);
	    ++i;
	}
    }

    fprintf(fo, "\nstruct NewGadget NGAry[%d] = {\n", nrg);
    for (rg = GetHead(&RegList); rg; rg = GetSucc(&rg->rg_Node)) {
	if (rg->rg_Type) {
	    fprintf(fo, "    { %d,%d,%d,%d,",
		rg->rg_Box.bo_Xs,
		rg->rg_Box.bo_Ys,
		rg->rg_Box.bo_Xe - rg->rg_Box.bo_Xs + 1,
		rg->rg_Box.bo_Ye - rg->rg_Box.bo_Ys + 1
	    );

	    if (rg->rg_LabText)
		fprintf(fo, "\"%s\",", rg->rg_LabText);
	    else
		fprintf(fo, "(void *)0L,");

	    fprintf(fo, "(void *)0L,GAD_%s,0x%04x,(void *)0L }%s\n",
		rg->rg_Node.ln_Name, rg->rg_Flags,
		(GetSucc(&rg->rg_Node) ? "," : "")
	    );
	}
    }
    fprintf(fo, "};\n\n");
}

void
DeclareWIN(fo)
FILE *fo;
{
    fprintf(fo, "#define WIN_LEFT   %d\n", Ph.ph_WinDim.bo_Xs);
    fprintf(fo, "#define WIN_TOP    %d\n", Ph.ph_WinDim.bo_Ys);
    fprintf(fo, "#define WIN_WIDTH  %d\n", Ph.ph_WinDim.bo_Xe - Ph.ph_WinDim.bo_Xs);
    fprintf(fo, "#define WIN_HEIGHT %d\n", Ph.ph_WinDim.bo_Ye - Ph.ph_WinDim.bo_Ys);
    fprintf(fo, "\n");
}

void
DeclareRG(fo, rg)
FILE *fo;
TplRegion *rg;
{
    fprintf(fo, "struct Gadget *Gad_%s;\n", rg->rg_Node.ln_Name);

    switch(rg->rg_Type) {
    case RGT_BUTTON:
	break;
    case RGT_ENTRY:
	fprintf(fo, "char *Buf_%s;\n", rg->rg_Node.ln_Name);
	fprintf(fo, "char *DefText_%s = ", rg->rg_Node.ln_Name);
	if (rg->rg_DefText && rg->rg_DefText[0])
	    fprintf(fo, "\"%s\";\n", rg->rg_DefText);
	else
	    fprintf(fo, "(char *)0L;\n");
	break;
    case RGT_SELLIST:
	{
	    MaxNode *mn;
	    short i;
	    short cnt;

	    for (cnt = 0, mn = GetHead(&rg->rg_ListSet); mn; ++cnt, mn = GetSucc(mn));

	    if (cnt) {
		fprintf(fo, "extern struct MinList List_%s;\n", rg->rg_Node.ln_Name);
		fprintf(fo, "long SelNo_%s = %d;\n", rg->rg_Node.ln_Name, ((rg->rg_DefText) ? atoi(rg->rg_DefText) : 0));
		fprintf(fo, "struct Node NodeAry_%s[%d] = {\n", rg->rg_Node.ln_Name, cnt);

		for (i = 0, mn = GetHead(&rg->rg_ListSet); mn; ++i, mn = GetSucc(mn)) {
		    fprintf(fo, "    { ");
		    if (GetSucc(mn))
			fprintf(fo, "NodeAry_%s + %d, ", rg->rg_Node.ln_Name, i + 1);
		    else
			fprintf(fo, "(struct Node *)&List_%s.mlh_Tail, ", rg->rg_Node.ln_Name);
		    if (GetPred(mn))
			fprintf(fo, "NodeAry_%s + %d, ", rg->rg_Node.ln_Name, i - 1);
		    else
			fprintf(fo, "(struct Node *)&List_%s.mlh_Head, ", rg->rg_Node.ln_Name);
		    fprintf(fo, "0, 0, \"%s\" }%s\n", mn->ln_Name, (i == cnt - 1) ? "" : ",");
		}
		fprintf(fo, "};\n\n");
	    }
	    fprintf(fo, "struct MinList List_%s = { ", rg->rg_Node.ln_Name);
	    if (cnt)
		fprintf(fo, "&NodeAry_%s[0], ", rg->rg_Node.ln_Name);
	    else
		fprintf(fo, "(struct MinNode *)&List_%s.mlh_Tail, ", rg->rg_Node.ln_Name);
	    fprintf(fo, "(void *)0L, ");
	    if (cnt)
		fprintf(fo, "&NodeAry_%s[%d]", rg->rg_Node.ln_Name, cnt - 1);
	    else
		fprintf(fo, "(struct MinNode *)&List_%s.mlh_Head", rg->rg_Node.ln_Name);
	    fprintf(fo, " };\n");
	}
	break;
    case RGT_CYCLE:
	{
	    short i = 0;

	    fprintf(fo, "char *StatAry_%s[] = { ", rg->rg_Node.ln_Name);
	    if (rg->rg_CycleAry) {
		char *ptr;
		for (; ptr = rg->rg_CycleAry[i]; ++i)
		    fprintf(fo, "%s\"%s\"", ((i) ? ", " : ""), ptr);
	    }
	    fprintf(fo, "%s(void *)0 };\n", ((i) ? ", " : ""));
	    fprintf(fo, "char **Ary_%s = StatAry_%s;\n",
		rg->rg_Node.ln_Name,
		rg->rg_Node.ln_Name
	    );
	    fprintf(fo, "long SelNo_%s = %d;\n", rg->rg_Node.ln_Name, ((rg->rg_DefText) ? atoi(rg->rg_DefText) : 0));
	}
	break;
    }
}

/*
 *  InitGads and FreeGads
 */

void
DeclareInitGads(fo)
FILE *fo;
{
    short i;
    short j;
    TplRegion *rg;

    fprintf(fo, "\n\n"
		"struct Gadget *GList;\n"
		"struct VisualInfo *VisInfo;\n"
		"\n"
	    );

    fprintf(fo, "\n\n"
		"struct Gadget *\n"
		"InitGads(scr)\n"
		"struct Screen *scr;\n"
		"{\n"
		"    struct Gadget *gad;\n"
		"    short i;\n"
		"\n"
	    );
    fprintf(fo, "    GList = (void *)0;\n");

    /*
     *	Step 1, allocate VisInfo
     */

    fprintf(fo, "    if ((VisInfo = GetVisualInfo(scr, TAG_END)) == NULL)\n");
    fprintf(fo, "\treturn((void *)0L);\n");

    /*
     *	Step 2, apply to NGAry ng_VisualInfo & ng_TextAttr (from screen)
     */

    fprintf(fo, "\n    {\n");
    fprintf(fo, "\tstruct NewGadget *ng;\n");
    fprintf(fo, "\tfor (i = 0, ng = NGAry; i < sizeof(NGAry)/sizeof(NGAry[0]); ++i, ++ng) {\n");
    fprintf(fo, "\t    ng->ng_VisualInfo = VisInfo;\n");
    fprintf(fo, "\t    ng->ng_TextAttr = scr->Font;\n");
    fprintf(fo, "\t}\n");
    fprintf(fo, "    }\n");

    /*
     *	Step 3, allocate GList
     */

    fprintf(fo, "    if ((gad = CreateContext(&GList)) == NULL)\n");
    fprintf(fo, "\treturn((void *)0L);\n");

    /*
     *	Step 4, allocate gadgets
     *
     *	Allocation is a two pass process.  The first pass deals with those
     *	gadgets that do not depend on other gadgets.  The second pass
     *	deals with those gadgets that DO depend on other gadgets.
     */

    for (j = 0; j < 2; ++j) {
	for (i = -1, rg = GetHead(&RegList); rg; rg = GetSucc(&rg->rg_Node)) {
	    if (rg->rg_Type) {
		++i;
		if (j == 0) {
		    rg->rg_Flags &= ~RGF_DEFERED;
		    if (rg->rg_LockedTo) {
			rg->rg_Flags |= RGF_DEFERED;
			continue;
		    }
		} else {
		    if ((rg->rg_Flags & RGF_DEFERED) == 0)
			continue;
		}
		fprintf(fo, "    Gad_%s = gad = CreateGadget(%s, gad, NGAry + %d,\n",
		    rg->rg_Node.ln_Name,
		    RgtKindAry[rg->rg_Type],
		    i
		);

		switch(rg->rg_Type) {
		case RGT_BUTTON:
		    break;
		case RGT_ENTRY:
		    fprintf(fo, "\tGTST_MaxChars, %d,\n", rg->rg_MaxBufLen);
		    fprintf(fo, "\tGTST_String, DefText_%s,\n", rg->rg_Node.ln_Name);
		    break;
		case RGT_SELLIST:
		    fprintf(fo, "\tGTLV_Labels, &List_%s,\n", rg->rg_Node.ln_Name);
		    fprintf(fo, "\tGTLV_Selected, SelNo_%s,\n", rg->rg_Node.ln_Name);
		    if (rg->rg_LockedTo)
			fprintf(fo, "\tGTLV_ShowSelected, Gad_%s,\n", rg->rg_LockedTo->rg_Node.ln_Name);
		    break;
		case RGT_CYCLE:
		    fprintf(fo, "\tGTCY_Labels, Ary_%s,\n", rg->rg_Node.ln_Name);
		    fprintf(fo, "\tGTCY_Active, SelNo_%s,\n", rg->rg_Node.ln_Name);
		    break;
		}
		fprintf(fo, "\tTAG_END\n");
		fprintf(fo, "    );\n");
		fprintf(fo, "    if (gad == NULL)\n");
		fprintf(fo, "\treturn(NULL);\n");

		switch(rg->rg_Type) {
		case RGT_ENTRY:
		    fprintf(fo, "    Buf_%s = ((struct StringInfo *)gad->SpecialInfo)->Buffer;\n", rg->rg_Node.ln_Name);
		}
		fprintf(fo, "\n");
	    }
	}
    }

    /*
     *	return GList
     */

    fprintf(fo, "    return(GList);\n");
    fprintf(fo, "}\n\n");
}

/*
 *  Free the GList and return
 */

void
DeclareFreeGads(fo)
FILE *fo;
{
    fprintf(fo, "\n\n"
		"void\n"
		"FreeGads(void)\n"
		"{\n"
		"    FreeGadgets(GList);\n"
		"    if (VisInfo)\n"
		"        FreeVisualInfo(VisInfo);\n"
		"    VisInfo = NULL;\n"
		"    GList = NULL;\n"
		"}\n"
	    );
}

