jct@jct.UUCP (jct) (07/11/89)
#! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 8 (of 9)." # Contents: lib/scrout1.c # Wrapped by jct@ on Mon Jul 10 22:48:32 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'lib/scrout1.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'lib/scrout1.c'\" else echo shar: Extracting \"'lib/scrout1.c'\" \(37438 characters\) sed "s/^X//" >'lib/scrout1.c' <<'END_OF_FILE' X/* module screen output */ X X/* X provides UNIX "curses" type routines X define MMAPPED if output is memory mapped X*/ X X/* X created May 5, 1987 by JCT X*/ X X/* X * Copyright (c) John C. Tompkins 1989 X * All rights reserved. X * X * Permission is granted to use this for any personal, noncommercial use. X * You may not distribute source or executable code for profit, nor X * may you distribute it with a commercial product without the prior X * written consent of the author. Please send modifications to the X * author for inclusion in updates to the program. X */ X X#include <stdio.h> X#include <fcntl.h> X#include <ctype.h> X X#include <km/defs.h> X#include <km/ascii.h> X#include <km/scrio.h> X#include <km/string1.h> X X#ifdef DOS /* must come after <km/defs.h> */ X#include <dos.h> X#endif X X/* X The following are masks and forground, background color bits X*/ X X#define A_MASK 0x00ff /* attribute flags mask */ X#define C_MASK 0x00ff /* color flags mask */ X#define F_MASK 0x00f0 /* 16 colors, 4 bits */ X#define B_MASK 0x000f /* 16 colors, 4 bits */ X#define F_BLACK 0x0000 X#define F_RED 0x0010 X#define F_GREEN 0x0020 X#define F_YELLOW 0x0030 X#define F_BLUE 0x0040 X#define F_MAGENTA 0x0050 X#define F_CYAN 0x0060 X#define F_WHITE 0x0070 X#define F_C8 0x0080 X#define F_C9 0x0090 X#define F_C10 0x00a0 X#define F_C11 0x00b0 X#define F_C12 0x00c0 X#define F_C13 0x00d0 X#define F_C14 0x00e0 X#define F_C15 0x00f0 X#define B_BLACK 0x0000 X#define B_RED 0x0001 X#define B_GREEN 0x0002 X#define B_YELLOW 0x0003 X#define B_BLUE 0x0004 X#define B_MAGENTA 0x0005 X#define B_CYAN 0x0006 X#define B_WHITE 0x0007 X#define B_C8 0x0008 X#define B_C9 0x0009 X#define B_C10 0x000a X#define B_C11 0x000b X#define B_C12 0x000c X#define B_C13 0x000d X#define B_C14 0x000e X#define B_C15 0x000f X#define OUTBUF_SIZE 256 X#define IOUTBUF_SIZE 20 X#define COLOR_SIZE 16 X#define BOX_SIZE 11 X typedef struct X { X char *name; X short value; X } COLOR_ENTRY; X typedef struct X { X int fg; X int bg; X } COLOR_BITS; X int LINES, COLS; int have_standout, have_blink, have_bold, have_underline; int have_color, have_graphic, rev_color; int def_fg = WHITE, def_bg = BLACK; WINDOW *stdscr = WIN_NULL; WINDOW *curscr = WIN_NULL; X#ifdef UNIX KEY_TBL key_tbl[KEY_TBL_SIZE]; int key_tbl_index; X#endif X X#ifdef UNIX static char termcap[1024], tc_tbl[1024], *tc_ptr; X#endif X#ifndef MMAPPED static char *_al, *_cd, *_ce, *_ci, *_cl, *_cm, *_dc, *_dl, *_do, X *_ei, *_im, *_is, *_nd, *_se, *_sf, *_so, *_sr, *_te, X *_ti, *_ue, *_us, *_ve, *_vs, *_sc, *_gs, *_ge, *_bs, X *_be, *_hs, *_he; static char outbuf[OUTBUF_SIZE]; static char *pout = outbuf; static char *color_tbl[COLOR_SIZE]; static int outbuf_count = 0, pfast = TRUE; static short *c_color, *c_attrib, *c_y_cur, *c_x_cur, c_x_max; X#endif static char *_ke, *_ks, *_gb; static char ioutbuf[IOUTBUF_SIZE]; static char *piout = ioutbuf; static int ioutbuf_count = 0; static char box_tbl[BOX_SIZE]; static char fake_tbl[BOX_SIZE] = {'-', '|', '+', '+', '+', '+', '+', '+', '+', '+', '+'}; static int LAST_y, LAST_x; X static COLOR_ENTRY color_table[] = X { X "BLACK", BLACK, X "RED", RED, X "GREEN", GREEN, X "YELLOW", YELLOW, X "BLUE", BLUE, X "MAGENTA", MAGENTA, X "CYAN", CYAN, X "WHITE", WHITE, X "COLOR_8", COLOR_8, X "COLOR_9", COLOR_9, X "COLOR_10", COLOR_10, X "COLOR_11", COLOR_11, X "COLOR_12", COLOR_12, X "COLOR_13", COLOR_13, X "COLOR_14", COLOR_14, X "COLOR_15", COLOR_15, X "UNDETERMINED", UNDETERMINED, X 0, 0 X }; X static COLOR_BITS bits_tbl[] = X { X F_BLACK, B_BLACK, X F_RED, B_RED, X F_GREEN, B_GREEN, X F_YELLOW, B_YELLOW, X F_BLUE, B_BLUE, X F_MAGENTA, B_MAGENTA, X F_CYAN, B_CYAN, X F_WHITE, B_WHITE, X F_C8, B_C8, X F_C9, B_C9, X F_C10, B_C10, X F_C11, B_C11, X F_C12, B_C12, X F_C13, B_C13, X F_C14, B_C14, X F_C15, B_C15, X }; X extern char *malloc(), *getenv(), *tgetstr(), *strcpy(); extern void free(); extern FILE *popen(), *fopen(); X X/* X The following are support routines X*/ X X#ifndef MMAPPED X X#define _puts(s) tputs(s, 0, _putchar) X static void _flush_outbuf() /* flush physical output buffer */ X{ X#ifdef DOS X int i; X X for (i = 0; i < outbuf_count; i++) X bdos(0x06, outbuf[i], 0); X pout = outbuf; X outbuf_count = 0; X#else X if (outbuf_count > 0) X { X write(_tty_ch, outbuf, outbuf_count); X pout = outbuf; X outbuf_count = 0; X } X#endif X} X static void _putchar(data) /* physical output of data */ X int data; X{ X *pout++ = data; X if (++outbuf_count >= OUTBUF_SIZE) X _flush_outbuf(); X} X static void _putstr(data) X REGISTER char *data; X{ X if (data) X { X while (*data) X { X *pout++ = *data++; X if (++outbuf_count >= OUTBUF_SIZE) X _flush_outbuf(); X } X } X} X X#endif X static void _iflush_outbuf() /* flush immediate output buffer */ X{ X#ifdef DOS X int i; X X for (i = 0; i < ioutbuf_count; i++) X bdos(0x06, ioutbuf[i], 0); X piout = ioutbuf; X ioutbuf_count = 0; X#else X if (ioutbuf_count > 0) X { X write(_tty_ch, ioutbuf, ioutbuf_count); X piout = ioutbuf; X ioutbuf_count = 0; X } X#endif X} X static void _iputchar(data) /* physical output immediate */ X int data; X{ X *piout++ = data; X if (++ioutbuf_count >= IOUTBUF_SIZE) X _iflush_outbuf(); X} X static void _iputs(s) /* immediate output string */ X char *s; X{ X tputs(s, 0, _iputchar); X _iflush_outbuf(); X} X X#ifndef MMAPPED X static void _goto(y, x) /* physical cursor positioning */ X int y; X int x; X{ X REGISTER WINDOW *p; X X p = curscr; X if (p->y_cur == y) X { X if ((p->x_cur - 1) == x) X { X if (BC) X _puts(BC); X else X _putchar(BS); X } X else if ((p->x_cur + 1) == x) X { X if (_nd) X _puts(_nd); X else X _puts(tgoto(_cm, x, y)); X } X else X _puts(tgoto(_cm, x, y)); X } X else if (p->x_cur == x) X { X if ((p->y_cur - 1) == y) X { X if (UP) X _puts(UP); X else X _puts(tgoto(_cm, x, y)); X } X else if ((p->y_cur + 1) == y) X { X if (_do) X _puts(_do); X else X _puts(tgoto(_cm, x, y)); X } X else X _puts(tgoto(_cm, x, y)); X } X else X _puts(tgoto(_cm, x, y)); X p->y_cur = y; X p->x_cur = x; X} X static void _setcolor(color) /* physical set terminal color */ X int color; X{ X REGISTER char *ptr1, *ptr2; X X if (ptr1 = _sc) X { X while (*ptr1) X { X if (*ptr1 == '%') X { X if (*(ptr1 + 1) == 'f') X { X ptr2 = color_tbl[(color >> 4) & 0x0f]; X while (*ptr2) X _putchar(*ptr2++); X ptr1++; X } X else if (*(ptr1 + 1) == 'b') X { X ptr2 = color_tbl[color & 0x0f]; X while (*ptr2) X _putchar(*ptr2++); X ptr1++; X } X else if (*(ptr1 + 1) == '%') X { X _putchar('%'); X ptr1++; X } X } X else X _putchar(*ptr1); X ptr1++; X } X } X curscr->color = color; X} X static void _setattrib(attrib, color) /* physical set terminal attributes */ X REGISTER int attrib; X int color; X{ X REGISTER short *p; X X p = &curscr->attrib; X if ((*p & GRAPHIC) && !(attrib & GRAPHIC)) X _puts(_ge); X if (!(rev_color && color) && (*p & STANDOUT) && !(attrib & STANDOUT)) X _puts(_se); X else if (*p & BLINK) X _puts(_be); X else if (*p & BOLD) X _puts(_he); X else if (*p & UNDERLINE) X _puts(_ue); X if (!(*p & GRAPHIC) && (attrib & GRAPHIC)) X _puts(_gs); X if (!(rev_color && color) && !(*p & STANDOUT) && (attrib & STANDOUT)) X _puts(_so); X else if (attrib & BLINK) X _puts(_bs); X else if (attrib & BOLD) X _puts(_hs); X else if (attrib & UNDERLINE) X _puts(_us); X *p = attrib; X#ifdef DOS X curscr->color = 0; X#endif X} X static int so_analyze() /* check standout ability */ X{ X char *so_ptr; X X if (!_se) X _so = NULL; X if (so_ptr = _so) X { X while (isdigit(*so_ptr)) X so_ptr++; X if (!isprint(*so_ptr)) X return(TRUE); X else X { X _so = NULL; X _se = NULL; X return(FALSE); X } X } X else X return(FALSE); X} X static int sc_analyze() /* check and set color parameters */ X{ X char *temp; X int i, all_em = FALSE, fg = FALSE, bg = FALSE; X X if (!_sc) X return(FALSE); X temp = _sc; X for (i = 0; i < COLOR_SIZE; i++) X color_tbl[i] = NULL; X while (*temp) X { X if (*temp == '%') X { X if (*(temp + 1) == 'f') X { X fg = TRUE; X temp++; X } X else if (*(temp + 1) == 'b') X { X bg = TRUE; X temp++; X } X else if (*(temp + 1) == 'c') X { X *temp = '\0'; X temp += 2; X i = 0; X while (*temp && (i < COLOR_SIZE)) X { X color_tbl[i] = temp; X while (*temp && (*temp != ',')) X temp++; X *temp++ = '\0'; X i++; X } X all_em = (i == COLOR_SIZE); X } X } X temp++; X } X if (!fg || !bg || !all_em) X { X _sc = NULL; X return(FALSE); X } X else X return(TRUE); X} X X#endif /* ifndef MMAPPED */ X static int gb_analyze() /* check and set box parameters */ X{ X char *temp; X int i; X X#ifndef MMAPPED X if (!_gb || !_gs || !_ge) X { X _gs = NULL; X _ge = NULL; X return(FALSE); X } X#endif X temp = _gb; X for (i = 0; i < BOX_SIZE; i++) X box_tbl[i] = UNDETERMINED; X i = 0; X while (*temp && (i < BOX_SIZE)) X { X box_tbl[i] = *temp; X temp++; X i++; X } X if (i != BOX_SIZE) X { X#ifndef MMAPPED X _gs = NULL; X _ge = NULL; X#endif X return(FALSE); X } X else X return(TRUE); X} X X#ifndef MMAPPED X static int us_analyze() X{ X if (_us && _ue) X return(TRUE); X _us = NULL; X _ue = NULL; X return(FALSE); X} X static int bs_analyze() X{ X if (_bs && _be) X return(TRUE); X _bs = NULL; X _be = NULL; X return(FALSE); X} X static int hs_analyze() X{ X if (_hs && _he) X return(TRUE); X _hs = NULL; X _he = NULL; X return(FALSE); X} X X#endif /* if MMAPPED */ X X#ifdef UNIX static void init_key_tbl() X{ X key_tbl_index = 0; X} X static void add_key_tbl(name, default_seq, value) X char *name; X char *default_seq; X int value; X{ X X/* X adds an ASCII keysequence to the lookup table X used to decipher arrows keys, function keys etc... X*/ X X if (key_tbl_index < KEY_TBL_SIZE) X { X if (!name || (!(key_tbl[key_tbl_index].str = tgetstr(name, &tc_ptr)))) X key_tbl[key_tbl_index].str = default_seq; X key_tbl[key_tbl_index].key = value; X key_tbl_index++; X } X} X#endif X X/* X The following are standard "curses" like routines that use "static" X data or functions. All other functions are in other files. X*/ X int endwin() /* end screen modes */ X{ X WINDOW *next; X X for (next = stdscr->next; next && next->next; next = next->next) X ; X for (; next && next->prev; next = next->prev) X delwin(next, FALSE); X wendattrib(stdscr); X wsetcolor(stdscr, def_fg, def_bg); X werase(stdscr); X#ifndef MMAPPED X werase(curscr); X#endif X wrefresh(stdscr); X keypadend(); X#ifndef MMAPPED X if (_te) X _puts(_te); X if (_ve) X _puts(_ve); X _flush_outbuf(); X#endif X resetty(); X return(TRUE); X} X WINDOW *initscr() /* begin screen modes */ X{ X char *ttptr; X X if (!stdscr) X { X _tty_ch = fileno(stdout); X#ifdef DOS X ttptr = Def_term; X#else X if (My_term || ((ttptr = getenv("TERM")) == NULL)) X ttptr = Def_term; X#endif X if (!setterm(ttptr)) X return(WIN_NULL); X#ifdef MMAPPED X if ((curscr = (WINDOW*)malloc(sizeof(WINDOW))) == WIN_NULL) X return(WIN_NULL); X curscr->buf_len = 0; X curscr->y_max = LINES; X curscr->x_max = COLS; X curscr->y_org = 0; X curscr->x_org = 0; X curscr->y_cur = 0; X curscr->x_cur = 0; X curscr->ch_cur = 0; X curscr->ch_first = 0; X curscr->ch_last = 0; X curscr->color = 0; X curscr->attrib = 0; X curscr->ch_flags = 0; X curscr->flags = 0; X curscr->prev = 0; X curscr->next = 0; X#else X if ((curscr = newwin(LINES, COLS, 0, 0)) == WIN_NULL) X return(WIN_NULL); X c_color = &curscr->color; X c_attrib = &curscr->attrib; X c_y_cur = &curscr->y_cur; X c_x_cur = &curscr->x_cur; X c_x_max = curscr->x_max; X#endif X if ((stdscr = newwin(LINES, COLS, 0, 0)) == WIN_NULL) X { X#ifndef MMAPPED X free(curscr->buf); X free(curscr); X#endif X return(WIN_NULL); X } X LAST_y = LINES - 1; X LAST_x = COLS - 1; X savetty(); X#ifdef DOS X ospeed = 0; X#else X ospeed = _stty.c_cflag & CBAUD; X#endif X } X else X werase(stdscr); X#ifndef MMAPPED X werase(curscr); X#endif X raw(); X noecho(); X nonl(); X#ifndef MMAPPED X if (_is) X _puts(_is); X if (_ti) X _puts(_ti); X if (_vs) X _puts(_vs); X _flush_outbuf(); /* force output before keypad */ X#endif X keypad(); /* keypad output is immediate */ X wrefresh(stdscr); X return(stdscr); X} X WINDOW *newwin(lines, cols, y_org, x_org) /* make a new window */ X int lines; X int cols; X int y_org; X int x_org; X{ X WINDOW *win, *p; X X if ((y_org < 0) || (x_org < 0) || X (lines <= 0) || ((y_org + lines) > LINES) || X (cols <= 0) || ((x_org + cols) > COLS)) X return(WIN_NULL); X if ((win = (WINDOW*)malloc(sizeof(WINDOW))) == WIN_NULL) X return(WIN_NULL); X win->buf_len = lines * cols; X if ((win->buf = (YX_ELEMENT*)malloc(win->buf_len * sizeof(YX_ELEMENT))) == (YX_ELEMENT*)NULL) X { X free((char*)win); X return(WIN_NULL); X } X win->y_max = lines; X win->x_max = cols; X win->y_org = y_org; X win->x_org = x_org; X win->y_cur = 0; X win->x_cur = 0; X win->ch_cur = win->buf; X win->ch_first = win->buf + win->buf_len - 1; X win->ch_last = win->buf; X win->color = 0; X win->attrib = 0; X win->flags = 0; X win->ch_flags = 0; X if (stdscr == WIN_NULL) X { X win->prev = WIN_NULL; X win->next = WIN_NULL; X } X else X { X for (p = stdscr; p->next != WIN_NULL; p = p->next) X ; X p->next = win; X win->prev = p; X win->next = NULL; X } X if ((y_org == 0) && (x_org == 0) && (lines == LINES) && (cols == COLS)) X win->flags |= FULLWINDOW; X#ifndef MMAPPED X if (((x_org + cols) == COLS) && _ce) X win->flags |= TSTCLRTOEOL; X#endif X wsetcolor(win, def_fg, def_bg); X werase(win); X return(win); X} X int setterm(name) /* set terminal parameters for name */ X char *name; X{ X int stat = TRUE; X X#ifdef UNIX X init_key_tbl(); X#endif X if (!name || !*name) X name = Def_term; X#ifdef MMAPPED X ini_mmscr(); X#endif X#ifdef DOS X#ifndef MMAPPED X LINES = 25; X COLS = 80; X _al = "\033[L"; X BC = 0; X _cd = "\033[J"; X _ce = "\033[K"; X _cl = "\033[2J\e[H"; X _cm = "\033[%i%d;%dH"; X _dc = "\033[P"; X _dl = "\033[M"; X _do = 0; X _ei = 0; X _im = 0; X _is = 0; X _ke = 0; X _ks = 0; X _nd = "\033[C"; X _se = "\033[m"; X _sf = 0; X _so = "\033[7m"; X _sr = 0; X _te = 0; X _ti = 0; X _ue = "\033[m"; X UP = "\033[A"; X _us = "\033[4m"; X _ve = 0; X _vs = 0; X PC = 0; X _sc = "\033[3%fm\033[4%bm%c0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15"; X _ci = 0; X _gs = ""; X _ge = ""; X _bs = "\033[5m"; X _be = "\033[m"; X _hs = "\033[1m"; X _he = "\033[m"; X#endif /* if MMAPPED */ X _gb = "\304\263\305\332\302\277\264\331\301\300\303"; X rev_color = TRUE; X#else X if (tgetent(termcap, name) != 1) X { X name = "dumb"; X stat = FALSE; X } X tc_ptr = tc_tbl; X LINES = tgetnum("li"); X COLS = tgetnum("co"); X _al = tgetstr("al", &tc_ptr); X BC = tgetstr("bc", &tc_ptr); X _cd = tgetstr("cd", &tc_ptr); X _ce = tgetstr("ce", &tc_ptr); X _cl = tgetstr("cl", &tc_ptr); X _cm = tgetstr("cm", &tc_ptr); X _dc = tgetstr("dc", &tc_ptr); X _dl = tgetstr("dl", &tc_ptr); X _do = tgetstr("do", &tc_ptr); X _ei = tgetstr("ei", &tc_ptr); X _im = tgetstr("im", &tc_ptr); X _is = tgetstr("is", &tc_ptr); X _ke = tgetstr("ke", &tc_ptr); X _ks = tgetstr("ks", &tc_ptr); X _nd = tgetstr("nd", &tc_ptr); X _se = tgetstr("se", &tc_ptr); X _sf = tgetstr("sf", &tc_ptr); X _so = tgetstr("so", &tc_ptr); X _sr = tgetstr("sr", &tc_ptr); X _te = tgetstr("te", &tc_ptr); X _ti = tgetstr("ti", &tc_ptr); X _ue = tgetstr("ue", &tc_ptr); X UP = tgetstr("up", &tc_ptr); X _us = tgetstr("us", &tc_ptr); X _ve = tgetstr("ve", &tc_ptr); X _vs = tgetstr("vs", &tc_ptr); X PC = tgetchar("pc"); X _sc = tgetstr("SC", &tc_ptr); X _ci = tgetstr("CI", &tc_ptr); X _gs = tgetstr("GS", &tc_ptr); X _ge = tgetstr("GE", &tc_ptr); X _gb = tgetstr("GB", &tc_ptr); X _bs = tgetstr("BS", &tc_ptr); X _be = tgetstr("BE", &tc_ptr); X _hs = tgetstr("HS", &tc_ptr); X _he = tgetstr("HE", &tc_ptr); X rev_color = tgetflag("RC"); X#endif X#ifndef MMAPPED X have_color = sc_analyze(); X have_standout = so_analyze(); X have_underline = us_analyze(); X have_blink = bs_analyze(); X have_bold = hs_analyze(); X#endif X have_graphic = gb_analyze(); X#ifdef UNIX X add_key_tbl("ku", "\005", K_UP); X add_key_tbl("kd", "\030", K_DOWN); X add_key_tbl("kl", "\023", K_LEFT); X add_key_tbl("kr", "\004", K_RIGHT); X add_key_tbl("BT", "\033\t", K_BACKTAB); X add_key_tbl("BB", "\021\022", K_BEG_BUF); X add_key_tbl("EB", "\021\003", K_END_BUF); X add_key_tbl("BS", "\021\005", K_BEG_SCREEN); X add_key_tbl("ES", "\021\030", K_END_SCREEN); X add_key_tbl("BL", "\021\023", K_BEG_LINE); X add_key_tbl("EL", "\021\004", K_END_LINE); X add_key_tbl("FS", "\003", K_FWD_SCREEN); X add_key_tbl("RS", "\022", K_BWD_SCREEN); X add_key_tbl("FW", "\006", K_FWD_WORD); X add_key_tbl("RW", "\001", K_BWD_WORD); X add_key_tbl("DL", "\033y", K_DEL_LINE); X add_key_tbl("DW", "\024", K_DEL_WORD); X add_key_tbl("DC", "\007", K_DEL_CHAR); X add_key_tbl("KI", "\026", K_INSERT); X add_key_tbl("KH", "\033h", K_HELP); X add_key_tbl("KC", "\033c", K_CANCEL); X add_key_tbl("KQ", "\033q", K_QUIT); X add_key_tbl("KB", "\033 ", K_BACKUP); X add_key_tbl("KP", "\033p", K_PRINT); X add_key_tbl("k0", "\0331", K_F0); X add_key_tbl("k1", "\0332", K_F1); X add_key_tbl("k2", "\0333", K_F2); X add_key_tbl("k3", "\0334", K_F3); X add_key_tbl("k4", "\0335", K_F4); X add_key_tbl("k5", "\0336", K_F5); X add_key_tbl("k6", "\0337", K_F6); X add_key_tbl("k7", "\0338", K_F6); X add_key_tbl("k8", "\0339", K_F8); X add_key_tbl("k9", "\0330", K_F9); X#endif X#ifndef MMAPPED X if ((COLS == ERROR) || (LINES == ERROR) || streq(tgoto(_cm, 0, 0), "OOPS", TRUE)) X { X _cm = NULL; X name = "dumb"; X stat = FALSE; X } X#endif X strcpy(ttytype, name); X return(stat); X} X static void pos_cursor(win) X REGISTER WINDOW *win; X{ X X/* X Set physical cursor position and color X*/ X X#ifdef MMAPPED X pos_mmscr(win->y_cur + win->y_org, win->x_cur + win->x_org); X#else X _setattrib(0, win->color); X if ((curscr->y_cur != (win->y_cur + win->y_org)) || X (curscr->x_cur != (win->x_cur + win->x_org))) X _goto(win->y_cur + win->y_org, win->x_cur + win->x_org); X if (have_color && win->color && (curscr->color != win->color)) X _setcolor(win->color); X _flush_outbuf(); X#endif X} X X#ifndef MMAPPED X static int do_cur() X{ X X/* X Special case for refresh curscr. See wrefresh below. X This will clean up the entire screen no matter how many subwindows or X what their order. Used to clean the screen after 'noise' or other X unwanted chars appear, much like using CTRL-L in vi. X*/ X X int i, temp, cur_x, cur_y, color, save_color; X int weol_x, eol_x, eol_y, chk_color, save_x, save_y; X REGISTER YX_ELEMENT *cur_yx; X X/* X Initialize the counters and pointers X*/ X X cur_y = 0; X cur_x = 0; X cur_yx = curscr->buf; X eol_y = UNDETERMINED; X eol_x = COLS; X chk_color = *c_color; X save_y = *c_y_cur; X save_x = *c_x_cur; X save_color = *c_color; X for (i = curscr->buf_len - 1; i >= 0; i--) X { X if (!cur_yx->ch) X cur_yx->ch = ' '; X cur_yx++; X } X cur_yx = curscr->buf; X for (i = curscr->buf_len - 1; i >= 0; i--) X { X weol_x = 0; X X/* X Check and set physical screen position X*/ X X if ((cur_y != *c_y_cur) || (cur_x != *c_x_cur)) X _goto(cur_y, cur_x); X X/* X Check and set physical screen colors and attributes X*/ X X#ifdef DOS X if (cur_yx->attrib != *c_attrib) X _setattrib(cur_yx->attrib, cur_yx->color); X if (chk_color && cur_yx->color && (cur_yx->color != *c_color)) X _setcolor(cur_yx->color); X#else X if (chk_color && cur_yx->color && (cur_yx->color != *c_color)) X _setcolor(cur_yx->color); X if (cur_yx->attrib != *c_attrib) X _setattrib(cur_yx->attrib, cur_yx->color); X#endif X X/* X This next part is a little tricky. Eol_y contains the current line that X eol_x is calculated for. If its not the current line, eol_x must be X recalculated. Eol_x is the first column on a line that contains blanks of X the same color up to the end of the line. This is the column where CE may X be used. I calculate eol_x once each line instead of looking forward X after each character for all blanks as comparing 2 column numbers is much X faster that comparing several columns of data. Also note that the X window being refreshed must be full to the end of the physical screen X else CE does not apply. X*/ X if (cur_y != eol_y) X { X REGISTER YX_ELEMENT *syxp; X X eol_y = cur_y; X eol_x = COLS; X syxp = cur_yx + (eol_x - cur_x - 1); X color = syxp->color; X while ((eol_x > cur_x) && (eol_x > weol_x)) X { X if ((syxp->ch == ' ') && (!syxp->attrib) && X (!have_color || (syxp->color == color))) X { X eol_x--; X syxp--; X } X else X break; X } X } X X/* X Test and output CE, update pointers if CE sent X*/ X X if ((cur_yx->ch == ' ') && (cur_x >= eol_x)) X { X _puts(_ce); X temp = COLS - cur_x; X i -= temp - 1; X cur_x += temp - 1; X cur_yx += temp - 1; X } X else X X/* X Output character unless bottom right corner as this may cause screen X to scroll up a line X*/ X X { X if ((cur_y != (LINES - 1)) || (cur_x != (COLS - 1))) X { X *pout++ = cur_yx->ch; /* save putchar */ X if (++outbuf_count >= OUTBUF_SIZE) /* call overhead */ X _flush_outbuf(); X (*c_x_cur)++; X } X } X X/* X Current character position complete, update pointers to next position X*/ X X cur_yx++; X cur_x++; X X/* X Test and set new line in window X*/ X X if (cur_x >= COLS) X { X cur_y++; X cur_x = 0; X } X } X X/* X Window refreshed, reset all flags X Set physical cursor position and color X*/ X X if ((*c_y_cur != save_y) || (*c_x_cur != save_x)) X _goto(save_y, save_x); X if (have_color && color && (save_color != color)) X _setcolor(save_color); X X/* X Flush and remaining buffer data X*/ X X _flush_outbuf(); X return(TRUE); X} X X#endif /* ifndef MMAPPED */ X int wrefresh(win) /* refresh window */ X WINDOW *win; X{ X X/* X This is the most critical routine in the package in determining speed. X Function calls, multiplication, division, array subscripting and X multiple indirection have been minimized for maximum speed. Instead, X inline code (even if bulkier), addition, subtraction and direct register X pointers are used as much as possible. X X It is responsible for taking a logical window and transferring it to the X physical device. It only updates portions that are different from a window X that reflects the physical screen (curscr). This cuts downs on the number X of output characters and thus increases the speed. X X It takes into account if a window is partially hidden by an overlaying X window or windows. X X Currently uses only CM and CE, needs to be improved to include DC, DL, IC X and so on. X*/ X X int i, temp, cur_x, cur_y, win_x, win_y; X int weol_x, win_y_min, win_y_max, in_range; X int outside, win_x_max, win_x_org; X REGISTER YX_ELEMENT *win_yx; X WINDOW *next; X#ifndef MMAPPED X int eol_y, eol_x, last_x, chk_color, tst_clrtoeol, color; X REGISTER YX_ELEMENT *cur_yx; X#endif X X#ifndef MMAPPED X if (win == curscr) X return(do_cur()); X#endif X if (!(win->flags & NO_CHANGE)) X { X X/* X Initialize the counters and pointers X*/ X if (win->ch_first > win->ch_last) X { X pos_cursor(win); X return(FALSE); X } X win_x_max = win->x_max; X win_x_org = win->x_org; X win_y = (win->ch_first - win->buf) / win_x_max; X win_x = (win->ch_first - win->buf) % win_x_max; X cur_y = win_y + win->y_org; X cur_x = win_x + win_x_org; X win_yx = win->ch_first; X win_y_min = LINES; X win_y_max = 0; X#ifndef MMAPPED X cur_yx = &curscr->buf[(cur_y * c_x_max) + cur_x]; X eol_y = UNDETERMINED; X eol_x = win_x_max; X last_x = c_x_max; X chk_color = (win->flags & SET_COLOR); X tst_clrtoeol = (win->flags & TSTCLRTOEOL); X#endif X X/* X Find the min and max y positions of any windows "on top" of this one X This simplifys the checking in the main refresh loop when we are out X of the possible "on top" range. X*/ X X for (next = win->next; next; next = next->next) X { X if ((temp = next->y_org) < win_y_min) X win_y_min = temp; X if ((temp += (next->y_max - 1)) > win_y_max) X win_y_max = temp; X } X next = win->next; X for (i = win->ch_last - win->ch_first; i >= 0; i--) X { X X/* X See if character in window is different from physical screen X If not, skip this character. X If memory mapped output all. X*/ X X#ifndef MMAPPED X X if ((win_yx->ch != cur_yx->ch) || X (win_yx->attrib != cur_yx->attrib) || X (chk_color && X ((win_yx->color && (win_yx->color != cur_yx->color)) || X (!win_yx->color && cur_yx->color && (cur_yx->color != *c_color))))) X X#endif X X { X weol_x = 0; X X/* X See if character position is visable, ie not covered by overlaying window X*/ X X outside = TRUE; X if ((cur_y >= win_y_min) && (cur_y <= win_y_max)) X { X REGISTER WINDOW *wptr; X X outside = FALSE; X for (wptr = next; wptr; ) X { X if ((temp = (wptr->x_org + wptr->x_max)) > weol_x) X weol_x = temp; X if ((cur_y < wptr->y_org) || X (cur_y >= (wptr->y_org + wptr->y_max)) || X (cur_x < wptr->x_org) || X (cur_x >= temp)) X wptr = wptr->next; X else X break; X } X in_range = (wptr ? FALSE : TRUE); X } X if (outside || in_range) X { X X#ifdef MMAPPED X X/* X Output character irregardless of what screen currently has X Memory mapping is faster than doing all the checking X*/ X X put_mmscr(cur_y, cur_x, win_yx); X curscr->color = win_yx->color; X curscr->attrib = win_yx->attrib; X#else X X/* X Check and set physical screen position X*/ X X if ((cur_y != *c_y_cur) || (cur_x != *c_x_cur)) X { X/* X Test to see if just need to advance one character ahead, if so output X character to advance and save cursor motion calculations and output. X*/ X X if ((cur_y == *c_y_cur) && X (cur_x == (last_x + 1)) && X ((win_yx - 1)->attrib == *c_attrib) && X (!chk_color || X ((win_yx - 1)->color && ((win_yx - 1)->color == *c_color)))) X { X *pout++ = (win_yx - 1)->ch; X if (++outbuf_count >= OUTBUF_SIZE) X _flush_outbuf(); X (*c_x_cur)++; X } X else X _goto(cur_y, cur_x); X } X X/* X Check and set physical screen colors and attributes X*/ X X#ifdef DOS X if (win_yx->attrib != *c_attrib) X _setattrib(win_yx->attrib, win_yx->color); X if (chk_color && win_yx->color && (win_yx->color != *c_color)) X _setcolor(win_yx->color); X#else X if (chk_color && win_yx->color && (win_yx->color != *c_color)) X _setcolor(win_yx->color); X if (win_yx->attrib != *c_attrib) X _setattrib(win_yx->attrib, win_yx->color); X#endif X X/* X This next part is a little tricky. Eol_y contains the current line that X eol_x is calculated for. If its not the current line, eol_x must be X recalculated. Eol_x is the first column on a line that contains blanks of X the same color up to the end of the line. This is the column where CE may X be used. I calculate eol_x once each line instead of looking forward X after each character for all blanks as comparing 2 column numbers is much X faster that comparing several columns of data. Also note that the X window being refreshed must be full to the end of the physical screen X else CE does not apply. X*/ X if (tst_clrtoeol) X { X if (win_y != eol_y) X { X REGISTER YX_ELEMENT *syxp; X X eol_y = win_y; X eol_x = win_x_max; X syxp = win_yx + (eol_x - win_x - 1); X color = syxp->color; X while ((eol_x > win_x) && X (outside || (eol_x > weol_x))) X { X if ((syxp->ch == ' ') && (!syxp->attrib) && X (!have_color || (syxp->color == color))) X { X eol_x--; X syxp--; X } X else X break; X } X } X } X X/* X Test and output CE, update pointers if CE sent X*/ X X if (tst_clrtoeol && (win_yx->ch == ' ') && (win_x >= eol_x)) X { X _puts(_ce); X temp = win_x_max - win_x; X i -= temp - 1; X win_x += temp - 1; X cur_x += temp - 1; X while (temp-- > 0) X *cur_yx++ = *win_yx++; X win_yx--; X cur_yx--; X } X else X X/* X Output character unless bottom right corner as this may cause screen X to scroll up a line X*/ X X { X if ((cur_y != LAST_y) || (cur_x != LAST_x)) X { X *pout++ = win_yx->ch; /* save putchar */ X if (++outbuf_count >= OUTBUF_SIZE) /* call overhead */ X _flush_outbuf(); X *cur_yx = *win_yx; X (*c_x_cur)++; X last_x = *c_x_cur; X } X } X X#endif /* ifdef MMAPPED */ X X } X } X X/* X Current character position complete, update pointers to next position X*/ X X win_yx++; X win_x++; X#ifndef MMAPPED X cur_yx++; X#endif X cur_x++; X X/* X Test and set new line in window X*/ X X if (win_x >= win_x_max) X { X win_y++; X win_x = 0; X#ifndef MMAPPED X cur_yx += c_x_max - win_x_max; X#endif X cur_y++; X cur_x = win_x_org; X } X } X X/* X Window refreshed, reset all flags and flush output X*/ X X win->ch_first = win->buf + win->buf_len - 1; X win->ch_last = win->buf; X win->flags |= NO_CHANGE; X pos_cursor(win); X } X return(TRUE); X} X X/* X Extensions to curses X*/ X int keypad() /* put terminal in keypad mode */ X{ X if (_ks) X { X _iputs(_ks); X return(TRUE); X } X else X return(FALSE); X} X int keypadend() /* end terminal keypad mode */ X{ X if (_ke) X { X _iputs(_ke); X return(TRUE); X } X else X return(FALSE); X} X int tographic(ch) /* convert to graphic character */ X REGISTER int ch; X{ X if ((ch >= G_H) && (ch <= G_RT)) X { X if (have_graphic) X return(box_tbl[ch - G_H]); X else X return(fake_tbl[ch - G_H]); X } X else X return(' '); X} X int waddgraphic(win, ch) /* add graphic character */ X REGISTER WINDOW *win; X REGISTER int ch; X{ X int gr_set; X X if ((ch >= G_H) && (ch <= G_RT)) X { X if (have_graphic) X { X if ((gr_set = (win->attrib & GRAPHIC)) == 0) X win->attrib |= GRAPHIC; X waddch(win, box_tbl[ch - G_H]); X if (!gr_set) X win->attrib &= ~GRAPHIC; X } X else X { X if ((gr_set = (win->attrib & GRAPHIC)) != 0) X win->attrib &= ~GRAPHIC; X waddch(win, fake_tbl[ch - G_H]); X if (gr_set) X win->attrib |= GRAPHIC; X } X } X else X waddch(win, ' '); X return(TRUE); X} X int fg_bits(color) X REGISTER int color; X{ X if ((color == UNDETERMINED) || (color < BLACK) || (color > COLOR_15)) X return(UNDETERMINED); X else X return(bits_tbl[color].fg); X} X int bg_bits(color) X REGISTER int color; X{ X if ((color == UNDETERMINED) || (color < BLACK) || (color > COLOR_15)) X return(UNDETERMINED); X else X return(bits_tbl[color].bg); X} X int wsetcolor(win, foreground, background) /* set color on a window */ X REGISTER WINDOW *win; X int foreground; X int background; X{ X int temp; X X if (!have_color || (foreground == background)) X return(FALSE); X if ((temp = fg_bits(foreground)) != UNDETERMINED) X win->color = (win->color & ~F_MASK) | temp; X if ((temp = bg_bits(background)) != UNDETERMINED) X win->color = (win->color & ~B_MASK) | temp; X win->flags |= SET_COLOR; X return(TRUE); X} X int get_color(color) X REGISTER char *color; X{ X REGISTER COLOR_ENTRY *tbl_ptr; X X if (color) X { X tbl_ptr = color_table; X while (tbl_ptr->name) X { X if (streq(color, tbl_ptr->name, TRUE)) X return(tbl_ptr->value); X else X tbl_ptr++; X } X } X return(UNDETERMINED); X} X X#ifdef UNIX int tgetchar(id) /* termcap get char spec */ X char *id; X{ X char *temp; X X if (temp = tgetstr(id, &tc_ptr)) X return(*temp); X else X return('\0'); X} X X#ifndef MMAPPED int print_screen(parm_printer, parm_file) X char *parm_printer; X char *parm_file; X{ X int i, j, k; X int p_ch, f_ch, effect, have_effect, f_append; X int p_uniplex, env_printer, f_uniplex; X WINDOW *win; X YX_ELEMENT *ptr; X FILE *p_file; X FILE *f_file; X char sh_cmd[100], file[50], printer[50], ufile[50]; X char *p_buf, *p_ptr, *f_buf, *f_ptr, *e_buf, *e_ptr, *env_ptr; X X win = curscr; X if (!(p_buf = malloc(win->x_max + 5)) || X !(f_buf = malloc(win->x_max + 5)) || X !(e_buf = malloc(win->x_max + 5))) X return(FALSE); X printer[0] = '\0'; X env_printer = FALSE; X p_uniplex = FALSE; X f_uniplex = FALSE; X f_append = FALSE; X if (parm_printer) X strncpy(printer, parm_printer, sizeof(printer) - 1); X else X { X if (env_ptr = getenv("SCR_PRINTER")) X { X env_printer = TRUE; X strncpy(printer, env_ptr, sizeof(printer) - 1); X } X } X printer[sizeof(printer) - 1] = '\0'; X if (printer[0] || env_printer) X { X if (printer[0]) X { X if (printer[0] == '#') X { X p_uniplex = TRUE; X strcpy(printer, &printer[1]); X sprintf(ufile, "/tmp/scr.%d", getuid()); X strcpy(sh_cmd, "cat > "); X strcat(sh_cmd, ufile); X } X else X { X strcpy(sh_cmd, "lp -s -d"); X strcat(sh_cmd, printer); X } X } X else X strcpy(sh_cmd, "lp -s"); X p_file = popen(sh_cmd, "w"); X } X else X p_file = NULL; X file[0] = '\0'; X if (parm_file) X strncpy(file, parm_file, sizeof(file) - 1); X else X { X if (env_ptr = getenv("SCR_FILE")) X strncpy(file, env_ptr, sizeof(file) - 1); X } X file[sizeof(file) - 1] = '\0'; X if (file[0]) X { X f_append = FALSE; X if (file[0] == '+') X { X strcpy(file, &file[1]); X f_append = TRUE; X } X if (file[0] == '#') X { X strcpy(file, &file[1]); X f_uniplex = TRUE; X if (file[0] == '+') X { X strcpy(file, &file[1]); X f_append = TRUE; X } X } X if (f_append) X f_file = fopen(file, "a"); X else X f_file = fopen(file, "w"); X } X else X f_file = NULL; X if (!p_file && !f_file) X return(FALSE); X j = 0; X have_effect = FALSE; X p_ptr = p_buf; X f_ptr = f_buf; X e_ptr = e_buf; X for (i = win->buf_len, ptr = win->buf; i; i--, ptr++) X { X p_ch = ptr->ch; X f_ch = ptr->ch; X if (ptr->attrib && (p_uniplex || f_uniplex)) X have_effect = TRUE; X if (ptr->attrib & GRAPHIC) X { X for (k = 0; k < BOX_SIZE; k++) X { X if (box_tbl[k] == ptr->ch) X { X if (p_uniplex) X p_ch = 'A' + k; X else X p_ch = fake_tbl[k]; X if (f_uniplex) X f_ch = 'A' + k; X else X f_ch = fake_tbl[k]; X break; X } X } X effect = '['; X } X else if (ptr->attrib & BOLD) X effect = 'A'; X else if (ptr->attrib & UNDERLINE) X effect = 'C'; X else if (ptr->attrib & STANDOUT) X { X if (p_ch == ' ') X p_ch = '*'; X if (f_ch == ' ') X f_ch = '*'; X effect = 'Z'; X } X else X effect = ' '; X j++; X *p_ptr++ = p_ch; X *f_ptr++ = f_ch; X *e_ptr++ = effect; X if (j == win->x_max) X { X while (*(p_ptr - 1) == ' ') X { X if (p_uniplex) X { X if (*(e_ptr - 1) == ' ') X e_ptr--; X else X break; X } X p_ptr--; X } X while (*(f_ptr - 1) == ' ') X { X if (f_uniplex && !p_uniplex) X { X if (*(e_ptr - 1) == ' ') X e_ptr--; X else X break; X } X f_ptr--; X } X if (p_uniplex && have_effect) X { X *p_ptr++ = '@'; X *p_ptr++ = '@'; X } X if (f_uniplex && have_effect) X { X *f_ptr++ = '@'; X *f_ptr++ = '@'; X } X *p_ptr++ = '\n'; X *p_ptr = '\0'; X *f_ptr++ = '\n'; X *f_ptr = '\0'; X *e_ptr++ = '\n'; X *e_ptr = '\0'; X if (p_file) X { X fputs(p_buf, p_file); X if (p_uniplex && have_effect) X fputs(e_buf, p_file); X } X if (f_file) X { X fputs(f_buf, f_file); X if (f_uniplex && have_effect) X fputs(e_buf, f_file); X } X j = 0; X have_effect = FALSE; X p_ptr = p_buf; X f_ptr = f_buf; X e_ptr = e_buf; X } X } X free(p_buf); X free(f_buf); X free(e_buf); X if (p_file) X pclose(p_file); X if (f_file) X fclose(f_file); X if (p_uniplex) X { X strcpy(sh_cmd, "/bin/sh -c '/usr/UII/bin/uprint -p "); X strcat(sh_cmd, printer); X strcat(sh_cmd, " "); X strcat(sh_cmd, ufile); X strcat(sh_cmd, " 2>/dev/null | lp -s 2>/dev/null'"); X return(do_command(sh_cmd, FALSE, (int*)0)); X } X return(TRUE); X} X#endif X#endif X END_OF_FILE if test 37438 -ne `wc -c <'lib/scrout1.c'`; then echo shar: \"'lib/scrout1.c'\" unpacked with wrong size! fi # end of 'lib/scrout1.c' fi echo shar: End of archive 8 \(of 9\). cp /dev/null ark8isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 9 archives. rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0