home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c005 / 5.ddi / C / WNWRAP.C < prev    next >
Encoding:
Text File  |  1986-08-05  |  8.0 KB  |  242 lines

  1. /**
  2. *
  3. * Name        wnwrap -- Write a string of characters to the current
  4. *              window, TTY-style, with word wrap.
  5. *
  6. * Synopsis    wnwrap(num_spaces,buffer,fore,back,option);
  7. *
  8. *        int  num_spaces Number of characters to write.
  9. *                If CHARS_ONLY is specified (see "option"
  10. *                below), num_spaces == 0 indicates that
  11. *                the buffer is terminated by a NUL ('\0')
  12. *                character.
  13. *        char *buffer    Data to write
  14. *        int  fore    -1 if window's native foreground
  15. *                attribute is to be used; if CHARS_ONLY
  16. *                is specified, a value between 0 and 15
  17. *                specifies a new foreground attribute.
  18. *        int  back    -1 if window's native background
  19. *                attribute is to be used; if CHARS_ONLY
  20. *                is specified, a value between 0 and 15
  21. *                specifies a new background attribute.
  22. *        int  option    One bit in the option value tells WNWRAP
  23. *                how the buffer is constructed.    The two
  24. *                possible values are:
  25. *
  26. *              Value        Meaning
  27. *              -----------   ------------------------------------
  28. *              CHARS_ONLY    Buffer contains characters only.
  29. *                    If num_spaces is zero, the string
  30. *                    is terminated by a NUL ('\0')
  31. *                    character.
  32. *                    The values of fore and back are used
  33. *                    as attributes.
  34. *              CHAR_ATTR     Buffer contains (char,attr) pairs.
  35. *                    The values of fore and back are
  36. *                    ignored.
  37. *
  38. * Description    This function writes characters to the current window
  39. *        without splitting words between rows of the window.
  40. *
  41. *        The window's cursor is left after the end of the
  42. *        displayed string.  The visible cursor is not moved
  43. *        unless this window is currently selected (via WNCURSOR)
  44. *        to have this page's active cursor.
  45. *
  46. *        The num_spaces argument specifies the number of actual
  47. *        characters to use from the buffer.  (If CHAR_ATTR is
  48. *        specified, twice this number of bytes will be used from
  49. *        the buffer.)  If num_spaces is 0 and CHARS_ONLY is used,
  50. *        then characters will be used from the buffer up to (but
  51. *        not including) the first NUL ('\0') encountered.  No
  52. *        more than 32767 bytes should be used from the buffer.
  53. *
  54. *        A "word" is defined to be a sequence of non-whitespace
  55. *        characters that is bounded by whitespace characters or
  56. *        by the beginning or end of the buffer.    "Whitespace"
  57. *        characters are blank (' '), tab ('\t'), bell ('\7'),
  58. *        backspace ('\b'), line feed ('\012'), and carriage
  59. *        return ('\15').  Words are split between rows of the
  60. *        window only if they are longer than the width of the
  61. *        window.  If a word is too long to fit on the current row
  62. *        without splitting, then it is written on the next row of
  63. *        the window, scrolling the window if necessary.
  64. *
  65. *        Multiple blanks are written literally up to the end of
  66. *        the current row.  They are given the attributes
  67. *        specified by fore and back as usual.  No blanks are
  68. *        written at the beginning of a row.  When blanks are
  69. *        added to avoid splitting a word, they are given the
  70. *        window's native attributes.
  71. *
  72. *        The window is scrolled if a line feed occurs on the last
  73. *        row or if the last row is overflowed.  The window's
  74. *        native attributes are used for the new blank row.
  75. *
  76. *        If the screen is in a text mode, specifying -1 for fore
  77. *        or back uses the window's default foreground or background
  78. *        attributes, respectively.  This will occur regardless of
  79. *        the value of option.
  80. *
  81. * Special    Tab characters ('\t') are regarded as single blank
  82. * characters    characters.
  83. *
  84. *        DEL characters ('\177') are written to the screen as
  85. *        blanks.  However, they are treated as nonblanks in that
  86. *        nonblank characters joined by DEL characters will not be
  87. *        split when whole words are wrapped.  The character value
  88. *        written to the screen is 0x20.
  89. *
  90. *        NUL ('\0') is a printable nonblank character (displayed
  91. *        as a blank space), not necessarily the end of the
  92. *        string.  It is only regarded as the end of the string if
  93. *        num_spaces is 0 and CHARS_ONLY is specified.  Otherwise
  94. *        it is treated the same as DEL, except that the character
  95. *        value written to the screen is 0.
  96. *
  97. *        Line feed ('\12') causes the cursor to move down one
  98. *        row, unless it is already on the bottom row of the
  99. *        window, in which case the window is scrolled.
  100. *
  101. *        Carriage return ('\r') causes the cursor to move to the
  102. *        leftmost column of the window.
  103. *
  104. *        Backspace ('\b') causes the cursor to move one column to
  105. *        the left (non-destructively), unless it is already at
  106. *        the leftmost column of the window, in which case nothing
  107. *        happens.
  108. *
  109. *        The BEL character ('\7') causes the computer's bell to
  110. *        sound if the current page is active.
  111. *
  112. * Returns    (Function return type is void.)
  113. *        _wnerr        Possible values:
  114. *                (No change)     Success.
  115. *                WN_BAD_WIN        No window designated
  116. *                        as current.
  117. *                WN_ILL_DIM        Internal error.
  118. *
  119. * Version    3.0  (C)Copyright Blaise Computing Inc. 1986
  120. *
  121. **/
  122.  
  123. #include <string.h>
  124.  
  125. #include <bwindow.h>
  126.  
  127.     /* Macro inc_ptr steps a pointer through the character buffer,    */
  128.     /* returning the new pointer value.                   */
  129.  
  130. #define  inc_ptr(ptr)       (want_attr ? (ptr += 2) : ++ptr)
  131.  
  132.     /* Macro str_len measures the distance between two locations in   */
  133.     /* the character buffer.                          */
  134.  
  135. #define  str_len(from,to)  ((to - from) >> (want_attr ? 1 : 0))
  136.  
  137. #define  BEL        '\7'
  138. #define  BS        '\b'
  139. #define  TAB        '\t'
  140. #define  CR        '\r'
  141. #define  LF        '\12'
  142. #define  DEL        '\177'
  143.  
  144. void wnwrap(num_spaces,buffer,fore,back,option)
  145. int  num_spaces;
  146. char *buffer;
  147. int  fore,back,option;
  148. {
  149.     char ch;
  150.     char *pendstr;
  151.     int  nbytes,nonblank_len;
  152.     int  w,row,col,i;
  153.     int  want_attr;
  154.  
  155.     if (wnvalwin(b_pcurwin) == NIL)
  156.     {
  157.     wnerror(WN_BAD_WIN);
  158.     return;
  159.     }
  160.  
  161.     w = b_pcurwin->img.dim.w;
  162.  
  163.     want_attr = ((option & CHAR_ATTR) != 0);
  164.     if ((!want_attr) && num_spaces == 0)
  165.     num_spaces = (int) strlen(buffer);
  166.  
  167.     while (num_spaces > 0)
  168.     {
  169.     wncurpos(&row,&col);
  170.     switch (ch = *buffer)
  171.     {
  172.         case TAB:
  173.         ch = ' ';             /* Treat TAB as a blank.        */
  174.         case ' ':
  175.         case CR:              /* WNWRTTY handles both          */
  176.         case LF:              /* ordinary and special          */
  177.         case BEL:              /* characters.              */
  178.         case BS:
  179.         if (ch != ' ' || col > 0)  /* Write a blank only if   */
  180.                        /* this isn't the beginning*/
  181.                        /* of the row.          */
  182.             wnwrtty(ch,
  183.                 want_attr ? (int) utlonyb(*(buffer+1)) : fore,
  184.                 want_attr ? (int) uthinyb(*(buffer+1)) : back);
  185.         num_spaces--;
  186.         inc_ptr(buffer);
  187.         break;
  188.  
  189.         default:          /* This is the beginning of a string of */
  190.                   /* one or more nonblanks.           */
  191.  
  192.                   /* First measure the length of the      */
  193.                   /* string of nonblanks.              */
  194.         nbytes    = (want_attr ? (num_spaces << 2) : num_spaces);
  195.         pendstr = buffer;
  196.         while (pendstr < buffer + nbytes)
  197.             if ((ch = *inc_ptr(pendstr)) == ' '
  198.                        || ch == CR
  199.                        || ch == LF
  200.                        || ch == TAB
  201.                        || ch == BEL
  202.                        || ch == BS)
  203.             break;
  204.         nonblank_len = str_len(buffer,pendstr);
  205.  
  206.                   /* If this string won't fit on this row,*/
  207.         if (col + nonblank_len > w
  208.  
  209.                   /* and the string is small enough to    */
  210.                   /* fit on a new row,              */
  211.             && nonblank_len <= w
  212.  
  213.                   /* and this isn't already a fresh row,  */
  214.             && col > 0)
  215.  
  216.                   /* Then fill the rest of the row with   */
  217.                   /* blanks and let WNWRTTY advance us to */
  218.                   /* the next row.                  */
  219.             while (col++ < w)
  220.             wnwrtty((char) ' ',-1,-1);
  221.  
  222.                   /* Write the string itself.  If the     */
  223.                   /* the string is longer than the window */
  224.                   /* is wide, then it will be split, but  */
  225.                   /* at least we tried.              */
  226.         for (i = nonblank_len; i; i--)
  227.         {
  228.             if ((ch = *buffer++) == DEL)
  229.             ch = ' ';     /* Print DEL as a blank         */
  230.             wnwrtty(ch,
  231.                 want_attr ? (int) utlonyb(*buffer) : fore,
  232.                 want_attr ? (int) uthinyb(*buffer) : back);
  233.             if (want_attr)
  234.             buffer++;
  235.         }
  236.         num_spaces -= nonblank_len;
  237.  
  238.         break;
  239.     }
  240.     }
  241. }
  242.