home *** CD-ROM | disk | FTP | other *** search
- /**
- *
- * Name scwrap -- Write a string of characters to a rectangular
- * region on the current display page via BIOS,
- * TTY-style, with word wrap.
- *
- * Synopsis scwrap(u_row,u_col,l_row,l_col,num_spaces,
- * buffer,fore,back,option);
- *
- * int u_row Top row of region (0 = top of screen)
- * int u_col Leftmost column of region (0 = left edge)
- * int l_row Bottom row of region
- * int l_col Rightmost column of region
- * int num_spaces Number of characters to write.
- * If CHARS_ONLY is specified (see "option"
- * below), num_spaces == 0 indicates that
- * the buffer is terminated by a NUL ('\0')
- * character.
- * char *buffer Data to write
- * int fore -1 if existing foreground is to be
- * preserved; if CHARS_ONLY is specified, a
- * value between 0 and 15 specifies a new
- * foreground attribute.
- * int back -1 if existing background is to be
- * preserved; if CHARS_ONLY is specified, a
- * value between 0 and 15 specifies a new
- * foreground attribute.
- * int option One bit of the option value tells SCWRAP
- * how the buffer is constructed. The two
- * possible values are:
- *
- * Value Meaning
- * ----------- ------------------------------------
- * CHARS_ONLY Buffer contains characters only.
- * If num_spaces is zero, the string
- * is terminated by a NUL ('\0')
- * character.
- * The values of fore and back are used
- * as attributes.
- * CHAR_ATTR Buffer contains (char,attr) pairs.
- * The values of fore and back are
- * ignored.
- *
- * Description This function writes characters to a rectangular region
- * on the current display page without splitting words
- * between lines.
- *
- * If the cursor is currently within the region, the
- * characters are written beginning at that point. If the
- * cursor is not within the region, the characters are
- * written beginning at the upper left corner of the
- * region. The cursor is left after the end of the
- * displayed string.
- *
- * The num_spaces argument specifies the number of actual
- * characters to use from the buffer. (If CHAR_ATTR is
- * specified, twice this number of bytes will be used from
- * the buffer.) No more than 32767 bytes should be used
- * from the buffer.
- *
- * A "word" is defined to be a sequence of non-whitespace
- * characters that is bounded by whitespace characters or
- * by the beginning or end of the buffer. "Whitespace"
- * characters are blank (' '), tab ('\t'), bell ('\7'),
- * backspace ('\b'), line feed ('\012'), and carriage
- * return ('\15'). Words are split between rows of the
- * region only if they are longer than the width of the
- * region. If a word is too long to fit on the current row
- * without splitting, then it is written on the next row of
- * the region, scrolling the region if necessary.
- *
- * Multiple blanks are written literally up to the end of
- * the current line. No blanks are written at the
- * beginning of a line.
- *
- * The region is scrolled if a line feed occurs on the last
- * line or if the last line is overflowed. The attribute
- * for the new blank line is chosen in the same manner as
- * SCTTYWRT.
- *
- * If the screen is in a text mode and CHARS_ONLY is
- * specified, then specifying -1 for fore or back preserves
- * the existing foreground or background attributes,
- * respectively. If the screen is in a graphics mode and
- * CHARS_ONLY is specified, then specifying -1 for fore
- * will cause color 1 to be used.
- *
- * Special Tab characters ('\t') are regarded as single blank
- * characters characters.
- *
- * DEL characters ('\177') are written to the screen as
- * blanks. However, they are treated as nonblanks in that
- * nonblank characters joined by DEL characters will not be
- * split when whole words are wrapped. The character value
- * written to the screen is 0x20.
- *
- * NUL ('\0') is treated differently depending on the
- * values of option and num_spaces. If CHARS_ONLY is
- * designated and num_spaces is zero, then NUL denotes the
- * end of the string. Otherwise it is a printable nonblank
- * character (displayed as a blank space), not the end of
- * the string. Thus it is treated the same as DEL, except
- * that the character value written to the screen is 0.
- *
- * Line feed ('\12') causes the cursor to move down one
- * row, unless it is already on the bottom row of the
- * region, in which case the screen is scrolled.
- *
- * Carriage return ('\r') causes the cursor to move to the
- * leftmost column of the region.
- *
- * Backspace ('\b') causes the cursor to move one column to
- * the left (non-destructively), unless it is already at
- * the leftmost column of the region, in which case nothing
- * happens.
- *
- * The BEL character ('\7') causes the computer's bell to
- * sound if the current page is active.
- *
- * Returns (None. Function return type is void.)
- *
- * Version 3.0 (C)Copyright Blaise Computing Inc. 1986
- *
- **/
-
- #include <string.h>
-
- #include <bscreen.h>
-
- #define range(a,l,h) (((a) < (l) || (a) > (h)))
-
- /* Macro inc_ptr steps a pointer through the character buffer, */
- /* returning the new pointer value. */
-
- #define inc_ptr(ptr) (want_attr ? (ptr += 2) : ++ptr)
-
- /* Macro str_len measures the distance between two locations in */
- /* the character buffer. */
-
- #define str_len(from,to) ((to - from) >> (want_attr ? 1 : 0))
-
- #define BEL '\7'
- #define BS '\b'
- #define TAB '\t'
- #define CR '\r'
- #define LF '\12'
- #define DEL '\177'
-
- void scwrap(u_row,u_col,l_row,l_col,num_spaces,buffer,fore,back,option)
- int u_row,u_col,l_row,l_col,num_spaces;
- char *buffer;
- int fore,back,option;
- {
- int mode,columns,act_page,last_row;
- char ch;
- char *pendstr;
- int nbytes,nonblank_len;
- int row,col,i;
- int want_attr;
-
- scmode(&mode,&columns,&act_page);
- last_row = scrows() - 1;
-
- utbound(u_row,0,last_row) /* Force reasonable values */
- utbound(u_col,0,columns - 1)
- utbound(l_row,u_row,last_row)
- utbound(l_col,u_col,columns - 1)
-
- sccurpos(&row,&col);
- if (range(row,u_row,l_row) || range(col,u_col,l_col))
- sccurset((row = u_row),(col = u_col));
-
- want_attr = ((option & CHAR_ATTR) != 0);
- if ((!want_attr) && num_spaces == 0)
- num_spaces = (int) strlen(buffer);
-
- while (num_spaces > 0)
- {
- sccurpos(&row,&col);
- switch (ch = *buffer)
- {
- case TAB:
- ch = ' '; /* Treat TAB as a blank. */
- case ' ':
- if (col == u_col) /* Write the blank only if this */
- { /* isn't the beginning of the */
- num_spaces--; /* line. */
- inc_ptr(buffer);
- break;
- }
- case CR: /* SCTTYWIN handles both */
- case LF: /* ordinary and special */
- case BEL: /* characters. */
- case BS:
- scttywin(u_row,u_col,l_row,l_col,ch,
- want_attr ? (int) utlonyb(*(buffer+1)) : fore,
- want_attr ? (int) uthinyb(*(buffer+1)) : back,
- -1,-1);
- num_spaces--;
- inc_ptr(buffer);
- break;
-
- default: /* This is the beginning of a */
- /* string of one or more */
- /* nonblanks. */
-
- /* First measure the length of */
- /* the string of nonblanks. */
- nbytes = (want_attr ? (num_spaces << 2) : num_spaces);
- pendstr = buffer;
- while (pendstr < buffer + nbytes)
- if ((ch = *inc_ptr(pendstr)) == ' '
- || ch == CR
- || ch == LF
- || ch == TAB
- || ch == BEL
- || ch == BS)
- break;
- nonblank_len = str_len(buffer,pendstr);
-
- /* If this string won't fit on */
- /* this line, */
- if (col + nonblank_len > l_col + 1
-
- /* and the string is small */
- /* enough to fit on a new line, */
- && nonblank_len <= (l_col - u_col + 1)
-
- /* and this isn't already a */
- /* fresh line, */
- && col > u_col)
-
- /* Then fill the rest of the */
- /* line with blanks and let */
- /* SCTTYWIN advance us to the */
- /* next line. */
- while (col++ <= l_col)
- scttywin(u_row,u_col,l_row,l_col,
- (char) ' ',-1,-1,-1,-1);
-
- /* Write the string itself. If */
- /* the string is longer than */
- /* the region is wide, then it */
- /* will be split, but at least */
- /* we tried. */
- for (i = nonblank_len; i; i--)
- {
- if ((ch = *buffer++) == DEL)
- ch = ' '; /* Print DEL as a blank */
- scttywin(u_row,u_col,l_row,l_col,ch,
- want_attr ? (int) utlonyb(*buffer) : fore,
- want_attr ? (int) uthinyb(*buffer) : back,
- -1,-1);
- if (want_attr)
- buffer++;
- }
- num_spaces -= nonblank_len;
-
- break;
- }
- }
- }