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

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

Prototype   STRPTR  docmdline	    (STRPTR);
Prototype   VOID    killprompthist  (VOID);
Prototype   VALUE * cmd_cli	    (LONG, VALUE *);
Prototype   VALUE * cmd_getstr	    (LONG, VALUE *);
Prototype   VALUE * cmd_getnum	    (LONG, VALUE *);

Local	    STRPTR  LastPrompted;   /* one line history */

/*
 * returns a string got from the command line
 * it (the string) must be freestring()'ed after use.
 * cursor should be off.
 */
STRPTR
docmdline(STRPTR prompt)
{
    STRPTR cmdline;
    LONG cmdlen = 1;
    WORD promptlen = strlen(prompt);

    if(!unsleep())
	return(FALSE);
    if(cmdline = savestring(""))
    {
	VW *vw = CurrVW;
	TX *tx = vw->vw_Tx;
	POS oldcursor = vw->vw_CursorPos;
	WORD oldstartcol = vw->vw_StartCol;
	WORD prevx = 0;
	WORD keepgoing = 0;

	vw->vw_CursorPos.pos_Col = promptlen;
	vw->vw_CursorPos.pos_Line = vw->vw_StartCol + vw->vw_MaxY - 1;
	vw->vw_StartCol = 0;

	redrawcmdline(prompt, cmdline, promptlen, 0);
	cmdlncursor(ON);

	while(!keepgoing)
	{
	    struct IntuiMessage *imsg;

	    Wait(1 << vw->vw_Window->UserPort->mp_SigBit);
	    while((!keepgoing) && (imsg = GetWinIMsg(vw->vw_Window)))
	    {
		struct IntuiMessage imsgcopy = *imsg;
		ReplyMsg((struct Message *)imsg);
		if(imsgcopy.Class == IDCMP_RAWKEY)
		{
		    cmdlncursor(OFF);
		    switch(imsgcopy.Code)
		    {
			case 0x41:  /* delete */
			    if(cmdlen > 1)
			    {
				STRPTR newline;
				vw->vw_CursorPos.pos_Col--;
				cmdlen--;
				if(newline = savestringn(cmdline, cmdlen - 1))
				{
				    freestring(cmdline);
				    cmdline = newline;
				}
			    }
			    break;
			case 0x44:  /* return */
			    keepgoing = 1;
			    break;
			case 0x45:  /* escape */
			    keepgoing = -1;
			    break;
			case 0x4c:  /* up */
			case 0x4d:  /* down */
			    if(LastPrompted)
			    {
				STRPTR temp = cmdline;
				cmdline = LastPrompted;
				LastPrompted = temp;
				cmdlen = strlen(cmdline) + 1;
				vw->vw_CursorPos.pos_Col = cmdlen + promptlen - 1;
				prevx = 20000;
			    }
			    break;
			default:
			    if(!(imsgcopy.Code & IECODE_UP_PREFIX))
			    {
				struct InputEvent ie;
				UBYTE buff[256];
				LONG len;

				ie.ie_Class = IECLASS_RAWKEY;
				ie.ie_SubClass = 0;
				ie.ie_Code = imsgcopy.Code;
				ie.ie_Qualifier = imsgcopy.Qualifier;
				ie.ie_EventAddress = *((APTR *)imsgcopy.IAddress);
				if((len = MapRawKey(&ie, buff, 255, NULL)) != -1)
				{
				    STRPTR newline;
				    buff[len] = 0;
				    if(newline = savestringn(cmdline, cmdlen + len))
				    {
					strcat(newline, buff);
					freestring(cmdline);
					cmdline = newline;
					cmdlen += len;
					vw->vw_CursorPos.pos_Col += len;
				    }
				}
			    }
			    break;
		    }
		}
		else if(imsgcopy.Class == IDCMP_NEWSIZE)
		{
		    cmdlncursor(OFF);
		    vw->vw_StartCol = oldstartcol;
		    updatedimensions(CurrVW);
		    redrawall();
		    prevx = 20000;
/*		    redrawcmdline(prompt, cmdline, promptlen, cmdlen - 1); */
		}
		else
		    continue;

		if(vw->vw_CursorPos.pos_Col >= vw->vw_MaxX)
		{
		    vw->vw_StartCol = vw->vw_CursorPos.pos_Col - vw->vw_MaxX + 1;
		    redrawcmdline(prompt, cmdline, promptlen, cmdlen - 1);
		}
		else
		{
		    vw->vw_StartCol = 0;
		    if(prevx >= vw->vw_MaxX)
			redrawcmdline(prompt, cmdline, promptlen, cmdlen - 1);
		    else if(prevx < vw->vw_CursorPos.pos_Col)
			redrawcmdlinefrom(prompt, cmdline, promptlen, cmdlen - 1, prevx);
		    else
			redrawcmdlinefrom(prompt, cmdline, promptlen, cmdlen - 1, vw->vw_CursorPos.pos_Col);
		}
		prevx = vw->vw_CursorPos.pos_Col;
		cmdlncursor(ON);
	    }
	}
	if(keepgoing < 0)
	{
	    freestring(cmdline);
	    cmdline = NULL;
	}
	else
	{
	    freestring(LastPrompted);
	    LastPrompted = savestring(cmdline);
	}
	cmdlncursor(OFF);
	vw->vw_CursorPos = oldcursor;
	vw->vw_StartCol = oldstartcol;
	restorecmdline();
	return(cmdline);
    }
    return(FALSE);
}

VOID
killprompthist(VOID)
{
    freestring(LastPrompted);
    LastPrompted = NULL;
}

/*
 * cli type command
 * (cli)
 */
VALUE *
cmd_cli(LONG argc, VALUE *argv)
{
    if(!CurrVW->vw_Sleeping || unsleep())
    {
	STRPTR cmd;
	VALUE result;

	if(cmd = docmdline("cmd> "))
	{
	    execstr(cmd, &RES, FALSE, 0, NULL);
	    freestring(cmd);
	}
    }
    return(&RES);
}

/*
 * command to get a string from a prompt at the bottom of the window
 * (getstr `prompt')
 */
VALUE *
cmd_getstr(LONG argc, VALUE *argv)
{
    if((TPLATE1(VTF_STRING)) && (!CurrVW->vw_Sleeping || unsleep()))
    {
	STRPTR str;
	if(str = docmdline(ARG1.val_Value.String))
	{
	    setstrres(str);
	}
    }
    return(&RES);
}

/*
 * command to get a number from the prompt
 * (getnum `prompt')
 */
VALUE *
cmd_getnum(LONG argc, VALUE *argv)
{
    if((TPLATE1(VTF_STRING)) && (!CurrVW->vw_Sleeping || unsleep()))
    {
	STRPTR string;
	LONG number;
	STRPTR dummy;
	if(string = docmdline(ARG1.val_Value.String))
	{
	    number = strtol(string, &dummy, 0);
	    freestring(string);
	    setnumres(number);
	}
    }
    return(&RES);
}

