home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mm / ccmd / ccmdio.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-18  |  13.9 KB  |  468 lines

  1. /*
  2.  Copyright (c) 1986, 1990 by The Trustees of Columbia University in
  3.  the City of New York.  Permission is granted to any individual or
  4.  institution to use, copy, or redistribute this software so long as it
  5.  is not sold for profit, provided this copyright notice is retained.
  6.  
  7.  Author: Andrew Lowry
  8. */
  9. /* ccmdio.c
  10. **
  11. ** Routines to perform console i/o with a built-in column counting 
  12. ** mechanism.  The column count is maintained in CSB variable
  13. ** _cmcol, and the routine names all start with "cmx".  Most routines
  14. ** make use of a parallel machine-dependent routine whose name starts
  15. ** with "cm".  In general, output characters must be printable 
  16. ** and must occupy a single printing position each.  If an attempt is
  17. ** made to print past the maximum column position specified in _cmcmx
  18. ** in the CSB, the line is broken automatically.
  19. **/
  20.  
  21. #include "ccmdlib.h"            /* get ccmd package symbols */
  22. #include "cmfncs.h"            /* and internal symbols */
  23.  
  24. static int ignlines;            /* for use with redraw routine */
  25.  
  26. int cmxcpos;                /* global column counter */
  27.  
  28. /* cmxputc - Output single character c */
  29.  
  30. cmxputc(c)
  31. char c;
  32. {
  33. #ifdef undef
  34.   if ((cmcsb._cmflg & CM_TTY) == 0)
  35.     return;                /* do nothing on non-terminal */
  36. #endif
  37.   if (c == NEWLINE) {
  38.     cmxnl(cmcsb._cmoj);            /* handle newlines properly */
  39.     return;
  40.   }
  41.   if (cmcsb._cmcol > cmcsb._cmcmx)
  42.     cmxwrap(cmcsb._cmoj);        /* wrap to new line if needed */
  43.   if (ignlines == 0)            /* if not ignoring this line */
  44.     cmputc(c,cmcsb._cmoj);        /* output the character */
  45.   cmcsb._cmcol++;            /* count it in either case */
  46. }
  47.  
  48. /* cmxputs - Output string of characters pointed to by s */
  49.  
  50. cmxputs(s)
  51. char *s;
  52. {
  53.   int slen,brkpos;            /* length of s, position for break */
  54.   char temp;                /* holds char in break position */
  55.   char buf[BUFSIZ];
  56.   
  57. #ifdef undef
  58.   if ((cmcsb._cmflg & CM_TTY) == 0)
  59.     return;                /* do nothing on non-terminal */
  60. #endif
  61.   slen = strlen(s);            /* find length of string */
  62.   while ((brkpos = (cmcsb._cmcmx+1) - cmcsb._cmcol) < slen) { /* too long */
  63.     strncpy(buf, s, brkpos);
  64.     buf[brkpos] = '\0';
  65.     cmputs(buf,cmcsb._cmoj);        /* output as much as will fit */
  66.     cmxwrap(cmcsb._cmoj);        /* then move to next line */
  67.     s += brkpos;            /* move forward in string */
  68.     slen -= brkpos;            /* count those characters output */
  69.   }
  70.   cmputs(s,cmcsb._cmoj);        /* finally, the last segment */
  71.   cmcsb._cmcol += slen;            /* and update column position */
  72. }
  73.  
  74. cmxerr(s) char *s; {
  75.   int slen,brkpos;            /* length of s, position for break */
  76.   char temp;                /* holds char in break position */
  77.   
  78.   slen = strlen(s);            /* find length of string */
  79.   while ((brkpos = (cmcsb._cmcmx+1) - cmcsb._cmcol) < slen) { /* too long */
  80.     temp = s[brkpos];            /* save char from break position */
  81.     s[brkpos] = NULCHAR;        /* replace with string terminator */
  82.     cmputs(s,cmcsb._cmej);        /* output as much as will fit */
  83.     cmxwrap(cmcsb._cmej);        /* then move to next line */
  84.     s[brkpos] = temp;            /* restore original character */
  85.     s += brkpos;            /* move forward in string */
  86.     slen -= brkpos;            /* count those characters output */
  87.   }
  88.   cmputs(s,cmcsb._cmej);        /* finally, the last segment */
  89.   cmcsb._cmcol += slen;            /* and update column position */
  90. }
  91.  
  92. /* cmxbol - Move to new line if not already at left screen edge */
  93.  
  94. cmxbol()
  95. {
  96. #ifdef undef
  97.   if ((cmcsb._cmflg & CM_TTY) == 0)
  98.     return;                /* do nothing on non-terminal */
  99. #endif
  100.   if (cmcpos() != 0)
  101.     cmnl(cmcsb._cmoj);            /* move if necessary */
  102.   cmcsb._cmcol = 0;            /* fix column counter */
  103. }
  104.  
  105. /* cmxnl - Output a newline sequence, and reset column counter */
  106.  
  107. cmxnl()
  108. {
  109. #ifdef undef
  110.   if ((cmcsb._cmflg & CM_TTY) == 0)
  111.     return;                /* do nothing on non-terminal */
  112. #endif
  113.   if (ignlines == 0)            /* if not ignoring this line */
  114.     cmnl(cmcsb._cmoj);            /* output the newline */
  115.   else
  116.     ignlines--;                /* else drop the count */
  117.   cmcsb._cmcol = 0;            /* and reset counter */
  118. }
  119.  
  120. /* cmxwrap - Wrap from the end of one line to the beginning of the next */
  121.  
  122. cmxwrap()
  123. {
  124. #ifdef undef
  125.   if ((cmcsb._cmflg & CM_TTY) == 0)
  126.     return;                /* do nothing on non-terminal */
  127. #endif
  128.   if (ignlines == 0)            /* if not ignoring this line */
  129.     cmwrap(cmcsb._cmoj);        /* do the wrap */
  130.   else
  131.     ignlines--;                /* else drop the count */
  132.   cmcsb._cmcol = 0;            /* and reset column counter */
  133. }
  134.  
  135.  
  136. /* cmxcls - Clear the screen and reset the column counter */
  137.  
  138. cmxcls()
  139. {
  140.   if ((cmcsb._cmflg2 & CM_CRT) == 0)
  141.     return;                /* do nothing on non-crt */
  142.   if (!cmcls())                /* clear the screen */
  143.     cmnl(cmcsb._cmoj);            /* or at least go to new line */
  144.   cmcsb._cmcol = 0;            /* reset the counter */
  145. }
  146.  
  147.  
  148. /* cmxcll - Clear the current line on the terminal screen */
  149.  
  150. cmxcll()
  151. {
  152.   int col = cmcsb._cmcol;        /* save position before clear */
  153.   if ((cmcsb._cmflg2 & CM_CRT) == 0)
  154.     return;                /* do nothing on non-crt */
  155.   cmcr(cmcsb._cmoj);            /* back to left margin */
  156.   if (!cmceol()) {            /* clear to end of line */
  157.     while (col-- > 0)            /* no luck... do it with spaces */
  158.       cmputc(SPACE,cmcsb._cmoj);
  159.     cmcr(cmcsb._cmoj);            /* back to the beginning */
  160.   }
  161.   cmcsb._cmcol = 0;
  162. }
  163.  
  164. /* cmxera
  165. **
  166. ** Purpose:
  167. **   Erases a portion of the current command line from the screen.
  168. **   The CSB itself is left unchanged.  Erasure takes into effect
  169. **   the translations performed by the echo routine in ccmdut, and
  170. **   characters that were not echoed are not erased.  Optionally,
  171. **   the prompt is redisplayed when the entire command line is
  172. **   erased.  The new screen column position after erasure is
  173. **   returned.
  174. **
  175. ** Input arguments:
  176. **   n - Number of chars to erase from the end of input.
  177. **   doprompt - If TRUE, and if entire buffer erased, prompt is refreshed.
  178. **
  179. ** Returns: New screen column position.
  180. **/
  181.  
  182. int
  183. cmxera(n,doprompt)
  184. int n,doprompt;
  185. {
  186.   int lpos1,cpos1;        /* line and column position before erase */
  187.   int lpos2,cpos2;        /* and after erasure */
  188.   int lpos1x;            /* extra copy of lpos1 */
  189.   int lsize;            /* width of text on a given line */
  190.   int i;
  191.  
  192.   countbuf(0,&lpos1,&cpos1);        /* get current position */
  193.   countbuf(n,&lpos2,&cpos2);        /* and after erasure */
  194.   lpos1x = lpos1;
  195.   if ((cmcsb._cmflg2 & CM_CRT) == 0)
  196.     return(cpos2);            /* do nothing on non-crt */
  197.  
  198.   if ((lpos1 != lpos2) || (cpos2 == 0)) { /* killing at least one full line */
  199.     cmcr(cmcsb._cmoj);            /* get to left screen edge */
  200.     while (lpos1-- > lpos2) {        /* kill abandoned lines */
  201.       if (!cmceol()) {            /* clear out one line  */
  202.     lsize = countline(lpos1+1); /* no luck...see how many chars to clear */
  203.     while (lsize-- > 0)
  204.           cmputc(SPACE,cmcsb._cmoj);    /* and write over them with spaces */
  205.     cmcr(cmcsb._cmoj);        /* then back to beginning of line */
  206.       }
  207.       if (!cmupl()) {            /* then move up to next line */
  208.         cmputc(BS,cmcsb._cmoj);        /* no luck.. try backspace-return */
  209.     cmcr(cmcsb._cmoj);
  210.       }
  211.     }
  212.   }
  213.   if ((lpos1x == lpos2) && (cpos2 != 0)) /* same line, not beginning? */
  214.     for (i = cpos2; i < cpos1; i++)
  215.       cmputc(BS,cmcsb._cmoj);        /* backsapce to new column */
  216.   else  
  217.     redraw(lpos2,cpos2);        /* redraw the final line */
  218.   if (!cmceol()) {            /* kill the rest of it */
  219.     lsize = countline(lpos2)-cpos2;    /* no luck... count excess chars */
  220.     for (i = 0; i < lsize; i++)
  221.       cmputc(SPACE,cmcsb._cmoj);    /* overwrite with spaces */
  222.     for (i = 0; i < lsize; i++)
  223.       cmputc(BS,cmcsb._cmoj);        /* then backspace back into position */
  224.   }      
  225.   if (n == (cmcsb._cminc + (cmcsb._cmptr - cmcsb._cmbfp)))
  226.     if (doprompt) {            /* entire buffer erased and prompt wanted? */
  227.       cmcr(cmcsb._cmoj);        /* yup, back to beginning of line */
  228.       if (!cmceol()) {            /* erase prior prompt */
  229.     lsize = cpos2;            /* no luck... see how many chars to erase */
  230.     while (lsize-- > 0)
  231.           cmputc(SPACE,cmcsb._cmoj);    /* erase with spaces */
  232.     cmcr(cmcsb._cmoj);        /* and back to beginning */
  233.       }
  234.       cmputs(cmcsb._cmrty,cmcsb._cmoj); /* and redisplay the prompt */
  235.     }
  236.   return(cpos2);        /* return new column position */
  237. }
  238.  
  239. /* countbuf
  240. **
  241. ** Purpose:
  242. **   Compute line and column position (relative to beginning of prompt
  243. **   string) that would result from displaying the current command line,
  244. **   truncated by a given number of characters from the end.  Non-echoed
  245. **   characters and special translations provided by the echo routine in
  246. **   module ccmdut are taken into account.
  247. **
  248. ** Input parameters:
  249. **   n - The number of characters to exclude from the end of the input.
  250. **
  251. ** Output parameters:
  252. **   lpos - Number of lines from the one containing the beginning of the
  253. **     prompt string.
  254. **   cpos - Column position (0 = left edge of screen).
  255. **/
  256.  
  257. static
  258. countbuf(n,lpos,cpos)
  259. int n,*lpos,*cpos;
  260. {
  261.   int count;                /* counts characters */
  262.   int *cp,cc;                /* for scanning buffer characters */
  263.   char c;
  264.  
  265.   count = strlen(cmcsb._cmrty);        /* get length of prompt string */
  266.   *lpos = count / (cmcsb._cmcmx);    /* compute prompt end coordinates */
  267.   *cpos = count % (cmcsb._cmcmx);
  268.                     /* get # of buffer chars to count */
  269.   count = cmcsb._cminc + (cmcsb._cmptr - cmcsb._cmbfp) - n;
  270.   cp = cmcsb._cmbfp;            /* point to buffer start */
  271.   while (count-- > 0) {            /* loop through chars */
  272.     c = (cc = *cp++) & CC_CHR;        /* get next char */
  273.     if (cc & CC_NEC)
  274.       continue;                /* non-echoed char... no count */
  275.     else if (c == NEWLINE) {
  276.       (*lpos)++;            /* newline... move to next line */
  277.       *cpos = 0;            /* and reset column counter */
  278.     }
  279.     else if (c == TAB) {        /* TAB character */
  280.       *cpos = 8 + 8*(*cpos / 8);    /* move col to next multiple of 8 */
  281.       if (*cpos >= cmcsb._cmcmx) {    /* wrap if necessary */
  282.     (*lpos)++;            /* to next line */
  283.     *cpos = 0;            /* column zero */
  284.       }
  285.     }
  286.     else {
  287.       if ((c == DELETE) || (c < SPACE)) /* other control char */
  288.         *cpos += 2;            /* count up-arrow and print char */
  289.       else                /* normal printing char */
  290.         (*cpos)++;            /* count it */
  291.       if (*cpos >= cmcsb._cmcmx) {    /* wrap if necessary */
  292.     (*lpos)++;
  293.     *cpos %= cmcsb._cmcmx;
  294.       }
  295.     }
  296.   }
  297. }
  298.  
  299.  
  300.  
  301. /* countline
  302. **
  303. ** Purpose - Determine how wide a given line is on the current
  304. ** display.
  305. **
  306. ** Input arguments:
  307. **   line - Number of line to count, 0 = prompt line
  308. **
  309. ** Output arguments: None
  310. ** Returns: Number of columns occupied by text on the given line.
  311. **/
  312.  
  313. static int
  314. countline(line)
  315. int line;
  316. {
  317.   int count;                /* counts characters */
  318.   int lpos,cpos;                /* keep track of position */
  319.   int *cp,cc;                /* for scanning buffer characters */
  320.   char c;
  321.  
  322.   count = strlen(cmcsb._cmrty);        /* get length of prompt string */
  323.   lpos = count / cmcsb._cmcmx;        /* compute prompt end coordinates */
  324.   cpos = count % (cmcsb._cmcmx+1);
  325.   if (line < lpos)            /* part of prompt */
  326.     return(cmcsb._cmcmx+1);        /* indicate whole line */
  327.  
  328.                     /* get # of buffer chars to count */
  329.   count = cmcsb._cminc + (cmcsb._cmptr - cmcsb._cmbfp);
  330.   cp = cmcsb._cmbfp;            /* point to buffer start */
  331.   while (count-- > 0) {            /* loop through chars */
  332.     c = (cc = *cp++) & CC_CHR;        /* get next char */
  333.     if (cc & CC_NEC)
  334.       continue;                /* non-echoed char... no count */
  335.     else if (c == NEWLINE) {
  336.       if (lpos == line)            /* newline - finished given line? */
  337.         return(cpos);            /* yup, return its width */
  338.       lpos++;                /* no, move to next line */
  339.       cpos = 0;                /* and reset column counter */
  340.     }
  341.     else if (c == TAB) {        /* TAB character */
  342.       cpos = 8 + 8*((cpos) / 8);    /* move col to next multiple of 8 */
  343.       if (cpos > cmcsb._cmcmx) {    /* wrap if necessary */
  344.     if (lpos == line)        /* finished given line? */
  345.       return(cmcsb._cmcmx + 1);    /* yup, it used all its columns */
  346.     lpos++;                /* no, move to next line */
  347.     cpos = 0;            /* column zero */
  348.       }
  349.     }
  350.     else {
  351.       if ((c == DELETE) || (c < SPACE)) /* other control char */
  352.         cpos += 2;            /* count up-arrow and print char */
  353.       else                /* normal printing char */
  354.         cpos++;                /* count it */
  355.       if (cpos > cmcsb._cmcmx) {    /* wrap if necessary */
  356.     if (lpos == line)        /* finished given line? */
  357.       return(cmcsb._cmcmx+1);    /* yup, it used entire width */
  358.     lpos++;                /* no, move to next line */
  359.     cpos %= cmcsb._cmcmx+1;
  360.       }
  361.     }
  362.   }
  363.   return(cpos);                /* given line was last line */
  364. }
  365.  
  366.  
  367.  
  368. /* redraw
  369. **
  370. ** Purpose:
  371. **   Redisplay a given line from the command display, up to but
  372. **   not including a given column position.  Will never be called
  373. **   with a column number such that redisplay must be turned off
  374. **   in the middle of a multi-character translation by cmechx.
  375. **
  376. ** Input arguments:
  377. **   line - Line number to be redisplayed
  378. **   col - Column position to end redisplay
  379. **
  380. ** Output arguments: None.
  381. ** Returns: Nothing.
  382. **/
  383.  
  384. static
  385. redraw(line,col)
  386. int line,col;
  387. {
  388.   char *pmt;                /* prompt string */
  389.   int *cp;                /* pointer to command buffer */
  390.  
  391.   if (col == 0)
  392.     return;                /* no replay required on line */
  393.   ignlines = line;            /* set number of lines to ignore */
  394.   cmcsb._cmcol = 0;            /* reset column counter */
  395.   pmt = cmcsb._cmrty;            /* point to prompt string */
  396.   while (*pmt != NULCHAR)
  397.     cmxputc(*pmt++);            /* output the prompt */
  398.   
  399.   cp = cmcsb._cmbfp;            /* point to beginning of buffer */
  400.   while ((ignlines > 0) || (cmcsb._cmcol < col)) 
  401.     if ((*cp & CC_NEC) == 0)        /* loop through buffer */
  402.       cmechx((char) (*cp++) & CC_CHR);    /* echo chars that were originally */
  403.     else
  404.       cp++;                /* skipping those that were not */
  405.   return;                /* all done */
  406. }
  407.  
  408. /*
  409.  * cmxflsh()
  410.  * flush output on csb output stream
  411.  */
  412. cmxflsh() {
  413.   cmflsh(cmcsb._cmoj);
  414. }
  415.  
  416. /*
  417.  * do a printf to our output file
  418.  */
  419.  
  420.  
  421. cmxprintf(va_alist) va_dcl {
  422.   char *fmt;
  423.   va_list arg_ptr;
  424.   int ret;
  425.  
  426.   if (cmcsb._cmoj == NULL)
  427.       return(0);
  428.   va_start(arg_ptr);
  429.   fmt = va_arg(arg_ptr, char *);
  430.   ret = vfprintf(cmcsb._cmoj,fmt,arg_ptr);
  431.   va_end(arg_ptr);
  432.   return ret;
  433. }
  434.  
  435. /*
  436.  * do a printf to our error file
  437.  */
  438.  
  439. cmxeprintf(va_alist) va_dcl {
  440.   char *fmt;
  441.   va_list arg_ptr;
  442.   int ret;
  443.  
  444.   if (cmcsb._cmej == NULL)
  445.       return(0);
  446.   va_start(arg_ptr);
  447.   fmt = va_arg(arg_ptr, char *);
  448.   ret = vfprintf(cmcsb._cmej,fmt,arg_ptr);
  449.   va_end(arg_ptr);
  450.   return ret;
  451. }
  452.  
  453. #ifdef BSD
  454. extern int _doprnt();
  455.  
  456. int
  457. vfprintf(iop, format, ap)
  458. FILE *iop;
  459. char *format;
  460. va_list ap;
  461. {
  462.     int count;
  463.  
  464.     count = _doprnt(format, ap, iop);
  465.     return(ferror(iop)? EOF: count);
  466. }
  467. #endif /* BSD */
  468.