
/*
 *  LOAD.C
 */

#include "defs.h"

Prototype void LoadProject(char *);
Prototype void ScanProject(short, FILE *, long);
Prototype void ResolveLinks(void);
Prototype void UnResolveIDs(void);
Prototype void ResolveIDs(void);

void
LoadProject(name)
char *name;
{
    FILE *fi;

    UnResolveIDs();
    if ((fi = fopen(name, "r")) == NULL) {
	printf("unable to open %s\n", name);
	return;
    }
    ScanProject(0, fi, -1);
    fclose(fi);
    ResolveIDs();
}

void
ScanProject(state, fi, endOffset)
short state;
FILE *fi;
long endOffset;
{
    ProjEntry pe;
    long subEndOffset;

    while (ftell(fi) != endOffset) {
	if (fread(&pe, sizeof(pe), 1, fi) != 1)
	    return;

	subEndOffset = ftell(fi) + pe.pe_Len;

	if (DDebug)
	    printf("TYPE %d ENDS %08lx\n", pe.pe_Type, subEndOffset);

	switch(pe.pe_Type) {
	case PT_PROJECT:
	    ScanProject(pe.pe_Type, fi, subEndOffset);
	    ResolveLinks();
	    break;
	case PT_HEADER:
	    fread(&Ph, pe.pe_Len, 1, fi);
	    break;
	case PT_REGION:
	    if (CurRegion) {
		puts("ScanError: region in region!");
		break;
	    }
	    CurRegion = AllocTplRegion();
	    ScanProject(pe.pe_Type, fi, subEndOffset);

	    /*
	     *	Handle list copy if RGT_CYCLE XXX
	     */

	    if (CurRegion->rg_Type == RGT_SELLIST || CurRegion->rg_Type == RGT_CYCLE) {
		short cnt;
		MaxNode *mn;

		cnt = 0;
		for (mn = GetHead(&CurRegion->rg_ListSet); mn; mn = GetSucc(mn)) {
		    ++cnt;
		}
		CurRegion->rg_CycleAry = zalloc(sizeof(char *) * (cnt + 1));
		cnt = 0;
		for (mn = GetHead(&CurRegion->rg_ListSet); mn; mn = GetSucc(mn)) {
		    CurRegion->rg_CycleAry[cnt++] = mn->ln_Name;
		}
	    }
	    CurRegion = NULL;
	    break;
	case PT_NAME:
	    {
		char *str;

		if (pe.pe_Len >= sizeof(TmpBuf))
		    break;
		fread(TmpBuf, pe.pe_Len, 1, fi);
		TmpBuf[pe.pe_Len] = 0;
		str = strdup(TmpBuf);

		switch(state) {
		case PT_REGION:
		    CurRegion->rg_Node.ln_Name = str;
		    break;
		case PT_TEXTATTR:
		    CurRegion->rg_TextAttr.ta_Name = str;
		    break;
		case PT_DATABASE:
		    CurRegion->rg_DataBase = str;
		    break;
		case PT_LISTREF:
		    CurRegion->rg_ListRef = str;
		    break;
		case PT_LISTSET:
		    AddNode(&CurRegion->rg_ListSet, str, 0);
		    break;
		case PT_DEFTEXT:
		    CurRegion->rg_DefText = str;
		    break;
		case PT_LABTEXT:
		    CurRegion->rg_LabText = str;
		    break;
		default:
		    free(str);
		    break;
		}
	    }
	    break;
	case PT_BOX:
	    {
		Box box;

		fread(&box, sizeof(box), 1, fi);
		switch(state) {
		case PT_REGION:
		    CurRegion->rg_Box = box;
		    break;
		default:
		    break;
		}
	    }
	    break;
	case PT_MINMAX:
	    {
		Box box;

		fread(&box, sizeof(box), 1, fi);
		switch(state) {
		case PT_REGION:
		    CurRegion->rg_MinMax = box;
		    break;
		default:
		    break;
		}
	    }
	    break;
	case PT_MAXBUFLEN:
	    if (state == PT_REGION) {
		long val;
		fread(&val, sizeof(val), 1, fi);
		CurRegion->rg_MaxBufLen = val;
	    }
	    break;
	case PT_ID:
	    if (state == PT_REGION) {
		long val;
		fread(&val, sizeof(val), 1, fi);
		CurRegion->rg_Id = val;
	    }
	    break;
	case PT_REGLL:
	    if (state == PT_REGION) {
		long val;
		fread(&val, sizeof(val), 1, fi);
		CurRegion->rg_LinkLeft = (TplRegion *)val;
	    }
	    break;
	case PT_REGLR:
	    if (state == PT_REGION) {
		long val;
		fread(&val, sizeof(val), 1, fi);
		CurRegion->rg_LinkRight = (TplRegion *)val;
	    }
	    break;
	case PT_REGLU:
	    if (state == PT_REGION) {
		long val;
		fread(&val, sizeof(val), 1, fi);
		CurRegion->rg_LinkUp = (TplRegion *)val;
	    }
	    break;
	case PT_REGLD:
	    if (state == PT_REGION) {
		long val;
		fread(&val, sizeof(val), 1, fi);
		CurRegion->rg_LinkDown = (TplRegion *)val;
	    }
	    break;
	case PT_LOCKTO:
	    if (state == PT_REGION) {
		long val;
		fread(&val, sizeof(val), 1, fi);
		CurRegion->rg_LockedTo = (TplRegion *)val;
	    }
	    break;
	case PT_FLAGS:
	    if (state == PT_REGION) {
		long val;
		fread(&val, sizeof(val), 1, fi);
		CurRegion->rg_Flags = val;
	    }
	    break;
	case PT_TYPE:
	    if (state == PT_REGION) {
		long val;
		fread(&val, sizeof(val), 1, fi);
		CurRegion->rg_Type = val;
		if (DDebug)
		    printf("PT_TYPE VAL %d\n", val);
	    }
	    break;
	case PT_EXCLID:
	    if (state == PT_REGION) {
		long val;
		fread(&val, sizeof(val), 1, fi);
		CurRegion->rg_ExclGroup = val;
	    }
	    break;
	case PT_DATABASE:
	case PT_LISTREF:
	case PT_LISTSET:
	case PT_DEFTEXT:
	case PT_LABTEXT:
	case PT_TEXTATTR:
	    ScanProject(pe.pe_Type, fi, subEndOffset);
	    break;
	case PT_YSIZE:
	    if (state == PT_TEXTATTR) {
		long val;
		fread(&val, sizeof(val), 1, fi);
		CurRegion->rg_TextAttr.ta_YSize = val;
	    }
	    break;
	case PT_END:
	    return;
	default:
	    break;
	}

	if (ftell(fi) != subEndOffset)
	    fseek(fi, subEndOffset, 0);
    }
}

void
ResolveLinks()
{
    TplRegion *rg;

    for (rg = GetHead(&RegList); rg; rg = GetSucc(&rg->rg_Node)) {
	if (DDebug)
	    printf("TG TYPE %d\n", rg->rg_Type);
	rg->rg_LinkLeft = IdToRegion((long)rg->rg_LinkLeft);
	rg->rg_LinkRight= IdToRegion((long)rg->rg_LinkRight);
	rg->rg_LinkUp	= IdToRegion((long)rg->rg_LinkUp);
	rg->rg_LinkDown = IdToRegion((long)rg->rg_LinkDown);
	rg->rg_LockedTo = IdToRegion((long)rg->rg_LockedTo);
    }
}

void
ResolveIDs()
{
    TplRegion *rg;

    for (IdNo = 0, rg = GetHead(&RegList); rg; rg = GetSucc(&rg->rg_Node)) {
	rg->rg_Id = ++IdNo;
    }
}

void
UnResolveIDs()
{
    TplRegion *rg;

    for (IdNo = 0, rg = GetHead(&RegList); rg; rg = GetSucc(&rg->rg_Node)) {
	rg->rg_Id = 0;
    }
}

