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

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