/*
 * User status and command window.
 *
 * Robert W. Baldwin, December 1984.
 *
 * Bob Baldwin 10/86.
 *  Formatting changes.
 *  Change usrdown to fix screen fall off bug.
 *  Change usrfirst to fix cursor pos so jumpcmd() works.
 */


#include	<stdio.h>
#include	"window.h"
#include	"terminal.h"
#include	"layout.h"
#include	"specs.h"
#include	"parser.h"


#define	DONEMSG	 "Command completed."
#define	USRHLP	1		/* Offset for help line. */
#define	USRSTAT	2		/* Offset for status line. */
#define	USRCMD	3		/* Offset for command line. */


/* Global space to build status messages. */
char	statmsg[MAXWIDTH+1];


extern	int	usrfirst();	/* Defined below. */
extern	int	usrdokey();	/* Defined below. */
extern	int	usrdraw();	/* Defined below. */
extern	int	usrup();	/* Defined below. */
extern	int	usrdown();	/* Defined below. */


/* Command table. */
#define USRHTEXT \
"bigram, knit, prop, load, save, lookup, clear, equiv, auto-tri, pword"

cmdent	usrcmdtab[] = {
		{"quit-program permanently", quitcmd},
{"auto-trigram max_dev: % min_total_chars: % min_wire_chars: %", atrguess},
		{"knitting using blocks from: % to: %  Min show count: %", kntguess},
		{"lookup-pattern: % in dictionary", webmatch},
		{"equivalence-class guess, use accept level: % (try 2.0)", ecbguess},
		{"pwords-from file: %  Max dev: % (try 1.0)", pwdguess},
		{"load-permutations", permload},
		{"save-permutations", permsave},
		{"clear-zee permutation", clearzee},
		{"propagate-info from: % to: % using Zee", pgate},
		{"bigram-guess level: % (2.0), min_prob: % (0.15)", lpbguess},
		{0, NULL},
		};


/* Keystroke table for the user area. */
extern	usrdocmd();

/* Keystroke table for the whole user window.
 * The editing on the command line is handled by a sub-window.
 */
keyer	usrktab[] = {
		{CGO_UP, usrup},	/* Keep off help and status lines. */
		{CGO_DOWN, usrdown},	/* Normal behavior ok. */
		{CEXECUTE, usrdocmd},	/* Interprete a command. */
		{0, NULL},		/* Handle other chars elsewhere. */
		};

/* Keystroke table for the command line sub-window.
 */
keyer	cmdktab[] = {
                {CNEXTARG, wl_nxtarg},
		{CGO_LEFT, wl_dlleft},	/* Stay withing variable area. */
		{CGO_RIGHT, wl_dlright},/* Stay withing variable area. */
		{CDELF, wl_dlfdel},	/* Delete forward within var area. */
		{CDELB, wl_dlbdel},	/* Delete backward within var area. */
		{CCLRLINE, wl_dlclr},	/* Clear variable area. */
		{CINSERT, wl_dlinsert},	/* All other chars self-insert. */
		};


/* Window for the user commands and program status. */

displine usraline[USRHEIGHT];		/* Display lines for the user. */
displine *usrlines[USRHEIGHT+1];	/* Pointers to them plus NULL. */

twindow	user = {
		USRROW,1,		/* Origin. */
		USRHEIGHT, USRWIDTH,	/* Height and width. */
		USRCMD+1, USRSCOL,	/* Initial (relative) cursor pos. */
		NULL,			/* No private data. */
		usrfirst,		/* Firstime = restore cursor pos. */
		wl_noop,		/* Lasttime = do nothing. */
		usrdraw,		/* Default draw routine. */
		usrdokey,		/* Custom keystroke handler. */
		usrktab,		/* Keystroke table. */
		usrlines,
};



/* Display a string in the status area.
 * If the string is empty, this will clear the status area.
 * Put the cursor back where it was.
 *
 * The empty string is special case.  If the status line is
 * empty, then wcur_col = 1.  A second request to clear
 * the line is ignored.
 * If the line is not empty, wcur_col = dl_min_col.
 */
usrstatus(w, str)
twindow	*w;
char	*str;
{
	displine *line;
	int	 row, col;
	
	row = rowcursor();
	col = colcursor();

	line = w->dlines[USRSTAT];
	if (*str == 0  &&  line->wcur_col == 1)
	  	return;

	dlsetvar(line, str);
	(*(line->wredraw))(line);
	setcursor(row, col);

	line->wcur_col = (*str == 0) ? 1 : 2;
}



/* Display a string in the help area.
 * If the string is empty, this will clear the help area.
 * Put the cursor back where it was.
 */
usrhelp(w, str)
twindow	*w;
char	*str;
{
	displine *line;
	int	 row, col;
	
	row = rowcursor();
	col = colcursor();

	line = w->dlines[USRHLP];
	dlsetvar(line, str);
	(*(line->wredraw))(line);

	setcursor(row, col);
}



/* Draw the user area.
 * Leaves the cursor on the command line.
 */
usrdraw(w)
twindow	*w;
{
	wl_twdraw(w);
}



/* Make a window with a title and partial outline.
 */
gwindow *(iuser())
{
	int	 i;
	displine *line, *lines;
	twindow	 *w;

	w = &user;
	lines = usraline;
	for (i = 0 ; i < w->wheight ; i++)  {
		line = &lines[i];
		line->worg_row = w->worg_row + i;
		line->worg_col = w->worg_col;
		line->wheight = 1;
/* Fix bug on terminals that autowrap. */
		line->wwidth = (i == USRCMD) ? w->wwidth - 1 : w->wwidth;
		line->wcur_row = 1;
		line->wcur_col = USRSCOL;
		line->wfirst = wl_rcursor;
		line->wlast = wl_noop;
		line->wredraw = wl_dldraw;
		line->wkey = dokey;
		line->wkeyprocs = arwktab;
		line->dl_min_col = USRSCOL;
		line->dl_max_col = line->wwidth;
		clrdline(line);
		w->dlines[i] = line;
		}
	w->dlines[i] = NULL;

	line = &lines[USRHLP];
	setadline(line, "Help   : This feature not implemented");
	line = &lines[USRSTAT];
	setadline(line, "Status : ");
	dlsetvar(line, "Just barely working");
	line = &lines[USRCMD];
	setadline(line, "Command: ");
	line->wkeyprocs = cmdktab;

	return((gwindow *) w);
}


/* Behavior of the up arrow key.
 * Move up to the window above us staying in the same column.
 */
usrup(w, k)
twindow	*w;		/* The user window. */
key	k;
{
	wl_setcur(w, 1, w->dlines[USRCMD]->wcur_col);
	jogup(w, k);
}


/* Behavior of the down arrow key.
 * Move to command line.
 */
usrdown(w, k)
twindow	*w;		/* The user window. */
key	k;
{
	wl_setcur(w, USRHEIGHT, w->dlines[USRCMD]->wcur_col);
}


/* Behavior when cursor first enters the user window.
 * Move to the command line.
 */
usrfirst(w, row, col)
twindow	*w;
int	row, col;	/* Place in window when cursor currently is. */
{
	displine *cmdline;

	wl_setcur(w, USRHEIGHT, w->dlines[USRCMD]->wcur_col);
	usrhelp(w, USRHTEXT);
	cmdline = w->dlines[USRCMD];
	(*(cmdline->wfirst))(cmdline, 1, col);
}


/* Keystroke handler for user window.
 * If it is not an up-arrow or down-arrow, pass it to the command line.
 */
usrdokey(w, k)
twindow	*w;		/* The user window. */
key	k;
{
	char	 *expanded;	/* Expanded command line. */
	char	 cmdbuf[MAXWIDTH+1];
	displine *cmdline;

	cmdline = w->dlines[USRCMD];
	usrstatus(&user, "");
	if (ddokey(w, k, w->wkeyprocs))  {  /* If handled by top window. */
		return;			    /* Includes doit key. */
	}

	if (k == ((CINSERT << CMDSHIFT) | SPACE))  {
		dlgetvar(cmdline, cmdbuf);
		expanded = cmdcomplete(usrcmdtab, cmdbuf);
		if (expanded != NULL)  {
			dlsetvar(cmdline, expanded);
			wl_dldraw(cmdline);
			return;
			}
		}
	(*(cmdline->wkey))(cmdline, k);	/* Else pass to sub-window. */
}


/* Interprete a command.
 */
usrdocmd(usr)
twindow	*usr;
{
	char	 cmdbuf[MAXWIDTH+1];
	char	 *errmsg;
	displine *cmdline;

	cmdline = usr->dlines[USRCMD];
	wl_setcur(usr, usr->wcur_row, cmdline->wcur_col);
	dlgetvar(cmdline, cmdbuf);
	if ((errmsg = cmddo(usrcmdtab, cmdbuf)) == NULL)
		errmsg = DONEMSG;
	usrstatus(&user, errmsg);
}
