Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Posting-Version: version B 2.10.1 6/24/83; site rna.UUCP
Path: utzoo!watmath!clyde!burl!mgnetp!ihnp4!houxm!houxz!vax135!floyd!cmcl2!rna!dan
From: dan@rna.UUCP (Dan Ts'o)
Newsgroups: net.emacs
Subject: CIT500 driver for EMACS
Message-ID: <262@rna.UUCP>
Date: Mon, 25-Jun-84 00:28:16 EDT
Article-I.D.: rna.262
Posted: Mon Jun 25 00:28:16 1984
Date-Received: Fri, 22-Jun-84 08:47:52 EDT
Organization: Rockefeller Neurobiology, NYC
Lines: 354

HI,
	Having received a number of requests for the CIT500 driver for
EMACS, here it is. Actually it should be quite suitable for most full-featured
ANSI terminals with functions such as line delete and insert and change scroll
region. (VT100's don't have line insert and delete).
	I made a number of decisions in favor of my view of esthetics. For
multiwindowed displays, I feel that change scrolling region updates look better
than line-insert/delete, although more costly. Code is present for both,
however, so if you disagree, just comment out the change scroll code.
	I'd appreciate any feedback since I know there probably is much room
for improvement. I know that the padding is probably not quite correct, but then
the CIT500 has a large buffer. In any case, this driver performs much better
than TrmTERM.c for the CIT500.

					Cheers,
					Dan Ts'o
					...cmcl2!rna!dan

P.S.
	Once one is used to a 64-line terminal, 24-lines is puny.

/*
 * terminal control module for CIT 500
 *	based on originally on TrmBitG.c
 *	Dan Ts'o 4/84
 *	Should be fine for many ANSI-like terminals.
 *	Uses delete character, delete line, insert character, insert line,
 *		change scrolling region, set/reset insert mode, inverse
 *		video, some private functions like set/reset automargins,
 *		as well as the usual cursor addressing, clear screen, etc.
 */

#include 
#include "Trm.h"
#define	AM_IS_NORMAL	1	/* Define if Autowrap is always on,
				 *	undefine if uncertain
				 */

static
int	curX, curY;

static int   Baud;

static int   CIT_LI = 64,
#ifdef	AM_IS_NORMAL
	CIT_CO = 80;
#else
	CIT_CO = 79;
#endif
static int   WindowSize;

static
enum IDmode { m_insert = 1, m_overwrite = 0}
	DesiredMode, CurrentMode;

#define	PAD(n,f)	if(Baud>9600)pad(n,f)

static
INSmode (new)
enum IDmode new; {
	DesiredMode = new;
};

static
setmode ()
{
	if (DesiredMode == CurrentMode)
		return;
	if (DesiredMode == m_insert)
		printf("\033[4h");
	else
		printf("\033[4l");
	CurrentMode = DesiredMode;
}

static
CurHL, DesHL;

static
HLmode (new) {
	DesHL = new;
}

static
SetHL (OverRide) {
	register LDes = OverRide ? 0 : DesHL;
	if (LDes == CurHL)
		return;
	printf (LDes ? "\033[7m" : "\033[m");
	CurHL = LDes;
}

static
inslines (n)
register int n;
{
	SetHL (1);
	/* Esthetics - CS motions look better than insert/delete motions
	 * with multiple windows
	 * Check for multi-windowed display
	 */
	if (WindowSize != tt.t_length) {
		printf("\033[%d;%dr\033[%dH", curY, WindowSize, curY);
		curX = 1;
/*
		while (--n >= 0) {
			printf("\033M");
			PAD(1, 20.);
		}
 */
		printf (n <= 1 ? "\033[L" : "\033[%dL", n);
		PAD (CIT_LI-curY-n, 3.0);
		printf("\033[r");
		PAD(1, 2.);
		curX = curY = 1;
		return;
	}
	printf (n <= 1 ? "\033[L" : "\033[%dL", n);
	PAD (CIT_LI-curY-n, 3.0);
};

static
dellines (n)
register int n;
{
	SetHL (1);
	/* Check for multi-windowed display */
	if (WindowSize != tt.t_length) {
/*
		printf("\033[%d;%dr\033[%dH", curY, WindowSize, WindowSize);
		curX = 1;
		curY = WindowSize;
		while (--n >= 0) {
			printf("\033E");
			PAD(1, 20.);
		}
 */
		printf("\033[%d;%dr\033[%dH", curY, WindowSize, curY);
		curX = 1;
		printf (n <= 1 ? "\033[M" : "\033[%dM", n);
		PAD (CIT_LI-curY, 3.0);
		printf("\033[r");
		PAD(1, 2.);
		curX = curY = 1;
		return;
	};
	printf (n <= 1 ? "\033[M" : "\033[%dM", n);
	PAD (CIT_LI-curY, 3.0);
};

static
writechars (start, end)
register char *start,
	      *end; {
	register p = end-start+1;

	SetHL (0);
	setmode();
/*
	if (DesiredMode == m_insert) {
		printf ("\033[%d@", p);
		PAD (1, 3.0);
	}
 */
	curX += p;
	while (start <= end)
		putchar (*start++);
	PAD (p, .6);
};

static
blanks (n) {
	if (n > 0) {
		setmode();
		SetHL (0);
/*
		if (DesiredMode == m_insert) {
			printf ("\033[%d@", n);
			PAD (1, 3.0);
		}
 */
		curX += n;
		while (--n >= 0) putchar (' ');
/*
 		putchar (' ');
		if (--n)
			printf ("\b\033[%d@", n);
		else
			curX++;
 */
	}
	PAD (n, .6);
};

static float BaudFactor;

static pad(n,f)
float   f; {
	register k;

	k = n * f * BaudFactor;
	while (--k >= 0)
		putchar (0);
};

static
topos (row, column) {
	if (curY == row) {
		if (curX == column)
			return;
		if (curX == column + 1) {
			putchar ('\b');
			goto done;
		}
	}
	if (curY+1 == row && (column == 1 || column == curX)) {
		if (column != curX) putchar (015);
		putchar (012);
		goto done;
	}
	if (curY == row+1 && column == curX) {
		printf ("\033M");
		goto done;
	}
	if (row == 1 && column == 1) {
		printf ("\033[H");
		goto done;
	}
	if (column == 1) {
		printf ("\033[%dH", row);
		goto done;
	}
	printf ("\033[%d;%dH", row, column);
done: 
	curX = column;
	curY = row;
};

static
init (BaudRate) {
	Baud = BaudRate;
	BaudFactor = ((float) BaudRate) / 10000.;
};

static
reset () {
	/* Home, clear, no HL, keypad mode */
	printf ("\033[H\033[2J\033[m\033[r\033=");
#ifdef	AM_IS_NORMAL
	printf ("\033[?7l");
#endif
	WindowSize = tt.t_length;
	curX = curY = 1;
	CurHL = 0;
	DesiredMode = m_overwrite;
	CurrentMode = m_insert;
};

static
cleanup () {
	SetHL (1);
	topos (WindowSize, 1);
	printf("\033>");		/* Exit keypad mode */
#ifdef	AM_IS_NORMAL
	printf("\033[?7h");
#endif
	DesiredMode = m_overwrite;
	CurrentMode = m_insert;
	setmode();
};

static
wipeline () {
	SetHL (1);
	printf ("\033[K");
	PAD (1, 6.0);
};

static
wipescreen () {
	SetHL (1);
	printf("\033[2J");
	PAD (1, 10.0);
};

static
window (n)
register int n;
{
	if (n <= 0 || n > tt.t_length)
		n = tt.t_length;
	WindowSize = n;
}

static
delchars (n) {
	if (n<=0) return;
	SetHL (1);
	printf(n == 1 ? "\033[P" : "\033[%dP", n);
	PAD (1, 3.0);
};

static
flash () {
	printf ("\033[?5%c", InverseVideo ? 'h' : 'l');
	pad (1, 100.0);

	printf ("\033[?5%c", InverseVideo ? 'l' : 'h');
	pad (1, 100.0);		/* this is REALLY slow!! */
}

TrmCIT500 (term)
char *term;
{
	register char *s;
	char *getenv();
	char tbuf[1024];

	if (tgetent (tbuf, term) <= 0) {
		tt.t_length = CIT_LI = tgetnum("li");
		tt.t_width = CIT_CO = tgetnum("co")
#ifdef	AM_IS_NORMAL
			;
#else
			- (tgetflag("am") ? 1 : 0);
#endif
	}
	else {
		tt.t_length = CIT_LI;
		tt.t_width = CIT_CO;
	}
		
	tt.t_INSmode = INSmode;
	tt.t_HLmode = HLmode;
	tt.t_inslines = inslines;
	tt.t_dellines = dellines;
	tt.t_blanks = blanks;
	tt.t_init = init;
	tt.t_cleanup = cleanup;
	tt.t_wipeline = wipeline;
	tt.t_wipescreen = wipescreen;
	tt.t_topos = topos;
	tt.t_reset = reset;
	tt.t_delchars = delchars;
	tt.t_writechars = writechars;
	tt.t_flash = flash;
	tt.t_window = window;
	tt.t_ILmf = 0;
	tt.t_ILov = 5;
	tt.t_ICmf = 0;
	tt.t_ICov = 5;
	tt.t_DCmf = 0;
	tt.t_DCov = 5;
};