/* display.c - functions for display management
 */

#include <stdio.h>
#include <string.h>
#include "mstring.h"
#include "terminal.h"
#include "editor.h"

long ed__topline;			 /* line number at top of display */
long ed__leftchar;			 /* char at left of display */
int ed__showhelp;			 /* 1 if currently showing help */
int ed__start_line = 0;			 /* start screen line of editor body */


/* Terminate the line "buf", trimming it if it's too long.
 *
 * NB "buf" must have about 16 bytes more than the string length allocated.
 */
void ed_redraw__terminate(char *buf)
{
	if (mstrlen(buf) >= t_cols) {
		buf[mstrindex(buf, t_cols - 1)] = 0;
		strcat(buf, "\035R>\035r");
	}
	strcat(buf, "\035a\035CA\035Ca");
}


/* Display the editor title "title".
 */
void ed_redraw__title(char *title)
{
	char buf[1024];
	int c;

	if (!title)
		title = "";

	buf[0] = 0;

	c = (t_cols - mstrlen(title)) / 2;
	while ((c > 0) && (strlen(buf) < (sizeof(buf) - 16))) {
		strcat(buf, " ");
		c--;
	}

	strncat(buf, title, sizeof(buf) - 16 - strlen(buf));

	ed_redraw__terminate(buf);

	t_goto(0, 0);
	t_lineout(buf, 0);		    /* title line */

	strcpy(buf, "\035CB");
	for (c = 0; (c < t_cols) && (c < (sizeof(buf) - 16)); c++)
		buf[c + 3] = '~';
	buf[c + 3] = 0;
	strcat(buf, "\035CA");
	t_lineout(buf, 0);		    /* row of ~~~~ under title */
}


/* Display the editor header "header", plus the editor top bar.
 */
void ed_redraw__header(char *header)
{
	char buf[1024];
	char *a;
	int i, l;

	if (!header)
		header = "";

	t_goto(0, 2);

	ed__start_line = 3;

	for (i = 0; i < 3; i++) {
		a = strchr(header, '\n');
		if (!a)
			continue;
		l = a - header;
		if (l > (sizeof(buf) - 16))
			l = sizeof(buf) - 16;
		strncpy(buf, header, l);
		buf[l] = 0;
		ed_redraw__terminate(buf);
		t_lineout(buf, 0);
		ed__start_line++;
		header = a;
		header++;
	}

	strcpy(buf, "\035R\035CC\
--Press-Control-O-for-options-and-help----Type-`.'-alone-on-a-line-to-finish-\
-|\035CA\035a");
	t_lineout(buf, 0);
}


/* Display the current editor body.
 */
void ed_redraw__body(void)
{
	long i;

	t_goto(0, ed__start_line);

	for (i = ed__topline;
	     i < (ed__topline + t_rows - 1 - ed__start_line); i++) {
		ed_redraw_line(i);
	}

	t_goto(ed__curchar - ed__leftchar,
	       ed__start_line + (ed__curline - ed__topline));
}


/* Display the help screen.
 */
void ed_redraw__help(void)
{
	char buf[1024];

	ed_redraw__title("Editing Options");

	t_lineout(0, 0);
	t_lineout("\035UAltering options keys:\035u               "
		  "\035UManipulation keys:\035u", 0);
	t_lineout(0, 0);

	sprintf(buf, "[\035BO\035b] Current mode: %s            "
		"[\035BUP\035b] Top of file  "
		"[\035BSPACE\035b] Save & Exit",
		ed_opt__insert ? "Insert   " : "Overwrite");
	t_lineout(buf, 0);

	sprintf(buf, "[\035BA\035b] Auto indent : %s                "
		"[\035BDOWN\035b] End of file      "
		"[\035BQ\035b] \035R\035CRQuit Edit\035CA\035a",
		ed_opt__indent ? "On " : "Off");
	t_lineout(buf, 0);

	sprintf(buf, "[\035BW\035b] Word wrap   : %s                   "
		"[\035BG\035b] Goto line        "
		"[\035BF\035b] Find text", ed_opt__wrap ? "On " : "Off");
	t_lineout(buf, 0);

	sprintf(buf, "[\035BR\035b] Right margin: %-3d                   "
		"[\035BM\035b] Mark block       "
		"[\035BB\035b] Insert block", ed_opt__margin);
	t_lineout(buf, 0);

	t_lineout("                                        "
		  "[\035BJ\035b] Justify paragraph", 0);
	t_lineout("                                        "
		  "[\035BD\035b] Insert Datestamp", 0);

	t_lineout(0, 0);
	t_lineout("\035UList of control keys available while editing\035u",
		  0);
	t_lineout(0, 0);
	t_lineout("  [\035B^B\035b] Left              "
		  "[\035B^F\035b] Right             "
		  "[\035B^P\035b] Up", 0);
	t_lineout("  [\035B^N\035b] Down              "
		  "[\035B^A\035b] Home              "
		  "[\035B^E\035b] End", 0);
	t_lineout("  [\035B^W\035b] Previous Word     "
		  "[\035B^T\035b] Next Word         "
		  "[\035B^U\035b] Previous Screen", 0);
	t_lineout("  [\035B^V\035b] Next Screen       "
		  "[\035B^D\035b] Delete Right      "
		  "[\035B^O\035b] Select Options", 0);
	t_lineout("  [\035B^X\035b] Cut Line          "
		  "[\035B^Y\035b] Paste             "
		  "[\035B^K\035b] Cut Forwards", 0);
	t_lineout("  [\035B^G\035b] Attribute", 0);

	t_lineout(0, 0);
	t_lineout("Press [\035BTAB\035b] to return to the editor.", 0);

	t_goto(0, t_rows - 1);
}


/* Redraw the whole of the screen.
 */
void ed_redraw(char *title, char *header)
{
	t_clear();
	if (ed__showhelp) {
		ed_redraw__help();
	} else {
		ed_redraw__title(title);
		ed_redraw__header(header);
		ed_redraw__body();
	}
}


/* Output line "l" to the current cursor position, followed by a newline.
 * The screen line is cleared beforehand.
 */
void ed_redraw_line(long l)
{
	char buf[5500];
	char *a;
	long i;
	long n;
	int x;

	t_clrtoeol();

	if (l >= ed__lines) {
		t_lineout(0, 0);
		return;
	}

	a = ed__array[l];
	if (!a)
		a = "";

	if (l == ed__curline) {		    /* current line is shown specially */

		i = ed__leftchar;
		if (i > strlen(a))
			i = strlen(a);
		n = t_cols;
		if (n > ((sizeof(buf) / 5) - 16))
			n = (sizeof(buf) / 5) - 16;
		buf[0] = 0;
		if (ed__leftchar > 0)
			i++;
		strncat(buf, a + i, n);
		buf[n] = 0;
		ed_line_expand(buf, sizeof(buf));
		x = 0;
		if (ed__leftchar > 0)
			mstrinsert(buf, "\035R<\035r", &x, sizeof(buf));

	} else {

		strncpy(buf, a, sizeof(buf) - 16);
		buf[sizeof(buf) - 16] = 0;

	}

	ed_redraw__terminate(buf);
	t_lineout(buf, 0);
}


/* Expand the contents of "buf" so that attribute characters are replaced by
 * \035R]\035r glyphs and insert \035a at the start of the buffer to prevent
 * automatic tag expansion by t_lineout(). ^Hs are also expanded.
 *
 * "sz" is the size of "buf".
 */
void ed_line_expand(char *buf, long sz)
{
	int n;

	n = 0;
	mstrinsert(buf, "\035a", &n, sz);

	for (n = 2; buf[n] != 0; n++) {
		if (miscntl(buf[n])) {
			n++;
			mstrinsert(buf, "R]\035r", &n, sz);
			n--;
		} else if (buf[n] == 8) {
			buf[n] = '\035';
			n++;
			mstrinsert(buf, "RH\035r", &n, sz);
			n--;
		}
	}
}

/* EOF */
