
/*
 *  MAIN.C
 *
 *  TPLEDIT [project]
 */

#include "defs.h"

Prototype void HandleMenu(IMsg *);
Prototype void BoxComplete();
Prototype void Title(char *);
Prototype void TitleState(void);
Prototype void TitleXY(short, short);
Prototype TplRegion *SetCurRegion(TplRegion *);


Prototype char	ProjName[256];
Prototype char	ProjSrcName[256];
Prototype char	TmpBuf[256];
Prototype Window    *Win;
Prototype Screen    *Scr;
Prototype NewGadget Ng;
Prototype NewMenu   Nm[];
Prototype Gadget    *GList;
Prototype Menu	    *GMenu;
Prototype List	    RegList;
Prototype List	    PPList;
Prototype TplRegion *CurRegion;
Prototype short     CurState;

Prototype ProjHeader	Ph;
Prototype short     NotDone;
Prototype short     DDebug;
Prototype uword     IdNo;
Prototype short     NewType;
Prototype long	    NewFlags;

void myexit(void);

NewMenu     Nm[] = {
    {	NM_TITLE,   "Project" },
    {	NM_ITEM,    "Save",         NULL, 0, 0, MENU_PROJ_SAVE      },
    {	NM_ITEM,    "SaveC",        NULL, 0, 0, MENU_PROJ_SAVESRC   },
    {	NM_ITEM,    "SaveAs",       NULL, 0, 0, MENU_PROJ_SAVEAS    },
    {	NM_ITEM,    "SaveAsC",      NULL, 0, 0, MENU_PROJ_SAVEASSRC },
    {	NM_ITEM,    "Load",         NULL, 0, 0, MENU_PROJ_LOAD      },
    {	NM_ITEM,    "Merge",        NULL, 0, 0, MENU_PROJ_MERGE     },
    {	NM_ITEM,    "Quit",         NULL, 0, 0, MENU_PROJ_QUIT      },

    {	NM_TITLE,   "Linking" },
    {	NM_ITEM,    "LockTo",       NULL, 0, 0, MENU_LINK_LOCK      },

    {	NM_TITLE,   "Snap" },
    {	NM_ITEM,    "1",       NULL, 0, 0, MENU_SNAP+1      },
    {	NM_ITEM,    "2",       NULL, 0, 0, MENU_SNAP+2      },
    {	NM_ITEM,    "4",       NULL, 0, 0, MENU_SNAP+4      },
    {	NM_ITEM,    "6",       NULL, 0, 0, MENU_SNAP+6      },
    {	NM_ITEM,    "8",       NULL, 0, 0, MENU_SNAP+8      },
    {	NM_ITEM,    "10",      NULL, 0, 0, MENU_SNAP+10     },
    {	NM_ITEM,    "12",      NULL, 0, 0, MENU_SNAP+12     },
    {	NM_ITEM,    "14",      NULL, 0, 0, MENU_SNAP+14     },
    {	NM_ITEM,    "16",      NULL, 0, 0, MENU_SNAP+16     },
    {	NM_ITEM,    "18",      NULL, 0, 0, MENU_SNAP+18     },
    {	NM_ITEM,    "20",      NULL, 0, 0, MENU_SNAP+20     },


    {	NM_END	}
};

char	    ProjName[256];
char	    ProjSrcName[256];
char	    TitleBuf[256];
char	    TmpBuf[256];
Window	    *Win;
Screen	    *Scr;
NewGadget   Ng;
Gadget	    *GList;
Menu	    *GMenu;
List	    RegList;
List	    PPList;
TplRegion   *CurRegion;
short	    CurState;
short	    ButState;
short	    DDebug;
short	    CoorSnap = 1;
uword	    IdNo;
short	    NewType  = 0;
long	    NewFlags = 0x0001;
long	    WinMask;

ProjHeader  Ph;

short	    NotDone = 1;
Box	    TBox;
short	    TX, TY;

main(ac, av)
char *av[];
{
    short i;

    NewList(&RegList);
    NewList(&PPList);

    atexit(myexit);

    for (i = 1; i < ac; ++i) {
	char *ptr = av[i];
	if (*ptr != '-') {
	    strcpy(ProjName, ptr);
	    continue;
	}
	ptr += 2;
	switch(ptr[-1]) {
	case 'd':
	    ++DDebug;
	    break;
	}
    }

    if ((Scr = LockPubScreen(NULL)) == NULL)
	exit(20);
    if ((Ng.ng_VisualInfo = GetVisualInfo(Scr, TAG_END)) == NULL)
	exit(22);

    GMenu = CreateMenus(Nm,
	GTMN_FullMenu, 1,
	TAG_END
    );
    if (GMenu == NULL)
	exit(24);

    if (LayoutMenus(GMenu, Ng.ng_VisualInfo, TAG_END) == 0)
	exit(25);

    Ph.ph_WinDim.bo_Xs	  = 0;
    Ph.ph_WinDim.bo_Ys	  = 0;
    Ph.ph_WinDim.bo_Xe	  = 200;
    Ph.ph_WinDim.bo_Ye	  = 200;
    Ph.ph_MinMaxDim.bo_Xs = 32;
    Ph.ph_MinMaxDim.bo_Ys = 32;
    Ph.ph_MinMaxDim.bo_Xe = -1;
    Ph.ph_MinMaxDim.bo_Ye = -1;

    if (OpenEditWindow() < 0)
	exit(26);

    if (ProjName[0] == 0)
	strcpy(ProjName, "unnamed");
    else
	LoadProject(ProjName);

    MakeAllGadgets();

    /*
     *	Open Window
     */

    Win = OpenWindowTags(NULL,
	WA_Flags,   WFLG_DRAGBAR|WFLG_DEPTHGADGET|WFLG_CLOSEGADGET|
		    WFLG_SIMPLE_REFRESH|WFLG_REPORTMOUSE|
		    WFLG_SIZEGADGET,

	WA_IDCMP,   IDCMP_NEWSIZE|IDCMP_MOUSEBUTTONS|IDCMP_GADGETDOWN|
		    IDCMP_GADGETUP|IDCMP_MENUPICK|IDCMP_VANILLAKEY|
		    IDCMP_RAWKEY|IDCMP_CHANGEWINDOW|IDCMP_CLOSEWINDOW|
		    IDCMP_REFRESHWINDOW|IDCMP_MOUSEMOVE|IDCMP_ACTIVEWINDOW,

	WA_Left,    Ph.ph_WinDim.bo_Xs,
	WA_Top,     Ph.ph_WinDim.bo_Ys,
	WA_Width,   Ph.ph_WinDim.bo_Xe - Ph.ph_WinDim.bo_Xs,
	WA_Height,  Ph.ph_WinDim.bo_Ye - Ph.ph_WinDim.bo_Ys,
	WA_Title,   ProjName,
	WA_MinWidth,  Ph.ph_MinMaxDim.bo_Xs,
	WA_MinHeight, Ph.ph_MinMaxDim.bo_Ys,
	WA_MaxWidth,  Ph.ph_MinMaxDim.bo_Xe,
	WA_MaxHeight, Ph.ph_MinMaxDim.bo_Ye,
	WA_AutoAdjust, 1,
	WA_PubScreen, NULL,
	WA_PubScreenFallBack, 1,
	WA_Gadgets, GList,
	TAG_END
    );

    if (Win == NULL)
	exit(27);

    WinMask = 1 << Win->UserPort->mp_SigBit;

    SetMenuStrip(Win, GMenu);

    Title("TPLEDIT 1.0 PUBLIC DOMAIN, Matthew Dillon");

    /*
     *	Main Loop
     */

    GT_RefreshWindow(Win, NULL);

    while (NotDone) {
	IMsg *im;
	long mask;

	mask = Wait(WinMask | EWinMask | SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_E | SIGBREAKF_CTRL_F);

	if (mask & SIGBREAKF_CTRL_C)
	    NotDone = 0;

	if (Win) {
	    while (im = GT_GetIMsg(Win->UserPort)) {
		short saveX = im->MouseX;
		short saveY = im->MouseY;

		im->MouseX = (saveX + (CoorSnap >> 1)) / CoorSnap * CoorSnap;
		im->MouseY = (saveY + (CoorSnap >> 1)) / CoorSnap * CoorSnap;

		if (DDebug && im->Class != IDCMP_MOUSEMOVE)
		    printf("CLASS %08lx CODE %d IA=%08lx\n", im->Class, im->Code, im->IAddress);

		switch(im->Class) {
		case IDCMP_ACTIVEWINDOW:
		    ClearMenuStrip(EWin);
		    SetMenuStrip(Win, GMenu);
		    break;
		case IDCMP_CHANGEWINDOW:
		    Ph.ph_WinDim.bo_Xs = Win->LeftEdge;
		    Ph.ph_WinDim.bo_Ys = Win->TopEdge;
		    Ph.ph_WinDim.bo_Xe = Win->LeftEdge + Win->Width;
		    Ph.ph_WinDim.bo_Ye = Win->TopEdge + Win->Height;
		    break;
		case IDCMP_CLOSEWINDOW:
		    NotDone = 0;
		    break;
		case IDCMP_REFRESHWINDOW:
		    GT_BeginRefresh(Win);
		    GT_EndRefresh(Win, TRUE);
		    break;
		case IDCMP_GADGETDOWN:
		case IDCMP_GADGETUP:
		    if (SetCurRegion(FindRegionByGad((Gadget *)im->IAddress))) {
			UpdateEWinInfo(CurRegion);
			TitleState();
		    }
		    break;
		case IDCMP_RAWKEY:	/*  HELP KEY		*/
		    break;
		case IDCMP_MENUPICK:
		    HandleMenu(im);
		    break;
		case IDCMP_MOUSEBUTTONS:
		    switch(im->Code) {
		    case SELECTDOWN:
			switch(CurState) {
			case STATE_NEWREGION:
			    TBox.bo_Xs = TBox.bo_Xe = im->MouseX;
			    TBox.bo_Ys = TBox.bo_Ye = im->MouseY;
			    DrawBox(&TBox);
			    TitleState();
			    ButState |= 4;
			    break;
			case STATE_DELREGION:
			    if (SetCurRegion(FindRegion(saveX, saveY))) {
				DeleteTplRegion(CurRegion);
				ReMakeEverything();
			    }
			    break;
			case STATE_MOVEREGION:
			case STATE_SIZEREGION:
			    if (SetCurRegion(FindRegion(saveX, saveY))) {
				TX = im->MouseX;
				TY = im->MouseY;
				UpdateEWinInfo(CurRegion);
				TBox = CurRegion->rg_Box;
				DrawBox(&TBox);
				TitleState();
				ButState |= 4;
			    }
			    break;
			case STATE_LINKREGION:
			    if (CurRegion) {
				TplRegion *tr;

				if (tr = FindRegion(saveX, saveY)) {
				    CurRegion->rg_LockedTo = tr;

				    /*
				     *	Apparently the width (Xe-Xs) must be
				     *	exactly the same as the listview width,
				     *	and all other parameters are ignored.
				     */

				    tr->rg_Box.bo_Xs = CurRegion->rg_Box.bo_Xs;
				    tr->rg_Box.bo_Xe = CurRegion->rg_Box.bo_Xe;
				    tr->rg_Box.bo_Ys = CurRegion->rg_Box.bo_Ye;
				    tr->rg_Box.bo_Ye = tr->rg_Box.bo_Ys + 16;
				    ReMakeEverything();
				    Title("Link Successful");
				}
			    }
			    CurState = STATE_WANDER;
			    EnableGadgets();
			    break;
			case STATE_WANDER:
			    if (SetCurRegion(FindRegion(saveX, saveY))) {
				UpdateEWinInfo(CurRegion);
				TitleState();
			    }
			    break;
			}
			ButState |= 1;
			break;
		    case SELECTUP:
			if (ButState & 4) {
			    DrawBox(&TBox);
			    TitleState();

			    switch(CurState) {
			    case STATE_NEWREGION:
				TBox.bo_Xe = im->MouseX;
				TBox.bo_Ye = im->MouseY;
				break;
			    case STATE_MOVEREGION:
				TBox.bo_Xs += im->MouseX - TX;
				TBox.bo_Xe += im->MouseX - TX;
				TBox.bo_Ys += im->MouseY - TY;
				TBox.bo_Ye += im->MouseY - TY;
				break;
			    case STATE_SIZEREGION:
				TBox.bo_Xe += im->MouseX - TX;
				TBox.bo_Ye += im->MouseY - TY;
				break;
			    }
			    FixBounds(&TBox);
			    BoxComplete();
			}
			ButState &= ~(1|4);
			break;
		    case MENUDOWN:
			ButState |= 2;
			break;
		    case MENUUP:
			ButState &= ~2;
			break;
		    default:
			break;
		    }
		    break;
		case IDCMP_MOUSEMOVE:
		    if (ButState & 4) {
			DrawBox(&TBox);

			switch(CurState) {
			case STATE_NEWREGION:
			    TBox.bo_Xe = im->MouseX;
			    TBox.bo_Ye = im->MouseY;
			    break;
			case STATE_MOVEREGION:
			    TBox.bo_Xs += im->MouseX - TX;
			    TBox.bo_Xe += im->MouseX - TX;
			    TBox.bo_Ys += im->MouseY - TY;
			    TBox.bo_Ye += im->MouseY - TY;
			    break;
			case STATE_SIZEREGION:
			    TBox.bo_Xe += im->MouseX - TX;
			    TBox.bo_Ye += im->MouseY - TY;
			    break;
			}
			TX = im->MouseX;
			TY = im->MouseY;
			DrawBox(&TBox);
			TitleState();
		    }
		    break;
		default:
		    break;
		}
		im->MouseX = saveX;
		im->MouseY = saveY;
		GT_ReplyIMsg(im);
	    }
	}
	if (EWin) {
	    while (im = GT_GetIMsg(EWin->UserPort)) {
		if (DDebug && im->Class != IDCMP_MOUSEMOVE)
		    printf("CLASS %08lx CODE %d IA=%08lx\n", im->Class, im->Code, im->IAddress);

		switch(im->Class) {
		case IDCMP_ACTIVEWINDOW:
		    ClearMenuStrip(Win);
		    SetMenuStrip(EWin, GMenu);
		    break;
		case IDCMP_CHANGEWINDOW:
		    break;
		case IDCMP_CLOSEWINDOW:
		    NotDone = 0;
		    break;
		case IDCMP_REFRESHWINDOW:
		    GT_BeginRefresh(EWin);
		    GT_EndRefresh(EWin, TRUE);
		    break;
		case IDCMP_GADGETUP:
		    HandleEditGadget(im);
		    break;
		case IDCMP_RAWKEY:	/*  HELP KEY		*/
		    break;
		case IDCMP_MENUPICK:
		    HandleMenu(im);
		    break;
		case IDCMP_MOUSEBUTTONS:
		    switch(im->Code) {
		    case SELECTDOWN:
			break;
		    case SELECTUP:
			break;
		    case MENUDOWN:
			break;
		    case MENUUP:
			break;
		    default:
			break;
		    }
		    break;
		case IDCMP_MOUSEMOVE:
		    break;
		default:
		    break;
		}
		GT_ReplyIMsg(im);
	    }
	}
    }
    return(0);
}

void
myexit(void)
{
    if (Win) {
	ClearMenuStrip(Win);
	CloseWindow(Win);
    }
    CloseEditWindow();
    if (GList)
	FreeGadgets(GList);
    if (GMenu)
	FreeMenus(GMenu);
    if (Ng.ng_VisualInfo)
	FreeVisualInfo(Ng.ng_VisualInfo);
    if (Scr)
	UnlockPubScreen(NULL, Scr);
}

void
BoxComplete()
{
    switch(CurState) {
    case STATE_WANDER:
	break;
    case STATE_NEWREGION:
	{
	    short dx = TBox.bo_Xe - TBox.bo_Xs;
	    short dy = TBox.bo_Ye - TBox.bo_Ys;

	    if ((dx < 5 && dy < 5) || dx < 3 || dy < 3)
		return;
	}
	if (RegName[0] == 0) {
	    puts("no region name");
	    return;
	}
	DrawBox(&TBox);
	{
	    TplRegion *rg = AllocTplRegion();

	    UpdateTplRegion(rg);

	    rg->rg_Box = TBox;
	    rg->rg_MinMax.bo_Xs = rg->rg_MinMax.bo_Xe = TBox.bo_Xe - TBox.bo_Xs;
	    rg->rg_MinMax.bo_Ys = rg->rg_MinMax.bo_Ye = TBox.bo_Ye - TBox.bo_Ys;

	    SetCurRegion(rg);
	    UpdateEWinInfo(CurRegion);
	    ReMakeEverything();
	}
	break;
    case STATE_MOVEREGION:
	if (CurRegion) {
	    CurRegion->rg_Box = TBox;
	    ReMakeEverything();
	}
	break;
    case STATE_SIZEREGION:
	if (CurRegion) {
	    CurRegion->rg_Box = TBox;
	    ReMakeEverything();
	}
	break;
    }
}

void
HandleMenu(im)
IMsg *im;
{
    MenuItem *mi;

    if (mi = ItemAddress(GMenu, im->Code)) {
	switch(GTMENUITEM_USERDATA(mi)) {
	case MENU_PROJ_SAVEAS:
	    strcpy(ProjSrcName, ProjName);
	    if (GetSaveFile(ProjSrcName) >= 0)
		SaveProject(ProjSrcName);
	    break;
	case MENU_PROJ_SAVE:
	    SaveProject(ProjName);
	    break;
	case MENU_PROJ_SAVESRC:     /*	ProjName.c  */
	    sprintf(ProjSrcName, "%s.c", ProjName);
	    SaveProjectAsSrc(ProjSrcName);
	    break;
	case MENU_PROJ_SAVEASSRC:
	    sprintf(ProjSrcName, "%s.c", ProjName);
	    if (GetSaveFile(ProjSrcName)) {
		SaveProjectAsSrc(ProjSrcName);
	    }
	    break;
	case MENU_LINK_LOCK:
	    if (CurRegion) {
		Title("Choose Link Destination");
		CurState = STATE_LINKREGION;
		DisableGadgets();
	    }
	    break;
	case MENU_PROJ_LOAD:
	    if (GetSaveFile(ProjName) >= 0) {
		TplRegion *rg;
		while (rg = GetHead(&RegList))
		    DeleteTplRegion(rg);
		LoadProject(ProjName);
		ReMakeEverything();
	    }
	    break;
	case MENU_PROJ_MERGE:
	    if (GetSaveFile(ProjSrcName) >= 0) {
		TplRegion *rg;
		LoadProject(ProjSrcName);
		ReMakeEverything();
	    }
	    break;
	case MENU_PROJ_QUIT:
	    NotDone = 0;
	    break;
	case MENU_SNAP + 1:
	case MENU_SNAP + 2:
	case MENU_SNAP + 4:
	case MENU_SNAP + 6:
	case MENU_SNAP + 8:
	case MENU_SNAP + 10:
	case MENU_SNAP + 12:
	case MENU_SNAP + 14:
	case MENU_SNAP + 16:
	case MENU_SNAP + 18:
	case MENU_SNAP + 20:
	    CoorSnap = (short)GTMENUITEM_USERDATA(mi) - MENU_SNAP;
	    break;
	default:
	    break;;
	}
    }
}

void
Title(tit)
char *tit;
{
    if (Win) {
	SetWindowTitles(Win, NULL, NULL);
	sprintf(TitleBuf, "%s  %s  %s",
	    ProjName,
	    (CurRegion) ? CurRegion->rg_Node.ln_Name : "<none>",
	    tit
	);
	SetWindowTitles(Win, TitleBuf, NULL);
    }
}

void
TitleState()
{
    switch(CurState) {
    case STATE_NEWREGION:
    case STATE_SIZEREGION:
	TitleXY(TBox.bo_Xe - TBox.bo_Xs, TBox.bo_Ye - TBox.bo_Ys);
	break;
    case STATE_MOVEREGION:
	TitleXY(TBox.bo_Xs, TBox.bo_Ys);
	break;
    }
}

void
TitleXY(x, y)
short x, y;
{
    if (x < 0)
	x = -x;
    if (y < 0)
	y = -y;
    sprintf(TmpBuf, "%dx%d", x, y);
    Title(TmpBuf);
}

TplRegion *
SetCurRegion(rg)
TplRegion *rg;
{
    CurRegion = rg;
    Title("");
    return(rg);
}

