DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download
Index: ┃ T v

⟦dc859f3a9⟧ TextFile

    Length: 11456 (0x2cc0)
    Types: TextFile
    Names: »vterm.c«

Derivation

└─⟦87ddcff64⟧ Bits:30001253 CPHDIST85 Tape, 1985 Autumn Conference Copenhagen
    └─ ⟦this⟧ »cph85dist/wm/vterm.c« 

TextFile

/*
 *************
 * 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);
}