
/*
 * MAIN.C
 * (c) 1992 J.Harper
 */

#include "jed.h"
#include "jed_protos.h"

Local	    BOOL	parseargs   (STRPTR);
Prototype   VALUE *	cmd_ilock   (LONG, VALUE *);
Prototype   VOID	doconmsg    (STRPTR);

Prototype   const UBYTE NoMemMsg[];
	    const UBYTE NoMemMsg[]	 = "panic: no memory!";
Prototype	  UBYTE RexxName[];
		  UBYTE RexxName[]	 = "JEDX";
Local	    const UBYTE NoStartupBdy[]	 = "Can't find a startup script, this means no keybindings or menus.\nAre you sure you want to go on? (I'd read the docs if I was you)";
Local	    const UBYTE NoStartupGad[]	 = "OK|Exit";
Local	    BOOL	ILock;
extern	struct Library *DOSBase;
extern	    APTR	_WBMsg;

/*
 * This function has to be stack based since c.o doesn't like a registered
 * _main().
 */
__stkargs LONG
_main(LONG cmdLen, STRPTR cmdLine)
{
    BOOL ok;
    if(DOSBase->lib_Version < 36)
    {
	doconmsg("error: need system 2.0+\n");
	return(5);
    }

    NewMList(&TXList);
    if(_WBMsg)
	ok = newfile(NULL);
    else
	ok = parseargs(cmdLine);
    if(ok)
    {
	initpath();
	if(initcommands())
	{
	    LONG rexxsig;
	    WORD i;
	    Forbid();
	    for(i = 0; i < 10; i++)
	    {
		sprintf(RexxName, "JED%lc", i ? i + '1' : 0);
		if(!FindPort(RexxName))
		{
		    rexxsig = upRexxPort(RexxName, "jed");
		    break;
		}
	    }
	    if(i == 10)
		RexxName[0] = 0;
	    Permit();
	    if(scriptfile("jed-startup") || scriptfile("s:jed/jed-startup") || scriptfile("s:jed-startup") || ezreq(NoStartupBdy, NoStartupGad, NULL))
	    {
		while(CurrVW)
		{
		    ULONG signals;
		    struct IntuiMessage *imsg;

		    stdtitle();
		    if(ILock && rexxsig)
			signals = Wait(rexxsig);
		    else
			signals = Wait((1 << CurrVW->vw_Window->UserPort->mp_SigBit) | rexxsig);
		    if(rexxsig && (signals & rexxsig))
			dispRexxPort();
		    while(CurrVW && (imsg = GetMsg(CurrVW->vw_Window->UserPort)))
		    {
			struct IntuiMessage imsgcopy = *imsg;
			ReplyMsg((struct Message *)imsg);

			CurrVW = (VW *)imsgcopy.IDCMPWindow->UserData;
			if(((imsgcopy.Class != IDCMP_RAWKEY) || (!(imsgcopy.Code & IECODE_UP_PREFIX))) && ((imsgcopy.Class != IDCMP_MENUPICK) || (imsgcopy.Code != MENUNULL)))
			{
			    switch(imsgcopy.Class)
			    {
				case IDCMP_NEWSIZE:
				    updatedimensions(CurrVW);
				    resyncxy();
				    CurrVW->vw_RefreshType |= RFF_ALL;
				    refresh();
				    cursor(ON);
				    break;
				case IDCMP_MOUSEBUTTONS:
				    if(imsgcopy.Code == IECODE_LBUTTON)
				    {
					resettitle();
					cursor(OFF);
					positioncursorfine(imsgcopy.MouseX, imsgcopy.MouseY);
					resyncxy();
					refresh();
					cursor(ON);
					CurrVW->vw_ClickSecs = imsgcopy.Seconds;
					CurrVW->vw_ClickMics = imsgcopy.Micros;
				    }
				    else if(imsgcopy.Code == IECODE_RBUTTON)
				    {
					if(CurrVW->vw_Sleeping)
					{
					    unsleep();
					    refresh();
					    cursor(ON);
					}
				    }
				    break;
				case IDCMP_MOUSEMOVE:
				    if(imsgcopy.Qualifier & IEQUALIFIER_LEFTBUTTON)
				    {
					resettitle();
					cursor(OFF);
					positioncursorfine(imsgcopy.MouseX, imsgcopy.MouseY);
					resyncxy();
					refresh();
					cursor(ON);
				    }
				    break;
				case IDCMP_MENUPICK:
				    resettitle();
				    evalmenu(imsgcopy.Code, imsgcopy.Qualifier);
				    break;
				case IDCMP_CLOSEWINDOW:
				    TX *tx = CurrVW->vw_Tx;
				    if((numviews(tx) > 1) || (!tx->tx_Changes) || (ezreq("OK to lose %ld changes\nto file %s", "Yeah|Cancel", tx->tx_Changes, tx->tx_TitleName)))
				    {
					cursor(OFF);
					killwindow();
					if(CurrVW)
					{
					    refresh();
					    cursor(ON);
					}
				    }
				    break;
				case IDCMP_RAWKEY:
				    usekey(&imsgcopy);
				    break;
				case IDCMP_ACTIVEWINDOW:
				    updatedimensions(CurrVW);
				    cursor(OFF);
				    resyncxy();
				    if(CurrVW->vw_LastRefresh != CurrVW->vw_Tx->tx_Changes)
					CurrVW->vw_RefreshType |= RFF_ALL;
				    refresh();
				    cursor(ON);
				    break;
			    }
			}
		    }
		    if(CurrVW)
			stdtitle();
		}
		killclipstuff();
		killfilereq();
		killprompthist();
		killmenu();
		killbindings();
	    }
	    else
		killwindow();
	    dnRexxPort();
	    killsymbols();
	}
	else
	{
	    killwindow();
	    doconmsg("error: no memory to initialize symbol table\n");
	}
	killpath();
    }
    else
	doconmsg("error: can't open window\n");
    return(0);
}

/*
 * CLI only.
 */
BOOL
parseargs(STRPTR args)
{
    BOOL inquote = FALSE;
    BOOL infile = FALSE;
    STRPTR laststart = args;
    UBYTE c;

    while(c = *args++)
    {
	if(c == '"')
	{
	    if(inquote)
	    {
		args[-1] = 0;
		if(!newfile(laststart))
		    Printf("can't open file %s\n", (LONG)laststart);
		else
		{
		    refresh();
		    cursor(ON);
		}
		inquote = FALSE;
	    }
	    else
	    {
		inquote = TRUE;
		laststart = args;
	    }
	}
	else if(isspace(c))
	{
	    if(infile)
	    {
		args[-1] = 0;
		if(!newfile(laststart))
		    Printf("can't open file %s\n", (LONG)laststart);
		else
		{
		    refresh();
		    cursor(ON);
		}
		infile = FALSE;
	    }
	}
	else
	{
	    if(!infile && !inquote)
	    {
		infile = TRUE;
		laststart = args - 1;
	    }
	}
    }
    if(IsMListEmpty(&TXList))
    {
	BOOL res = newfile(NULL);
	if(res)
	{
	    refresh();
	    cursor(ON);
	}
	return(res);
    }
    return(TRUE);
}

/*
 * Input lock, when this is on only ARexx messages can get through.
 */
VALUE *
cmd_ilock(LONG argc, VALUE *argv)
{
    if(TPLATE1(VTF_NUMBER))
    {
	setnumres(ILock);
	ILock = ARG1.val_Value.Number;
    }
    return(&RES);
}

/*
 * CLI/WB & 1.3/2.0 compatible
 */
VOID
doconmsg(STRPTR msg)
{
    if(_WBMsg)
    {
	BPTR fh = Open("CON:///80/JEd output/WAIT/CLOSE", MODE_NEWFILE);
	if(fh)
	    Write(fh, msg, strlen(msg));
	Close(fh);
    }
    else
	Write(Output(), msg, strlen(msg));
}

/*
 * reference to pull in WB startup
 */
VOID _waitwbmsg(VOID);
Local VOID
dummy(VOID)
{
    _waitwbmsg();
}

