|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T v
Length: 11456 (0x2cc0)
Types: TextFile
Names: »vterm.c«
└─⟦87ddcff64⟧ Bits:30001253 CPHDIST85 Tape, 1985 Autumn Conference Copenhagen
└─⟦this⟧ »cph85dist/wm/vterm.c«
/*
*************
* DISTRIBUTION NOTICE July 30 1985
* A Revised Edition of WM, by Matt Lennon and Tom Truscott,
* Research Triangle Institute, (919) 541-7005.
* Based on the original by Robert Jacob (decvax!nrl-css!jacob),
* Naval Research Laboratory, (202) 767-3365.
* No claims or warranties of any sort are made for this distribution.
* General permission is granted to copy, but not for profit,
* any of this distribution, provided that this notice
* is always included in the copies.
*************
*/
/*
* This file contains routines for low-level virtual
* terminal emulation.
*/
#include "wm.h"
#define FULLWIDTH(wp) (wcols(wp)==COLS)
#define FULLSCREEN(wp) (FULLWIDTH(wp) && wlines(wp)==LINES-1)
/* Termcap entry for virtual terminals.
*/
static char TERMCAP[]="wm|wmvirt|wm virtual terminal:am:bs:ce=\\EK:ho=\\EH:cd=\\EB:cl=\\ES:nd=\\EC:up=\\EA:cm=\\EY%+ %+ :";
#define TBUFLEN (sizeof(TERMCAP)+300) /* max length of termcap string */
extern char *tgoto(), *tparm();
/*
* Add 'n' characters of 'p' to window 'w' at its current (y, x) coordinate.
*/
WMaddbuf(w, p, n)
int w;
register char *p;
register int n;
{
register WINDOW *wp;
register int y, x;
register int c;
/*
* Are we in the midst of an escape sequence?
*/
while (win[w].pend[0] && --n >= 0)
WMescape(w, toascii(*p++));
wp = win[w].wptr;
getyx(wp, y, x);
while (--n >= 0) switch (c = toascii(*p++))
{
case '\t':
x = (x+8) & ~07;
while (x >= wcols(wp)) {
WMaddbuf(w, "\n", 1);
x -= wcols(wp);
}
wmove(wp, y = wcury(wp), x);
break;
case '\n':
if (++y >= wlines(wp)) {
--y;
wmove(wp, 0, x); WMdeleteln(w);
}
wmove(wp, y, x);
break;
case '\r':
wmove(wp, y, x = 0);
break;
case '\b':
if (x>0) wmove(wp, y, --x);
break;
case '\007':
beep();
break;
case '\0':
break;
case ESC:
win[w].pend[0] = ESC;
win[w].pend[1] = '\0';
while (win[w].pend[0] && --n >= 0)
WMescape(w, toascii(*p++));
getyx(wp, y, x);
break;
/* Dummy cases to fool pcc into generating a fast switch table */
case 01: case 02: case 03: case 04: case 05: case 06:
default:
if (isprint(c))
{
waddch(wp, c);
if (++x >= wcols(wp)) {
if (++y >= wlines(wp)) {
--y;
wmove(wp, 0, 0); WMdeleteln(w);
}
wmove(wp, y, x = 0);
}
}
else
{
char *s = mkprint(c);
WMaddbuf(w, s, strlen(s));
getyx(wp, y, x);
}
break;
}
}
/*
* Construct virtual terminal escape sequence
* one character at a time.
* When escape sequence is complete, perform
* the indicated action in window 'w'.
*/
WMescape(w, c)
int w;
int c;
{
register WINDOW *wp;
register int y, x;
register char *pend;
int oldx, oldy;
pend = win[w].pend;
wp = win[w].wptr;
getyx(wp, y, x);
/* ESC-Y is a multi-character escape sequence
* so we need to make sure we have all the
* characters before we start processing it.
*/
if (c == 'Y' && pend[1] == '\0') { pend[1]=c; pend[2]='\0'; return; }
else if (pend[1] == 'Y')
{
if (pend[2]=='\0') { pend[2]=c; return; }
else { pend[3]=c; c='Y'; }
}
/* Process escape sequence.
*/
pend[0] = '\0'; /* escape no longer pending */
switch (c)
{
case 'Y': /* cursor motion */
y = oldy = pend[2]-' '; x = oldx = pend[3]-' ';
if (x < 0) x = 0;
if (y < 0) y = 0;
if (x >= wcols(wp)) x = wcols(wp)-1;
if (y >= wlines(wp)) y = wlines(wp)-1;
if (y != oldy || x != oldx)
showmsg("Bad cursor motion to (%d,%d).", oldy, oldx);
wmove(wp, y, x);
break;
case 'K': /* clear to end of line */
wclrtoeol(wp);
break;
case 'B': /* clear to bottom of window */
wclrtobot(wp);
break;
case 'H': /* home cursor */
wmove(wp, 0, 0);
break;
case 'R': /* visual bell */
flash();
break;
case 'D': /* delete line */
WMdeleteln(w);
break;
case 'L': /* insert line */
WMinsertln(w);
break;
case 'P': /* insert character */
#ifdef CURSEASSIST
#ifndef TERMINFO
if (FULLWIDTH(wp) && insert_character && !insert_null_glitch) {
(void) movecursor(wbegy(wp)+y, wbegx(wp)+x);
putp(insert_character); winsch(curscr, ' ');
}
#endif
#endif
winsch(wp, ' ');
break;
case 'Q': /* delete character */
#ifdef CURSEASSIST
#ifndef TERMINFO
if (FULLWIDTH(wp) && delete_character) {
(void) movecursor(wbegy(wp)+y, wbegx(wp)+x);
putp(delete_character); wdelch(curscr);
}
#endif
#endif
wdelch(wp);
break;
case 'S': /* erase window */
werase(wp);
#ifdef CURSEASSIST
if (FULLSCREEN(wp) && !msgbirth)
clearok(curscr, TRUE);
#endif
break;
case 'C': /* non-destructive blank */
if (++x >= wcols(wp)) {
WMaddbuf(w, "\n", 1);
x = 0;
}
wmove(wp, wcury(wp), x);
break;
case 'A': /* cursor up */
if (--y>=0) wmove(wp, y, x);
break;
case 'O': /* enter standout mode */
wstandout(wp);
break;
case 'E': /* leave standout mode */
wstandend(wp);
break;
default:
{
char *s;
s = mkprint(ESC);
WMaddbuf(w, s, strlen(s));
s = mkprint(c);
WMaddbuf(w, s, strlen(s));
}
break;
}
}
/*
* Insert a line just above the current line of window wp.
* The cursor location in wp is not changed.
*/
WMinsertln(w)
int w;
{
register WINDOW *wp;
register int curline, curcol;
wp = win[w].wptr;
wrefresh(wp); /* smooths scrolling. Crucial for untouchwin. */
winsertln(wp);
#ifdef CURSEASSIST
/* If this terminal has scrolling regions, use them */
if (has_scroll_region && FULLWIDTH(wp)) {
/* First, get curscr management out of the way. */
curline = cursrow(); curcol = curscol();
Cmove(wbegy(wp)+wlines(wp)-1, 0);
Cdeleteln();
Cmove(wbegy(wp)+wcury(wp), 0);
Cinsertln();
Cmove(curline, curcol);
/* now update the screen itself */
(void) movecursor(wbegy(wp)+wcury(wp), wbegx(wp)+wcurx(wp));
putp(save_cursor); /* Save since CS garbles cursor */
putp(tgoto(change_scroll_region,
wbegy(wp)+wlines(wp)-1, wbegy(wp)+wcury(wp)));
putp(restore_cursor); /* CS garbles cursor */
putp(scroll_reverse);
putp(tgoto(change_scroll_region, LINES-1, 0));
putp(restore_cursor); /* Once again put it back */
Untouchwin(wp);
}
/* Else if this terminal has scrolling rectangles, use them now. */
#ifdef SET_WINDOW
else if (has_scroll_window) {
overwrite(wp, curscr); /* slow but easy */
putp(tparm(set_window,
wbegy(wp)+wcury(wp), wbegy(wp)+wlines(wp)-1,
wbegx(wp), wbegx(wp)+wcols(wp)-1));
putp(scroll_reverse);
putp(tparm(set_window, 0, LINES-1, 0, COLS-1));
/* get back to where curses thinks we are */
putp(tgoto(cursor_address, curscol(), cursrow()));
Untouchwin(wp);
}
#endif
/* Else if this terminal has ins/del line, now is the time */
else if (has_insdel_line && FULLWIDTH(wp)) {
/* Open a line above current line in window wp,
* then delete wp's bottom line.
* Perform identical operations on curscr
* as we do on the terminal itself.
*/
(void) movecursor(wbegy(wp)+wcury(wp), 0);
putp(insert_line); Cinsertln();
(void) movecursor(wbegy(wp)+wlines(wp), 0);
putp(delete_line); Cdeleteln();
RestoreMsg();
Untouchwin(wp);
}
#endif
}
/*
* This routine deletes the current line in window wp.
* The cursor location in wp is not changed.
*/
WMdeleteln(w)
int w;
{
register WINDOW *wp;
register int curline, curcol;
wp = win[w].wptr;
/*
* See what we can do about windows that scroll slowly
*/
if (!(win[w].flags&FAST)) {
static int lines_since_refresh = 0;
if ((lines_since_refresh += 7) >= wlines(wp)) {
wrefresh(wp);
lines_since_refresh = 0;
}
wdeleteln(wp);
#ifdef BUGGYTERMINFO
touchwin(wp);
#endif
return;
}
wrefresh(wp); /* smooths scrolling. Crucial for untouchwin. */
wdeleteln(wp);
#ifdef BUGGYTERMINFO
/* wdeleteln neglects first/bottom info for the last line */
touchwin(wp);
#endif
#ifdef CURSEASSIST
/* If we're deleting top line of a full screen window,
* this is the same as scrolling.
* (We do not this if we have scrolling region support
* and there is a wm message, but what a bother.)
*/
if (FULLSCREEN(wp) && wcury(wp)==0 && !(has_scroll_region && msgbirth))
{
ZapMsgLine(); /* so it doesn't scroll up into our window */
curline = cursrow(); curcol = curscol();
Cmove(0, 0); Cdeleteln();
Cmove(curline, curcol);
/* Cause screen to scroll.
* Since wm almost always 'wants' the cursor on LINES-2,
* there is a cheap heuristic thrown in.
*/
(void) movecursor(LINES, curcol);
#ifndef TERMINFO
if (cursor_up) {
putp(cursor_up);
Cmove(LINES-2, curcol);
}
#endif
RestoreMsg();
Untouchwin(wp);
}
/* Else if this terminal has scrolling regions, use them. */
else if (has_scroll_region && FULLWIDTH(wp)) {
curline = cursrow(); curcol = curscol();
Cmove(wbegy(wp)+wcury(wp), 0);
Cdeleteln(); /* it is about to be deleted */
Cmove(wbegy(wp)+wlines(wp)-1, 0);
Cinsertln(); /* it is about to be cleared */
Cmove(curline, curcol);
(void) movecursor(wbegy(wp)+wlines(wp)-1, wbegx(wp)+wcurx(wp));
putp(save_cursor); /* Save since CS garbles cursor */
putp(tgoto(change_scroll_region,
wbegy(wp)+wlines(wp)-1, wbegy(wp)+wcury(wp)));
putp(restore_cursor); /* put cursor back */
putp(scroll_forward);
putp(tgoto(change_scroll_region, LINES-1, 0));
putp(restore_cursor); /* put cursor back */
Untouchwin(wp);
}
/* Else if this terminal has scrolling rectangles, use them. */
#ifdef SET_WINDOW
else if (has_scroll_window) {
overwrite(wp, curscr); /* slow but easy */
putp(tparm(set_window,
wbegy(wp)+wcury(wp), wbegy(wp)+wlines(wp)-1,
wbegx(wp), wbegx(wp)+wcols(wp)-1));
putp(tgoto(cursor_address, 0, wlines(wp)-1));
putp(scroll_forward);
putp(tparm(set_window, 0, LINES-1, 0, COLS-1));
putp(tgoto(cursor_address, curscol(), cursrow()));
Untouchwin(wp);
}
#endif
/* Else if this terminal has insdel line, use that. */
else if (has_insdel_line && FULLWIDTH(wp)) {
/* Open a line below the last line in window wp,
* then delete wp's current line.
*/
(void) movecursor(wbegy(wp)+wlines(wp), 0);
putp(insert_line); Cinsertln();
(void) movecursor(wbegy(wp)+wcury(wp), 0);
putp(delete_line); Cdeleteln();
RestoreMsg();
Untouchwin(wp);
}
#endif
}
/*
* Construct termcap for wmvirt terminal in window w.
*/
char *
termcap(w)
int w;
{
register WINDOW *wp;
static char tbuf[TBUFLEN]; /* termcap buffer */
wp = win[w].wptr;
(void)sprintf(tbuf, "%sco#%d:li#%d:", TERMCAP, wcols(wp), wlines(wp));
/* If terminal scrolls 'quickly', add insert/delete line to termcap. */
if ((win[w].flags&FAST)
&& (has_insdel_line || has_scroll_region || has_scroll_window))
strcat(tbuf, "al=\\EL:dl=\\ED:");
/* If terminal has insert/delete character options, add them here */
if (insert_character || (enter_insert_mode && exit_insert_mode))
strcat(tbuf, "ic=\\EP:");
if (delete_character)
strcat(tbuf, "dc=\\EQ:");
/* If terminal has standout capabilities, add that too. */
if (enter_standout_mode && exit_standout_mode)
strcat(tbuf, "so=\\EO:se=\\EE:");
/* Include vb if terminal has a visual bell */
if (flash_screen)
strcat(tbuf, "vb=\\ER:");
/* Include keypad capabilities if there is room left */
if (strlen(tbuf)+strlen(keycap) < TBUFLEN)
strcat(tbuf, keycap);
return(tbuf);
}