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