dan@rna.UUCP (Dan Ts'o) (06/25/84)
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 <stdio.h>
#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;
};chris@umcp-cs.UUCP (07/02/84)
Just got around to looking at rna!dan's CIT500 terminal driver. I noticed
one odd thing in the code. In TrmCIT500(), there is the following:
if (tgetent (tbuf, term) <= 0) {
tt.t_length = CIT_LI = tgetnum("li");
tt.t_width = CIT_CO = tgetnum("co")
.
.
.
Now, I don't know about your tgetent, but ours (4.1BSD) returns 1 if
the tgetent succeeded. So it seems to me that the code should say
if (tgetent (tbuf, term) > 0) {
.
.
.
Other than that, it looks reasonable. By the way, for Emacs #264
you'd want to change all the padding calls to use fltofixp and
friends. (For mine, you'd use the `pad' routine in display.c with
`long' values in terms of microseconds, but then you don't have mine.)
--
In-Real-Life: Chris Torek, Univ of MD Comp Sci (301) 454-7690
UUCP: {seismo,allegra,brl-bmd}!umcp-cs!chris
CSNet: chris@umcp-cs ARPA: chris@maryland