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