home *** CD-ROM | disk | FTP | other *** search
- /*++
- /* NAME
- /* window 3
- /* SUMMARY
- /* screen manipulator
- /* PROJECT
- /* pc-mail
- /* PACKAGE
- /* mail
- /* SYNOPSIS
- /* #include "window.h"
- /*
- /* int printcl(wp,line,s)
- /* WIN *wp;
- /* int line;
- /* char *s;
- /*
- /* int printat(wp,line,s)
- /* WIN *wp;
- /* int line;
- /* char *s;
- /*
- /* void setwin(wp)
- /* WIN *wp;
- /*
- /* int wputc(c)
- /* int c;
- /*
- /* int wputs(s)
- /* char *s;
- /*
- /* void clrtoeol()
- /*
- /* void clrtobot()
- /*
- /* void clrscreen()
- /*
- /* void beep()
- /*
- /* int fputchar(c)
- /* int c;
- /*
- /* void wininit()
- /* DESCRIPTION
- /* The window manipulator is responsable for three screen windows:
- /* the top window for key labels, the middle window for
- /* information, and the lower window for messages and dialogue.
- /* These can be manipulated via the window handles topwin, midwin
- /* and botwin, respectively.
- /* Use is made of the terminal capability database termcap, or terminfo,
- /* or something else, depending on the OS we are dealing with.
- /*
- /* For MS-DOS systems, there is a termcap facility that generates
- /* escape sequences for the ANSI.SYS terminal driver.
- /*
- /* Appropriate macros for window selection are given in window.h.
- /* Needless to say, all screen output should proceed through
- /* functions in this module.
- /*
- /* All character output functions return the number of screen lines
- /* used for outputting the text (at least 1). All routines that
- /* have a window agrument set the current window.
- /*
- /* printat() writes the specified line in the specified window,
- /* starting at the left margin.
- /*
- /* printcl() performs the same functions as printat() and erases to
- /* the end of the line.
- /*
- /* setwin() sets the current window. The cursor is moved to the
- /* current (row, column) of that window.
- /*
- /* wputs() writes a character string to the current cursor location
- /* in the current window.
- /*
- /* wputc() does the same for characters.
- /*
- /* cltroeol(), clrtobot() erase the screen from the cursor to the
- /* end of the line and screen respectively. beep() makes some noise.
- /*
- /* fputchar() outputs a character to stdout, just as putchar,
- /* but it is not a macro.
- /*
- /* wininit() initializes the window manipulator. It reads the
- /* terminal capabilities from the termcap database.
- /* FILES
- /* /etc/termcap, $TERMCAP on V7 or BSD UNIX
- /* /usr/lib/terminfo, $TERMINFO on System-V UNIX
- /* SEE ALSO
- /* window(5) window manipulator definitions
- /* DIAGNOSTICS
- /* The program is terminated with an error message if no terminal
- /* descriptions could be found, if the terminal lacks some
- /* essential features or if an attempt is made to write outside
- /* a window.
- /* BUGS
- /* All functions that do not take a "window" argument should not be
- /* called before anything has appeared on the screen.
- /*
- /* This module should be replaced by a PD curses/termcap library.
- /* AUTHOR(S)
- /* W.Z. Venema
- /* Eindhoven University of Technology
- /* Department of Mathematics and Computer Science
- /* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
- /* CREATION DATE
- /* Wed Apr 1 21:14:53 GMT+1:00 1987
- /* LAST MODIFICATION
- /* 90/01/22 13:02:55
- /* VERSION/RELEASE
- /* 2.1
- /*--*/
-
- #include <stdio.h>
- #include <ctype.h>
-
- #include "defs.h"
- #include "window.h"
-
- #define BUFFERSIZE 1024 /* max. length of termcap entry */
-
- hidden char outbuf[BUFSIZ]; /* for stdio */
-
- hidden char tcapent[BUFFERSIZE]; /* storage for termcap entry */
- hidden char capst[BUFFERSIZE]; /* storage for tgetstr */
- hidden char *capptr = capst; /* pointer to next tgetstr output */
-
- extern char *tgetstr(); /* returns capability string */
- extern char *getenv();
- extern char *tgoto(); /* returns cursor addressing code */
-
- /* function-key strings, keypad control */
-
- public char *KU, *KD, *KL, *KR, *PU, *PD;
- public char *KS, *KE;
-
- /* screen control capabilities */
-
- hidden char *CL, *CD, *CM, *CE, *SO, *SE;
-
- public int CO, LI; /* screen size */
-
- /* Storage for convenient capability lookup */
-
- struct strcaps {
- char **dest; /* pointer to storage */
- char *name; /* capability name */
- };
-
- struct intcaps {
- int *dest; /* pointer to storage */
- char *name; /* capability name */
- };
-
- /* Required string-valued termcap capabilities */
-
- hidden struct strcaps reqd_str[] = {
- &CE, "ce", /* clear to end of line */
- &CD, "cd", /* clear to end of screen */
- &CL, "cl", /* clear to end of screen */
- #ifdef someday
- &SO, "so", /* stand-out on */
- &SE, "se", /* stand-out off */
- #endif
- &CM, "cm", /* cursor movement */
- &KU, "ku", /* up-arrow */
- &KD, "kd", /* down_arrow */
- &KL, "kl", /* left-arrow */
- &KR, "kr", /* right-arrow */
- #ifdef unix
- &PU, "k1", /* page-up (F1) */
- &PD, "k2", /* page down (F2) */
- #endif
- #ifdef MSDOS
- &PU, "PU", /* really PgUp */
- &PD, "PD", /* really PgDn */
- #endif
- 0, 0,
- };
-
- /* Required integer-valued terminal capabilities */
-
- hidden struct intcaps reqd_int[] = {
- &CO, "co", /* number of columns */
- &LI, "li", /* number of lines */
- 0, 0,
- };
-
- /* Optional string-valued terminal capabilities */
-
- hidden struct strcaps opt_str[] = {
- &KS, "ks", /* keypad on */
- &KE, "ke", /* keypad off */
- 0, 0,
- };
-
- /* Optional integer-valued terminal capabilities */
-
- hidden struct intcaps opt_int[] = {
- 0, 0,
- };
-
- /* Window bases and sizes */
-
- WIN wins[3] = {
- {0, 2, 0, 0}, /* top */
- {2, 0, 0, 0}, /* middle */
- {0, 5, 0, 0}, /* bottom */
- };
-
- /* Stuff related to where we are on the screen */
-
- hidden WIN *currwin = 0; /* what window we are in */
-
- /* convenient macros to update and set cursor location */
-
- #define moveto(wp) tputs(tgoto(CM,wp->x,wp->y+wp->base),1,fputchar)
- #define moveset(wp,c,l) { wp->x = c; wp->y = l; moveto(wp); }
-
- hidden void winout();
-
- /* checkline - validate line number */
-
- hidden WIN *checkline(wp, line)
- WIN *wp;
- int line;
- {
- if (line < 0 || line >= wp->size)
- fatal("line %d not in window %d", line, wp - wins);
- }
-
- /* printcl - print one line in a window, then clear to end of line */
-
- public int printcl(wp, line, s)
- WIN *wp;
- int line;
- char *s;
- {
- checkline(currwin = wp, line);
-
- moveset(wp, 0, line);
- winout(s);
- if (wp->y < wp->size)
- tputs(CE, 1, fputchar);
- (void) fflush(stdout);
- return (wp->y - line + 1);
- }
-
- /* printat - print one line in a window */
-
- public int printat(wp, line, s)
- WIN *wp;
- int line;
- char *s;
- {
- checkline(currwin = wp, line);
-
- moveset(wp, 0, line);
- winout(s);
- (void) fflush(stdout);
- return (wp->y - line + 1);
- }
-
- /* setwin - set focus and cursor */
-
- public void setwin(wp)
- register WIN *wp;
- {
- currwin = wp;
- moveto(wp);
- }
-
- /* wputc - put character at current location in current window */
-
- public int wputc(c)
- int c;
- {
- register int line = currwin->y;
- static char buf[] = "?";
-
- buf[0] = c;
- winout(buf);
- (void) fflush(stdout);
- return (currwin->y - line + 1);
- }
-
- /* wputs - print string at current location in current window */
-
- public int wputs(s)
- char *s;
- {
- register int line = currwin->y;
-
- winout(s);
- (void) fflush(stdout);
- return (currwin->y - line + 1);
- }
-
- /* winout - update current window and keep track of where we are */
-
- hidden void winout(s)
- register char *s;
- {
- register int ch;
- register WIN *wp;
- static char dectrl[] = "^?";
-
- for (wp = currwin; (ch = (*s & 0177)) && wp->y < wp->size; s++) {
- if (isprint(ch) || ch == ' ') { /* if printable */
- putchar(ch), wp->x++; /* leave it alone */
- } else if (ch == '\t') {
- do {
- winout(" "); /* expand it */
- } while ((wp->x & 7) && wp->y < wp->size);
- } else if (ch == '\b') {
- if (wp->x > 0 || wp->y > 0) { /* don\'t leave the window */
- if (wp->x-- == 0) { /* at beginning of line */
- wp->x = CO - 1;
- wp->y--;
- moveto(wp);
- } else {
- putchar(ch);
- }
- }
- } else if (ch == '\n') {
- tputs(CE, 1, fputchar); /* erase rest of line */
- moveset(wp, 0, wp->y + 1); /* advance */
- } else if (ch == '\r') {
- (wp->x = 0), moveto(wp); /* back to left margin */
- } else if (ch == '\07') {
- putchar(ch); /* make them sound */
- } else {
- dectrl[1] = ch ^ 0100; /* uncontrollify */
- winout(dectrl); /* and output */
- }
- if (wp->x >= CO) /* wrap at end of line */
- moveset(wp, 0, wp->y + 1);
- }
- }
-
- #ifdef unix
- /* fputchar - output a character on stdout */
-
- public int fputchar(c)
- int c;
- {
- return (putchar(c));
- }
-
- #endif /* unix */
-
- /* clrtoeol - clear to end of line */
-
- public void clrtoeol()
- {
- tputs(CE, 1, fputchar);
- }
-
- /* clrtobot - clear to end of screen */
-
- public void clrtobot()
- {
- tputs(CD, 1, fputchar);
- }
-
- /* clrscreen - clear screen */
-
- public void clrscreen()
- {
- tputs(CL, 1, fputchar);
- }
-
- /* beep - ring the bell */
-
- public void beep()
- {
- (void) putchar('\07');
- (void) fflush(stdout);
- }
-
- /* wininit - extract terminal info and initialize window routines */
-
- public void wininit()
- {
- char *term;
- struct strcaps *cp;
- struct intcaps *ip;
-
- /* selected buffered standard output */
-
- setbuf(stdout, outbuf);
-
- /* make sure our terminal is known */
-
- #ifdef unix
- if ((term = getenv("TERM")) == 0)
- fatal("TERM not set");
- #endif
-
- switch (tgetent(tcapent, term)) {
- case -1:
- fatal("no terminal database\n");
- /* NOTREACHED */
- case 0:
- fatal("unknown terminal: %s\n", term);
- /* NOTREACHED */
- }
- /* extract required terminal capabilities */
-
- for (cp = reqd_str; cp->name; cp++)
- if ((*cp->dest = tgetstr(cp->name, &capptr)) == 0)
- fatal("Your terminal is too dumb");
- for (ip = reqd_int; ip->name; ip++)
- if ((*ip->dest = tgetnum(ip->name)) == 0)
- fatal("Your terminal is too dumb");
-
- /* set up per-window base and size */
-
- if (CO < 80)
- fatal("Terminal screen is to narrow");
- botwin->base = LI - botwin->size;
- if ((midwin->size = botwin->base - midwin->base) < 10)
- fatal("Not enough lines on this terminal");
-
- /* extract optional terminal capabilities */
-
- for (cp = opt_str; cp->name; cp++)
- *cp->dest = tgetstr(cp->name, &capptr);
- for (ip = opt_int; ip->name; ip++)
- *ip->dest = tgetnum(ip->name);
- }
-