home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / communic / pcmail / main / window.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-05  |  10.5 KB  |  432 lines

  1. /*++
  2. /* NAME
  3. /*      window 3
  4. /* SUMMARY
  5. /*      screen manipulator
  6. /* PROJECT
  7. /*      pc-mail
  8. /* PACKAGE
  9. /*      mail
  10. /* SYNOPSIS
  11. /*      #include "window.h"
  12. /*
  13. /*      int printcl(wp,line,s)
  14. /*      WIN *wp;
  15. /*      int line;
  16. /*      char *s;
  17. /*
  18. /*      int printat(wp,line,s)
  19. /*      WIN *wp;
  20. /*      int line;
  21. /*      char *s;
  22. /*
  23. /*    void setwin(wp)
  24. /*    WIN *wp;
  25. /*
  26. /*      int wputc(c)
  27. /*      int c;
  28. /*
  29. /*      int wputs(s)
  30. /*      char *s;
  31. /*
  32. /*      void clrtoeol()
  33. /*
  34. /*      void clrtobot()
  35. /*
  36. /*      void clrscreen()
  37. /*
  38. /*      void beep()
  39. /*
  40. /*    int fputchar(c)
  41. /*    int c;
  42. /*
  43. /*    void wininit()
  44. /* DESCRIPTION
  45. /*      The window manipulator is responsable for three screen windows:
  46. /*      the top window for key labels, the middle window for
  47. /*      information, and the lower window for messages and dialogue.
  48. /*    These can be manipulated via the window handles topwin, midwin
  49. /*    and botwin, respectively.
  50. /*      Use is made of the terminal capability database termcap, or terminfo,
  51. /*    or something else, depending on the OS we are dealing with.
  52. /*
  53. /*    For MS-DOS systems, there is a termcap facility that generates
  54. /*    escape sequences for the ANSI.SYS terminal driver.
  55. /*
  56. /*      Appropriate macros for window selection are given in window.h.
  57. /*      Needless to say, all screen output should proceed through
  58. /*      functions in this module.
  59. /*
  60. /*      All character output functions return the number of screen lines
  61. /*      used for outputting the text (at least 1). All routines that
  62. /*    have a window agrument set the current window.
  63. /*
  64. /*      printat() writes the specified line in the specified window,
  65. /*      starting at the left margin.
  66. /*
  67. /*      printcl() performs the same functions as printat() and erases to
  68. /*      the end of the line.
  69. /*
  70. /*    setwin() sets the current window. The cursor is moved to the
  71. /*    current (row, column) of that window.
  72. /*
  73. /*      wputs() writes a character string to the current cursor location
  74. /*    in the current window.
  75. /*
  76. /*      wputc() does the same for characters. 
  77. /*
  78. /*      cltroeol(), clrtobot() erase the screen from the cursor to the
  79. /*      end of the line and screen respectively. beep() makes some noise.
  80. /*
  81. /*    fputchar() outputs a character to stdout, just as putchar,
  82. /*    but it is not a macro.
  83. /*
  84. /*      wininit() initializes the window manipulator. It reads the
  85. /*    terminal capabilities from the termcap database.
  86. /* FILES
  87. /*      /etc/termcap, $TERMCAP         on V7 or BSD UNIX
  88. /*    /usr/lib/terminfo, $TERMINFO    on System-V UNIX
  89. /* SEE ALSO
  90. /*      window(5)       window manipulator definitions
  91. /* DIAGNOSTICS
  92. /*      The program is terminated with an error message if no terminal
  93. /*      descriptions could be found, if the terminal lacks some
  94. /*      essential features or if an attempt is made to write outside
  95. /*      a window.
  96. /* BUGS
  97. /*    All functions that do not take a "window" argument should not be
  98. /*    called before anything has appeared on the screen.
  99. /*
  100. /*    This module should be replaced by a PD curses/termcap library.
  101. /* AUTHOR(S)
  102. /*      W.Z. Venema
  103. /*      Eindhoven University of Technology
  104. /*      Department of Mathematics and Computer Science
  105. /*      Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  106. /* CREATION DATE
  107. /*      Wed Apr  1 21:14:53 GMT+1:00 1987
  108. /* LAST MODIFICATION
  109. /*    90/01/22 13:02:55
  110. /* VERSION/RELEASE
  111. /*    2.1
  112. /*--*/
  113.  
  114. #include <stdio.h>
  115. #include <ctype.h>
  116.  
  117. #include "defs.h"
  118. #include "window.h"
  119.  
  120. #define BUFFERSIZE      1024        /* max. length of termcap entry */
  121.  
  122. hidden char outbuf[BUFSIZ];        /* for stdio */
  123.  
  124. hidden char tcapent[BUFFERSIZE];    /* storage for termcap entry */
  125. hidden char capst[BUFFERSIZE];        /* storage for tgetstr */
  126. hidden char *capptr = capst;        /* pointer to next tgetstr output */
  127.  
  128. extern char *tgetstr();            /* returns capability string */
  129. extern char *getenv();
  130. extern char *tgoto();            /* returns cursor addressing code */
  131.  
  132. /* function-key strings, keypad control */
  133.  
  134. public char *KU, *KD, *KL, *KR, *PU, *PD;
  135. public char *KS, *KE;
  136.  
  137. /* screen control capabilities */
  138.  
  139. hidden char *CL, *CD, *CM, *CE, *SO, *SE;
  140.  
  141. public int CO, LI;            /* screen size */
  142.  
  143. /* Storage for convenient capability lookup */
  144.  
  145. struct strcaps {
  146.     char  **dest;            /* pointer to storage */
  147.     char   *name;            /* capability name */
  148. };
  149.  
  150. struct intcaps {
  151.     int    *dest;            /* pointer to storage */
  152.     char   *name;            /* capability name */
  153. };
  154.  
  155. /* Required string-valued termcap capabilities */
  156.  
  157. hidden struct strcaps reqd_str[] = {
  158.     &CE, "ce",                /* clear to end of line */
  159.     &CD, "cd",                /* clear to end of screen */
  160.     &CL, "cl",                /* clear to end of screen */
  161. #ifdef  someday
  162.     &SO, "so",                /* stand-out on */
  163.     &SE, "se",                /* stand-out off */
  164. #endif
  165.     &CM, "cm",                /* cursor movement */
  166.     &KU, "ku",                /* up-arrow */
  167.     &KD, "kd",                /* down_arrow */
  168.     &KL, "kl",                /* left-arrow */
  169.     &KR, "kr",                /* right-arrow */
  170. #ifdef  unix
  171.     &PU, "k1",                /* page-up (F1) */
  172.     &PD, "k2",                /* page down (F2) */
  173. #endif
  174. #ifdef MSDOS
  175.     &PU, "PU",                /* really PgUp */
  176.     &PD, "PD",                /* really PgDn */
  177. #endif
  178.     0, 0,
  179. };
  180.  
  181. /* Required integer-valued terminal capabilities */
  182.  
  183. hidden struct intcaps reqd_int[] = {
  184.     &CO, "co",                /* number of columns */
  185.     &LI, "li",                /* number of lines */
  186.     0, 0,
  187. };
  188.  
  189. /* Optional string-valued terminal capabilities */
  190.  
  191. hidden struct strcaps opt_str[] = {
  192.     &KS, "ks",                /* keypad on */
  193.     &KE, "ke",                /* keypad off */
  194.     0, 0,
  195. };
  196.  
  197. /* Optional integer-valued terminal capabilities */
  198.  
  199. hidden struct intcaps opt_int[] = {
  200.     0, 0,
  201. };
  202.  
  203. /* Window bases and sizes */
  204.  
  205. WIN     wins[3] = {
  206.     {0, 2, 0, 0},            /* top */
  207.     {2, 0, 0, 0},            /* middle */
  208.     {0, 5, 0, 0},            /* bottom */
  209. };
  210.  
  211. /* Stuff related to where we are on the screen */
  212.  
  213. hidden WIN *currwin = 0;        /* what window we are in */
  214.  
  215. /* convenient macros to update and set cursor location */
  216.  
  217. #define    moveto(wp)    tputs(tgoto(CM,wp->x,wp->y+wp->base),1,fputchar)
  218. #define    moveset(wp,c,l)    { wp->x = c; wp->y = l; moveto(wp); }
  219.  
  220. hidden void winout();
  221.  
  222. /* checkline - validate line number */
  223.  
  224. hidden WIN *checkline(wp, line)
  225. WIN    *wp;
  226. int     line;
  227. {
  228.     if (line < 0 || line >= wp->size)
  229.     fatal("line %d not in window %d", line, wp - wins);
  230. }
  231.  
  232. /* printcl - print one line in a window, then clear to end of line */
  233.  
  234. public int printcl(wp, line, s)
  235. WIN    *wp;
  236. int     line;
  237. char   *s;
  238. {
  239.     checkline(currwin = wp, line);
  240.  
  241.     moveset(wp, 0, line);
  242.     winout(s);
  243.     if (wp->y < wp->size)
  244.     tputs(CE, 1, fputchar);
  245.     (void) fflush(stdout);
  246.     return (wp->y - line + 1);
  247. }
  248.  
  249. /* printat - print one line in a window */
  250.  
  251. public int printat(wp, line, s)
  252. WIN    *wp;
  253. int     line;
  254. char   *s;
  255. {
  256.     checkline(currwin = wp, line);
  257.  
  258.     moveset(wp, 0, line);
  259.     winout(s);
  260.     (void) fflush(stdout);
  261.     return (wp->y - line + 1);
  262. }
  263.  
  264. /* setwin - set focus and cursor */
  265.  
  266. public void setwin(wp)
  267. register WIN *wp;
  268. {
  269.     currwin = wp;
  270.     moveto(wp);
  271. }
  272.  
  273. /* wputc - put character at current location in current window */
  274.  
  275. public int wputc(c)
  276. int     c;
  277. {
  278.     register int line = currwin->y;
  279.     static char buf[] = "?";
  280.  
  281.     buf[0] = c;
  282.     winout(buf);
  283.     (void) fflush(stdout);
  284.     return (currwin->y - line + 1);
  285. }
  286.  
  287. /* wputs - print string at current location in current window */
  288.  
  289. public int wputs(s)
  290. char   *s;
  291. {
  292.     register int line = currwin->y;
  293.  
  294.     winout(s);
  295.     (void) fflush(stdout);
  296.     return (currwin->y - line + 1);
  297. }
  298.  
  299. /* winout - update current window and keep track of where we are */
  300.  
  301. hidden void winout(s)
  302. register char *s;
  303. {
  304.     register int ch;
  305.     register WIN *wp;
  306.     static char dectrl[] = "^?";
  307.  
  308.     for (wp = currwin; (ch = (*s & 0177)) && wp->y < wp->size; s++) {
  309.     if (isprint(ch) || ch == ' ') {        /* if printable */
  310.         putchar(ch), wp->x++;        /* leave it alone */
  311.     } else if (ch == '\t') {
  312.         do {
  313.         winout(" ");            /* expand it */
  314.         } while ((wp->x & 7) && wp->y < wp->size);
  315.     } else if (ch == '\b') {
  316.         if (wp->x > 0 || wp->y > 0) {    /* don\'t leave the window */
  317.         if (wp->x-- == 0) {        /* at beginning of line */
  318.             wp->x = CO - 1;
  319.             wp->y--;
  320.             moveto(wp);
  321.         } else {
  322.             putchar(ch);
  323.         }
  324.         }
  325.     } else if (ch == '\n') {
  326.         tputs(CE, 1, fputchar);        /* erase rest of line */
  327.         moveset(wp, 0, wp->y + 1);        /* advance */
  328.     } else if (ch == '\r') {
  329.         (wp->x = 0), moveto(wp);        /* back to left margin */
  330.     } else if (ch == '\07') {
  331.         putchar(ch);            /* make them sound */
  332.     } else {
  333.         dectrl[1] = ch ^ 0100;        /* uncontrollify */
  334.         winout(dectrl);            /* and output */
  335.     }
  336.     if (wp->x >= CO)            /* wrap at end of line */
  337.         moveset(wp, 0, wp->y + 1);
  338.     }
  339. }
  340.  
  341. #ifdef unix
  342. /* fputchar - output a character on stdout */
  343.  
  344. public int fputchar(c)
  345. int     c;
  346. {
  347.     return (putchar(c));
  348. }
  349.  
  350. #endif                    /* unix */
  351.  
  352. /* clrtoeol - clear to end of line */
  353.  
  354. public void clrtoeol()
  355. {
  356.     tputs(CE, 1, fputchar);
  357. }
  358.  
  359. /* clrtobot - clear to end of screen */
  360.  
  361. public void clrtobot()
  362. {
  363.     tputs(CD, 1, fputchar);
  364. }
  365.  
  366. /* clrscreen - clear screen */
  367.  
  368. public void clrscreen()
  369. {
  370.     tputs(CL, 1, fputchar);
  371. }
  372.  
  373. /* beep - ring the bell */
  374.  
  375. public void beep()
  376. {
  377.     (void) putchar('\07');
  378.     (void) fflush(stdout);
  379. }
  380.  
  381. /* wininit - extract terminal info and initialize window routines */
  382.  
  383. public void wininit()
  384. {
  385.     char   *term;
  386.     struct strcaps *cp;
  387.     struct intcaps *ip;
  388.  
  389.     /* selected buffered standard output */
  390.  
  391.     setbuf(stdout, outbuf);
  392.  
  393.     /* make sure our terminal is known */
  394.  
  395. #ifdef unix
  396.     if ((term = getenv("TERM")) == 0)
  397.     fatal("TERM not set");
  398. #endif
  399.  
  400.     switch (tgetent(tcapent, term)) {
  401.     case -1:
  402.     fatal("no terminal database\n");
  403.     /* NOTREACHED */
  404.     case 0:
  405.     fatal("unknown terminal: %s\n", term);
  406.     /* NOTREACHED */
  407.     }
  408.     /* extract required terminal capabilities */
  409.  
  410.     for (cp = reqd_str; cp->name; cp++)
  411.     if ((*cp->dest = tgetstr(cp->name, &capptr)) == 0)
  412.         fatal("Your terminal is too dumb");
  413.     for (ip = reqd_int; ip->name; ip++)
  414.     if ((*ip->dest = tgetnum(ip->name)) == 0)
  415.         fatal("Your terminal is too dumb");
  416.  
  417.     /* set up per-window base and size */
  418.  
  419.     if (CO < 80)
  420.     fatal("Terminal screen is to narrow");
  421.     botwin->base = LI - botwin->size;
  422.     if ((midwin->size = botwin->base - midwin->base) < 10)
  423.     fatal("Not enough lines on this terminal");
  424.  
  425.     /* extract optional terminal capabilities */
  426.  
  427.     for (cp = opt_str; cp->name; cp++)
  428.     *cp->dest = tgetstr(cp->name, &capptr);
  429.     for (ip = opt_int; ip->name; ip++)
  430.     *ip->dest = tgetnum(ip->name);
  431. }
  432.