home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume3 / pcmail / part02 / window.c < prev   
Encoding:
C/C++ Source or Header  |  1989-02-03  |  9.7 KB  |  339 lines

  1. /*++
  2. /* NAME
  3. /*      window 3
  4. /* SUMMARY
  5. /*      screen manager
  6. /* PROJECT
  7. /*      pc-mail
  8. /* PACKAGE
  9. /*      mailsh
  10. /* SYNOPSIS
  11. /*      #include "window.h"
  12. /*
  13. /*      int printcl(window,line,s)
  14. /*      int window;
  15. /*      int line;
  16. /*      char *s;
  17. /*
  18. /*      int printat(window,line,s)
  19. /*      int window;
  20. /*      int line;
  21. /*      char *s;
  22. /*
  23. /*      int putw(c)
  24. /*      int c;
  25. /*
  26. /*      int printw(s)
  27. /*      char *s;
  28. /*
  29. /*      void clrtoeol()
  30. /*
  31. /*      void clrtobot()
  32. /*
  33. /*      void clrscreen()
  34. /*
  35. /*      void beep()
  36. /*
  37. /*    int fputchar(c)
  38. /*    int c;
  39. /*
  40. /*      void wininit()          /* extract terminal control from database */
  41. /* DESCRIPTION
  42. /*      The window manipulator is responsable for three screen windows:
  43. /*      the top window for key labels, the middle window for 
  44. /*      information, and the lower window for messages and dialogue.
  45. /*      Use is made of the terminal capability database termcap.
  46. /*
  47. /*    For MS-DOS systems, there is a termcap facility that generates
  48. /*    escape sequences for the ANSI.SYS terminal driver.
  49. /*
  50. /*      Appropriate macros for window selection are given in window.h.
  51. /*      Needless to say, all screen output should proceed through 
  52. /*      functions in this module.
  53. /*
  54. /*      All character output functions return the number of screen lines
  55. /*      used for outputting the text (at least 1).
  56. /*
  57. /*      printat() writes the specified line in the specified window,
  58. /*      starting at the left margin. 
  59. /*
  60. /*      printcl() performs the same functions as printat() and erases to
  61. /*      the end of the line. 
  62. /*
  63. /*      printw() writes a character string to the current cursor location.
  64. /*      putw() does the same for characters. These two functions are
  65. /*      mostly used for output to the top and bottom windows.
  66. /*
  67. /*      cltroeol(), clrtobot() erase the screen from the cursor to the
  68. /*      end of the line and screen respectively. beep() makes some noise.
  69. /*
  70. /*    fputchar() outputs a character to stdout, just as putchar,
  71. /*    but it is not a macro.
  72. /*
  73. /*      wininit() initializes the window manipulator. It reads the
  74. /*    terminal capabilities from the termcap database.
  75. /* FILES
  76. /*      /etc/termcap, $TERMCAP         on V7 or BSD UNIX
  77. /*    /usr/lib/terminfo, $TERMINFO    on System-V UNIX
  78. /* SEE ALSO
  79. /*      window(5)       window manager definitions
  80. /* DIAGNOSTICS
  81. /*      The program is terminated with an error message if no terminal
  82. /*      descriptions could be found, if the terminal lacks some
  83. /*      essential features or if an attempt is made to write outside
  84. /*      a window.
  85. /* BUGS
  86. /*    This module is a big mess. It should be replaced by a PD
  87. /*    curses/termcap library.
  88. /* AUTHOR(S)
  89. /*      W.Z. Venema
  90. /*      Eindhoven University of Technology
  91. /*      Department of Mathematics and Computer Science
  92. /*      Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  93. /* CREATION DATE
  94. /*      Wed Apr  1 21:14:53 GMT+1:00 1987
  95. /* LAST MODIFICATION
  96. /*    Mon Apr  4 23:51:29 MET 1988
  97. /* VERSION/RELEASE
  98. /*    1.3
  99. /*--*/
  100.  
  101. #include <ctype.h>
  102. #include "defs.h"
  103. #include "window.h"
  104.  
  105. #define BUFFERSIZE      1024            /* max. length of termcap entry */
  106.  
  107. hidden char outbuf[BUFSIZ];             /* for stdio */
  108.  
  109. hidden char tcapent[BUFFERSIZE];        /* storage for termcap entry */
  110. hidden char capst[BUFFERSIZE];          /* storage for tgetstr */
  111. hidden char *capptr = capst;            /* pointer to next tgetstr output */
  112.  
  113. extern char *tgetstr();                 /* returns capability string */
  114. extern char *getenv();
  115. extern char *tgoto();                   /* returns cursor addressing code */
  116.  
  117. public char *KU,*KD,*KL,*KR,*PU,*PD;    /* function-key strings */
  118. public char *KS,*KE;                    /* keypad enable/disable */
  119.  
  120. hidden char *CL,*CD,*CM,*CE,*SO,*SE;    /* screen capabilities */
  121. public int CO,LI;                       /* screen size */
  122.  
  123. public int wbase[BOT+1];                /* where windows start */
  124. public int wsize[BOT+1];                /* how big windows are */
  125.  
  126. hidden int curwin = 0;                  /* what window we are in */
  127. hidden int curx = 0;                    /* where we are on the screen */
  128. hidden int cury = 0;                    /* line in that window */
  129.  
  130. hidden void winout();
  131.  
  132. /* printcl - print one line in a window, then clear to end of line */
  133.  
  134. public int printcl(window,line,s)
  135. int window;
  136. int line;
  137. char *s;
  138. {
  139.     if (line < 0 || line >= wsize[window])
  140.     fatal("line %d not in window %d",line,window);
  141.  
  142.     tputs(tgoto(CM,curx = 0,(cury = line)+wbase[curwin = window]),1,fputchar);
  143.     winout(s);
  144.     if (cury < wsize[curwin])
  145.     tputs(CE,1,fputchar);
  146.     fflush(stdout);
  147.     return(cury-line+1);
  148. }
  149.  
  150. /* printat - print one line in a window */
  151.  
  152. public int printat(window,line,s)
  153. int window;
  154. int line;
  155. char *s;
  156. {
  157.     if (line < 0 || line >= wsize[window])
  158.     fatal("line %d not in window %d",line,window);
  159.  
  160.     tputs(tgoto(CM,curx = 0,(cury = line)+wbase[curwin = window]),1,fputchar);
  161.     winout(s);
  162.     fflush(stdout);
  163.     return(cury-line+1);
  164. }
  165.  
  166. /* putw - put character at current location */
  167.  
  168. public int putw(c)
  169. int c;
  170. {
  171.     register int line = cury;
  172.     char buf[2];
  173.  
  174.     buf[0] = c;
  175.     buf[1] = '\0';
  176.     winout(buf);
  177.     fflush(stdout);
  178.     return(cury-line+1);
  179. }
  180.  
  181. /* printw - formatted print at current location */
  182.  
  183. public int printw(s)
  184. char *s;
  185. {
  186.     register int line = cury;
  187.  
  188.     winout(s);
  189.     fflush(stdout);
  190.     return(cury-line+1);
  191. }
  192.  
  193. /* winout - keep track of the column we are in (clean this up) */
  194.  
  195. /*
  196. * Routine to check that output stays within its window.
  197. * It takes care of terminals that cannot wrap long lines
  198. * or cannot backspace across the beginning of a line.
  199. */
  200.  
  201. hidden void winout(s)   /* implicit inputs/outputs: cury,curx,curwin,wsize */
  202. register char *s;
  203. {
  204.     register int ch;
  205.     int limit;
  206.  
  207.     for (limit = wsize[curwin]; (ch = (*s&0177)) && cury < limit; s++) {
  208.     if (isprint(ch) || ch == ' ') {         /* if printable */
  209.         putchar(ch),curx++;                 /* leave it alone */
  210.     } else if (ch == '\t') {                /* if horizontal tab */
  211.         do {
  212.         winout(" ");                    /* expand it */
  213.         } while (curx&7 && cury < limit);
  214.     } else if (ch == '\b') {                /* backspace */
  215.         if (curx == 0 && cury == 0) {
  216.         /* void */ ;                    /* don't leave the window */
  217.         } else if ((curx = (curx > 0 ? curx-1 : (cury--,CO-1))) != CO-1) {
  218.         putchar(ch);                    /* not at start of line */
  219.         } else {
  220.         tputs(tgoto(CM,curx,cury+wbase[curwin]),1,fputchar);
  221.         }
  222.     } else if (ch == '\n') {        /* if newline */
  223.         tputs(CE,1,fputchar);        /* erase rest of line */
  224.         if ((curx = 0),++cury < limit)      /* advance virtual cursor */
  225.         fputs("\r\n",stdout);           /* advance physical cursor */
  226.     } else if (ch == '\r') {                /* if carriage return */
  227.         putchar(ch),curx = 0;               /* output it and reset curx */
  228.     } else if (ch == '\07') {               /* if the bell */
  229.         putchar(ch);                        /* make them sound */
  230.     } else {                                /* otherwise garbage */
  231.         char buf[3];
  232.         sprintf(buf,"^%c",ch^0100);         /* uncontrollify */
  233.         winout(buf);                        /* output it */
  234.     }
  235.     if (curx >= CO)                         /* at rhs of screen */
  236.         tputs(tgoto(CM,curx = 0,++cury+wbase[curwin]),1,fputchar);
  237.     }
  238. }
  239.  
  240. #ifdef unix
  241.  
  242. /* fputchar - output a character on stdout */
  243.  
  244. public int fputchar(c)
  245. int c;
  246. {
  247.     return(putchar(c));
  248. }
  249.  
  250. #endif /* unix */
  251.  
  252. /* clrtoeol - clear to end of line */
  253.  
  254. public void clrtoeol()
  255. {
  256.     tputs(CE,1,fputchar);
  257. }
  258.  
  259. /* clrtobot - clear to end of screen */
  260.  
  261. public void clrtobot()
  262. {
  263.     tputs(CD,1,fputchar);
  264. }
  265.  
  266. /* clrscreen - clear screen */
  267.  
  268. public void clrscreen()
  269. {
  270.     tputs(CL,1,fputchar);
  271. }
  272.  
  273. /* beep - ring the bell */
  274.  
  275. public void beep()
  276. {
  277.     putw('\07');
  278. }
  279. /* wininit - extract terminal info and initialize window manager */
  280.  
  281. public void wininit()
  282. {
  283.     char *term;
  284.  
  285.     setbuf(stdout,outbuf);                      /* buffer stdout */
  286.  
  287.     term = getenv("TERM");
  288.     switch(tgetent(tcapent,term = getenv("TERM"))) {
  289.     case -1:
  290.     fatal("termcap database not found\n");
  291.     /* NOTREACHED */
  292.     case 0:
  293.     fatal("unknown terminal: %s\n",term);
  294.     /* NOTREACHED */
  295.     }
  296.     /* extract capabilities. should use tables, but what the heck */
  297.  
  298.     if ((CE = tgetstr("ce",&capptr)) == 0       /* clear to end of line */
  299.     || (CD = tgetstr("cd",&capptr)) == 0        /* clear to end of screen */
  300.     || (CL = tgetstr("cl",&capptr)) == 0        /* clear to end of screen */
  301. #ifdef  someday
  302.     || (SO = tgetstr("so",&capptr)) == 0        /* stand-out on */
  303.     || (SE = tgetstr("se",&capptr)) == 0        /* stand-out off */
  304. #endif
  305.     || (CM = tgetstr("cm",&capptr)) == 0        /* cursor movement */
  306.     || (KU = tgetstr("ku",&capptr)) == 0        /* up-arrow */
  307.     || (KD = tgetstr("kd",&capptr)) == 0        /* down_arrow */
  308.     || (KL = tgetstr("kl",&capptr)) == 0        /* left-arrow */
  309.     || (KR = tgetstr("kr",&capptr)) == 0        /* right-arrow */
  310. #ifdef  unix
  311.     || (PU = tgetstr("k1",&capptr)) == 0        /* page-up (F1) */
  312.     || (PD = tgetstr("k2",&capptr)) == 0        /* page down (F2) */
  313. #endif
  314. #ifdef  MSDOS
  315.     || (PU = tgetstr("PU",&capptr)) == 0        /* really PgUp */
  316.     || (PD = tgetstr("PD",&capptr)) == 0        /* really PgDn */
  317. #endif
  318.     || (CO = tgetnum("co")) == 0
  319.     || (LI = tgetnum("li")) == 0)
  320.     fatal("Your terminal is too dumb");
  321.  
  322.     /* the following capabilities are not mandatory */
  323.  
  324.     KS = tgetstr("ks",&capptr);                 /* keypad on */
  325.     KE = tgetstr("ke",&capptr);                 /* keypad off */
  326.  
  327.     /* set window base and size */
  328.  
  329.     if (CO < 80)
  330.     fatal("Terminal screen is to narrow");
  331.     wsize[TOP] = 2;
  332.     wbase[TOP] = 0;
  333.     wsize[BOT] = 5;
  334.     wbase[BOT] = LI-wsize[BOT];
  335.     wbase[MID] = wbase[TOP]+wsize[TOP];
  336.     if ((wsize[MID] = wbase[BOT]-wbase[MID]) < 5)
  337.     fatal("Not enough lines on this terminal");
  338. }
  339.