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