
/*
 * MAIN.C
 *
 *	(C)Copyright 1987 by Matthew Dillon, All Rights Reserved.
 *
 */

#include "defs.h"

#define IDCMPFLAGS   CLOSEWINDOW|NEWSIZE|RAWKEY|MOUSEBUTTONS|ACTIVEWINDOW|MOUSEMOVE

extern WIN *OpenWindow();

NW Nw = {
   0, 1, 640, 199, -1, -1,
   IDCMPFLAGS,
   ACTIVATE|WINDOWSIZING|WINDOWDRAG|WINDOWDEPTH|WINDOWCLOSE|NOCAREREFRESH|RMBTRAP,
   NULL, NULL, (ubyte *)"   WAIT   ",
   NULL, NULL,
   32, 32, -1, -1,
   WBENCHSCREEN
};

short Sharedrefs;
short Oldtlen = 999;	  /*  Old Title Length	  */
struct MsgPort *Sharedport;
DISKOBJ *Do;
WBS	*Wbs;

WIN *Win;
RP  *Rp;

short Xsize,  Ysize;		/* font character sizes        */
short Rows,  Columns;		/* character rows/cols available       */
short Xbase,  Ybase;		/* offset pixel base for display       */
short XTbase,YTbase;		/* used for text display	       */
short Xpixs,  Ypixs;		/* actual # X/Y pixels available       */
short Mx, My;

ubyte *av[8];
char Quitflag;
char Overide;
char SizeOveride;
char Wdisable = 1;		/* Disable icon save		       */
char MShowTitle, MForceTitle;
short Nwwidth, Nwheight, Nwtopedge, Nwleftedge, Nwtmpwidth, Nwtmpheight;

int Enable_Abort;

extern ED E, *Ep, *Base;
extern char memoryfail;
extern WIN *opensharedwindow();
extern IMESS *GetMsg();

static char *Ffile;

main(mac, mav)
char *mav[];
{
    register IMESS *im;
    register WIN *win;
    char nf, ni;	    /* # files on command line	*/
    char notdone;
    char iawm = 0;
    char dontwait = 0;
    short i;
    short Code;

    init_command();

    Nwwidth	= Nw.Width;
    Nwheight	= Nw.Height;
    Nwtopedge	= Nw.TopEdge;
    Nwleftedge	= Nw.LeftEdge;

    Enable_Abort= 0;

    String  = (char *)malloc(1);
    *String = 0;

    if (!openlibs(INTUITION_LIB|GRAPHICS_LIB))
	exiterr("cannot open intuition or graphics library");

    if (mac == 0) {
	long oldlock;

	Wdisable = 0;
	Wbs = (WBS *)mav;
	if (!openlibs(ICON_LIB))
	    exiterr("unable to open icon library");
	oldlock = CurrentDir(Wbs->sm_ArgList[0].wa_Lock);   /* tool */
	Do = GetDiskObject(Wbs->sm_ArgList[0].wa_Name);
	CurrentDir(oldlock);
	if (Do == NULL)
	    exiterr("unable to get disk object");
	mac = 99;
    }

    resethash();

    if (Do) {
	ops(Do->do_ToolTypes, 1);
	nf = Wbs->sm_NumArgs - 1;
	E.dirlock = Wbs->sm_ArgList[0].wa_Lock;
    } else {
	nf = ops(mav+1, 0);
    }

    for (ni = 0, i = 1; i < mac; ++i) {
	register char *str;
	register DISKOBJ *dso;
	long oldlock;
	if (Wbs) {
	    if (i > nf)
		break;
	    str = Wbs->sm_ArgList[i].wa_Name;
	    oldlock = CurrentDir(Wbs->sm_ArgList[i].wa_Lock);
	    if (dso = GetDiskObject(Wbs->sm_ArgList[i].wa_Name)) {
		ops(dso->do_ToolTypes, 1);
		FreeDiskObject(dso);
	    }
	    E.dirlock = CurrentDir(oldlock);
	} else {
	    str = mav[i];
	    if (*str == '-')
		continue;
	}
	do_newwindow(nf > 1, ni * 10);
	++ni;
	av[0] = (ubyte *)"newfile";
	av[1] = (ubyte *)str;
	do_edit();
	MForceTitle = 1;
	window_title();
    }
    if (nf == 0)                     /* no files to edit */
	do_newwindow(nf > 1, ni * 10);

    mountrequest(0);
    av[0] = NULL;
    av[1] = (ubyte *)"s:.edrc";
    do_source();
    av[0] = NULL;
    av[1] = (ubyte *)((Ffile) ? Ffile : ".edrc");
    do_source();
    mountrequest(1);
    title("DME V1.28f \251Copyright 1987 Matthew Dillon,  All Rights Reserved                  ");
loop:
    if (!E.iconmode)
	text_cursor(1);
    for (notdone = 1; !Quitflag && notdone;) {
	char mmove = 0;
	short mqual;

	if (!E.iconmode)
	    window_title();
	if (dontwait)
	    --dontwait;
	else
	    WaitPort(Win->UserPort);

	/*
	 *  NOTE: due to operation of breakcheck(), the userport signal
	 *  may not be set even if there are messages pending.
	 */

	while (im = (IMESS *)GetMsg(Win->UserPort)) {
	    Msgchk = 1;
	    Abortcommand = 0;
	    Code = im->Code;
	    if (im->IDCMPWindow != Win) {
		Overide = 0;
		if (Comlinemode)
		    escapecomlinemode();
		text_sync();
		MShowTitle = 0;
		if (!E.iconmode)
		    window_title();
		if (text_switch(im->IDCMPWindow) == 0) {
		    ReplyMsg(im);
		    continue;
		}
		if (!E.iconmode) {
		    set_window_params();
		    window_title();
		}
	    }
	    Mx = im->MouseX;
	    My = im->MouseY;
	    switch(im->Class) {
	    case NEWSIZE:
		if (!E.iconmode) {
		    if (Comlinemode)
			escapecomlinemode();
		    set_window_params();
		    if (!text_sync())
		       text_redisplay();
		    text_cursor(1);
		}
		break;
	    case MOUSEBUTTONS:
		switch(Code) {
		case SELECTDOWN:
		case MENUDOWN:
		    if (E.iconmode || iawm) {
			uniconify();
			break;
		    }
		    ReportMouse(-1, Win);
		    uniconify();
		    text_cursor(0);
		    keyctl(NULL, im->Code|0x80, im->Qualifier);
		    text_cursor(1);
		    break;
		case SELECTUP:
		case MENUUP:
		    ReportMouse(0, Win);
		    break;
		}
		break;
	    case RAWKEY:
		if ((im->Qualifier & 0x80) == 0) {
		    if (E.iconmode) {
			uniconify();
			break;
		    }
		    text_cursor(0);
		    keyctl(im, im->Code, im->Qualifier);
		    text_cursor(1);
		}
		break;
	    case CLOSEWINDOW:
		if (Comlinemode)
		    escapecomlinemode();
		text_sync();
		notdone = 0;
		break;
	    case ACTIVEWINDOW:
		if (!E.iconmode)
		    iawm = 1;
		break;
	    case MOUSEMOVE:
		mmove = 1;
		mqual = im->Qualifier;
		break;
	    }
	    if (im)
		ReplyMsg(im);
	    if (notdone == 0 || Quitflag) {
		dontwait = 2;
		goto boom;
	    }
	}
	iawm = 0;
	if (mmove) {
	    uniconify();
	    mmove = 0;
	    text_cursor(0);
	    keyctl(NULL, QMOVE, mqual);
	    text_cursor(1);
	}
	closesharedwindow(NULL);
    }
boom:
    if (E.Modified && !Overide) {
	uniconify();
	Overide = 1;
	title("*** File has been modified ***");
	Quitflag = 0;
	goto loop;
    }
    SetWindowTitles(Win, "", -1);
    text_uninit();                      /* uninitialize text portion    */
    closesharedwindow(Win);
    if (Base) {
	Quitflag = 0;
	Win = E.Win;			/* make arbitrary other window act. */
	Rp = Win->RPort;
	if (!E.iconmode)
	    set_window_params();
	text_load();
	MShowTitle = 0;
	goto loop;
    }
    closesharedwindow(NULL);
    if (Do)
	FreeDiskObject(Do);
    closelibs(-1);
    dealloc_hash();
}

do_iconify()
{
    if (!Comlinemode)
	iconify();
}

do_tomouse()
{
    text_position((Mx-Xbase)/Xsize, (My-Ybase)/Ysize);
}

iconify()
{
    if (!E.iconmode) {
	E.Winx	    = Win->LeftEdge;
	E.Winy	    = Win->TopEdge;
	E.Winwidth  = Win->Width;
	E.Winheight = Win->Height;
	Nw.Height = 10;
	Nw.Width  = 20 + 5*8 + strlen(E.Name)*8;
	Nw.LeftEdge= E.IWinx;
	Nw.TopEdge = E.IWiny;
	if (Nw.LeftEdge + Nw.Width > Win->WScreen->Width)
	    Nw.LeftEdge = Win->WScreen->Width - Nw.Width;
	if (Nw.TopEdge + Nw.Height > Win->WScreen->Height)
	    Nw.TopEdge = Win->WScreen->Height - Nw.Height;
	Nw.Title = Ep->Wtitle;
	Nw.Flags &= ~(WINDOWSIZING|WINDOWDEPTH|ACTIVATE);
	Nw.Flags |= BORDERLESS;
	sprintf(Ep->Wtitle, "%s %s    ", E.Name, ((E.Modified) ? "(mod)":""));
	closesharedwindow(Win);
	Win = E.Win = Ep->Win = opensharedwindow(&Nw);
	Nw.Flags |= WINDOWSIZING|WINDOWDEPTH|ACTIVATE;
	Nw.Flags &= ~BORDERLESS;
	Rp = Win->RPort;
    }
    E.iconmode = 1;
}

uniconify()
{
    if (E.iconmode) {
	E.IWinx = Win->LeftEdge;
	E.IWiny = Win->TopEdge;
	closesharedwindow(Win);
	Nw.LeftEdge = E.Winx;
	Nw.TopEdge  = E.Winy;
	Nw.Width    = E.Winwidth;
	Nw.Height   = E.Winheight;
	Nw.Title = Ep->Wtitle;
	Win = E.Win = Ep->Win = opensharedwindow(&Nw);
	Rp = Win->RPort;
	set_window_params();
	if (!text_sync())
	    text_redisplay();
	text_cursor(1);
	MShowTitle = 0;
	window_title();
    }
    E.iconmode = 0;
}


do_newwindow(makesmall, deltaheight)
{
    WIN *win;
    int msadj = makesmall;

    if (SizeOveride)
	msadj = 0;
    if (Ep)
	text_sync();
    Nw.Title = (ubyte *)"    OK    ";
    Nw.Width = (Nwtmpwidth) ? Nwtmpwidth : Nwwidth;
    Nw.Height= (Nwtmpheight)? Nwtmpheight: Nwheight;
    Nwtmpwidth = Nwtmpheight = 0;
    Nw.LeftEdge = Nwleftedge;
    Nw.TopEdge	= Nwtopedge;
    if (msadj > 0) {                    /* deltaheight must be valid    */
	Nw.TopEdge = deltaheight + 16;
	Nw.LeftEdge= 10*8;
	Nw.Flags &= ~ACTIVATE;
	Nw.Width = 40*8;
	Nw.Height= 10*8;
	if (Nw.TopEdge + Nw.Height > 200)
	    Nw.TopEdge = deltaheight = 200 - Nw.Height;
    }
    win = opensharedwindow(&Nw);
    Nw.Flags |= ACTIVATE;
    if (win) {
	Win = win;			/* set new window   */
	Rp = Win->RPort;
	set_window_params();
	text_init();                    /* initialize       */
	text_load();
	if (makesmall != -1)            /* if deltaheight valid */
	    E.IWiny = deltaheight + 16;
    }
}

WIN *
TOpenWindow(nw)
NW *nw;
{
    WIN *win;

    while ((win = OpenWindow(nw)) == NULL) {
	if (nw->Width < 50 || nw->Height < 50)
	    break;
	nw->Width -= 10;
	nw->Height-= 10;
    }
    return(win);
}


WIN *
opensharedwindow(nw)
NW *nw;
{
    WIN *win;

    if (Sharedport)
	nw->IDCMPFlags = NULL;
    else
	nw->IDCMPFlags = IDCMPFLAGS;
    win = TOpenWindow(nw);
    if (win) {
	if (Sharedport) {
	    win->UserPort = Sharedport;
	    ModifyIDCMP(win, IDCMPFLAGS);
	} else {
	    Sharedport = win->UserPort;
	}
	++Sharedrefs;
    }
    return(win);
}


closesharedwindow(win)
WIN *win;
{
    static WIN *wunlink;
    register IMESS *im;
    char notoktoclosenow = 0;

    if (win) {
	SetWindowTitles(win, "", -1);
	Forbid();
	win->UserPort = NULL;
	ModifyIDCMP(win, GADGETUP);     /* NEVER occurs */

	notoktoclosenow = 1;

	Permit();
	if (notoktoclosenow) {
	    win->UserData = (char *)wunlink;
	    wunlink = win;
	} else {
	    CloseWindow(win);
	}
	--Sharedrefs;
    } else {
	if (Sharedrefs == 0 && Sharedport) {
	    DeletePort(Sharedport);
	    Sharedport = NULL;
	}
	for (win = wunlink; win; win = wunlink) {
	    wunlink = (WIN *)win->UserData;
	    CloseWindow(win);
	}
	wunlink = NULL;
    }
}


getyn(text)
char *text;
{
    int result;
    ITEXT *body, *pos, *neg;

    body = (ITEXT *)AllocMem(sizeof(ITEXT), 0);
    pos  = (ITEXT *)AllocMem(sizeof(ITEXT), 0);
    neg  = (ITEXT *)AllocMem(sizeof(ITEXT), 0);
    bzero(body, sizeof(ITEXT));
    bzero(pos , sizeof(ITEXT));
    bzero(neg , sizeof(ITEXT));
    body->BackPen = pos->BackPen = neg->BackPen = 1;
    body->DrawMode= pos->DrawMode= neg->DrawMode= AUTODRAWMODE;
    body->LeftEdge = 10;
    body->TopEdge  = 12;
    body->IText    = (ubyte *)text;
    pos->LeftEdge = AUTOLEFTEDGE;
    pos->TopEdge = AUTOTOPEDGE;
    pos->IText = (ubyte *)"OK";
    neg->LeftEdge = AUTOLEFTEDGE;
    neg->TopEdge = AUTOTOPEDGE;
    neg->IText = (ubyte *)"CANCEL";
    result = AutoRequest(Win,body,pos,neg,0,0,320,58);
    FreeMem(body, sizeof(ITEXT));
    FreeMem(pos , sizeof(ITEXT));
    FreeMem(neg , sizeof(ITEXT));
    return(result);
}


title(buf)
char *buf;
{
    SetWindowTitles(Win, buf, -1);
    Oldtlen = 999;
    MShowTitle = 3;
}

window_title()
{
    register int len, maxlen;

    if (memoryfail) {
	title(" -- NO MEMORY -- ");
	memoryfail = 0;
	text_redisplay();
    }
    if (MForceTitle) {
	MShowTitle = 0;
	MForceTitle = 0;
    }
    if (MShowTitle) {
	--MShowTitle;
	return(0);
    }
    {
	register char *mod;
	mod = (E.Modified) ? " (modified)" : "          ";
	sprintf(Ep->Wtitle, "%3ld/%-3ld %3ld %s%s  ", text_lineno(), text_lines(), text_colno()+1, text_name(), mod);
	if (!text_imode())
	    strcat(Ep->Wtitle, "Ovr ");
	len = strlen(Ep->Wtitle);
	if (len < Columns && Columns < 128) {
	    bset(Ep->Wtitle+len, Columns - len + 1, ' ');
	    Ep->Wtitle[Columns + 1] = 0;
	}

	Win->Title = Ep->Wtitle;
	SetAPen(Rp, 0);
	SetBPen(Rp, 1);
	Move(Rp, 30, Win->RPort->Font->tf_Baseline+1);
	maxlen = (Win->Width-96)/Win->RPort->Font->tf_XSize;
	if (maxlen < 0)
	    maxlen = 0;
	if (len > maxlen)
	    len = Oldtlen = maxlen;
	if (Oldtlen > maxlen)
	    Oldtlen = maxlen;
	Text(Rp, Ep->Wtitle, len);      /*  No flash                    */
	while (Oldtlen - len >= (int)sizeof(Space)) {
	    Text(Rp, Space, sizeof(Space));
	    Oldtlen -= sizeof(Space);
	}
	if (Oldtlen - len > 0)
	    Text(Rp, Space, Oldtlen - len);
	Oldtlen = len;			/*  Oldtlen might have been <	*/
	SetAPen(Rp, 1);
	SetBPen(Rp, 0);
    }
}

set_window_params()
{
    Xsize = Rp->Font->tf_XSize;
    Ysize = Rp->Font->tf_YSize;
    Xbase = Win->BorderLeft;
    Ybase = Win->BorderTop;
    Xpixs   = Win->Width - Win->BorderRight - Xbase;
    Ypixs   = Win->Height- Win->BorderBottom- Ybase;
    Columns = Xpixs / Xsize;
    Rows    = Ypixs / Ysize;
    XTbase  =  Xbase;
    YTbase  =  Ybase + Rp->Font->tf_Baseline;
}


exiterr(str)
char *str;
{
    if (Output()) {
	Write(Output(),str,strlen(str));
	Write(Output(),"\n",1);
    }
    exit(1);
}


/*
 *  Check break by scanning pending messages in the I stream for a ^C.
 *  Msgchk forces a check, else the check is only made if the signal is
 *  set in the I stream (the signal is reset).
 */

breakcheck()
{
    IMESS *im;
    register struct List *list = &Win->UserPort->mp_MsgList;

    if (Msgchk || (SetSignal(0,0) & (1<<Win->UserPort->mp_SigBit))) {
	Msgchk = 0;
	SetSignal(0,1<<Win->UserPort->mp_SigBit);

	im = (IMESS *)list->lh_Head;
	Forbid();
	for (; im != &list->lh_Tail; im = (IMESS *)im->ExecMessage.mn_Node.ln_Succ) {
	    if (im->Class == RAWKEY && (im->Qualifier & 0xFB) == 0x08 &&
		im->Code == CtlC) {

		Permit();
		SetSignal(SIGBREAKF_CTRL_C,SIGBREAKF_CTRL_C);
		return(1);
	    }
	}
	Permit();
    }
    return(0);
}

breakreset()
{
    SetSignal(0, SIGBREAKF_CTRL_C);
}

/*
 *  leftedge n
 *  topedge  n
 *  width    n
 *  height   n
 *  tmpwidth  n
 *  tmpheight n
 */

void
do_windowparm()
{
    int val = atoi(av[1]);

    if (av[0][0] == 't' && av[0][1] == 'm') {   /*  tmpwidth/tmpheight  */
	if (av[0][3] == 'w')
	    Nwtmpwidth = val;
	if (av[0][3] == 'h')
	    Nwtmpheight= val;
	return;
    }
    switch(av[0][0]) {
    case 'l':
	Nwleftedge = val;
	break;
    case 't':
	Nwtopedge = val;
	break;
    case 'w':
	Nwwidth = val;
	break;
    case 'h':
	Nwheight = val;
	break;
    }
}

/*
 *  resize cols rows
 */

do_resize()
{
    int cols = atoi(av[1]);
    int rows = atoi(av[2]);
    short width = (cols*Win->RPort->Font->tf_XSize) + Win->BorderLeft + Win->BorderRight;
    short height= (rows*Win->RPort->Font->tf_YSize) + Win->BorderTop + Win->BorderBottom;

    if (width < 16 || height < 16 ||
    width > Win->WScreen->Width - Win->LeftEdge ||
    height > Win->WScreen->Height - Win->TopEdge) {
	title ("window too big (try moving to upper left corner and retrying)");
	return(0);
    }
    SizeWindow(Win, width - Win->Width, height - Win->Height);
    Delay(50*2);    /* wait 2 seconds */
}

ops(av, iswb)
register char *av[];
{
    register short nonops;
    register short i;
    register long val;
    register char *str;

    for (i = nonops = 0; str = av[i]; ++i) {
	if (iswb) {
	    if (strncmp(str, "ARG", 3) == 0) {
		while (*str && *str != '-')
		    ++str;
	    }
	}
	if (*str == '-') {
	    val = atoi(str+2);
	    switch(str[1]) {
	    case 'f':
		Ffile = str+2;
		break;
	    case 'b':
		SizeOveride = 1;
		break;
	    case 't':
		Nwtopedge = val;
		break;
	    case 'l':
		Nwleftedge= val;
		break;
	    case 'w':
		SizeOveride = 1;
		Nwwidth   = val;
		break;
	    case 'h':
		SizeOveride = 1;
		Nwheight  = val;
		break;
	    }
	} else {
	    ++nonops;
	}
    }
    return(nonops);
}



