⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wordwrap.c

📁 《c语言实例解析精粹》
💻 C
📖 第 1 页 / 共 2 页
字号:
}


/*
 * Name:    combine_wrap_spill
 * Purpose: combine word wrap lines so we don't push each word onto a
 *          separate line.
 * Date:    November 27, 1991
 * Passed:  window:   pointer to current window
 *          wrap_col: col to combine next line
 *          lm:       left margin
 *          rm:       right margin
 *          side:     left or right margin to insert spaces
 *          new_line: boolean, should we insert a new line?
 */
void combine_wrap_spill( WINDOW *window, int wrap_col, int lm, int rm,
                         int side, int new_line )
{
line_list_ptr p;        /* line we wrapped */
line_list_ptr pp;       /* pointer to next line after wrapped line */
int  p_len;             /* length of line we just word wrapped */
int  non_blank;         /* first non-blank column on next line */
int  control_t;         /* number of times to call word_delete */
int  next_line_len;     /* length of next line counting from 1st word */
WINDOW w;               /* scratch window */

   dup_window_info( &w, window );
   g_status.command = WordWrap;
   w.rcol = wrap_col;
   if (new_line) {
      insert_newline( &w );
      if (mode.right_justify == TRUE)
         justify_right_margin( &w, w.ll->prev, mode.word_wrap == FIXED_WRAP ?
                find_left_margin( w.ll->prev, mode.word_wrap ) : lm, rm, side );
      p = window->ll->next;
   } else
      p = window->ll;
   if (p != NULL) {
      p_len = find_end( p->line, p->len );
      pp = p->next;
      if (pp != NULL) {
         non_blank = first_non_blank( pp->line, pp->len );
         next_line_len = find_end( pp->line, pp->len ) - non_blank;
         if (!is_line_blank( pp->line, pp->len ) && p_len + next_line_len <= rm) {
            control_t = 1;
            if (mode.inflate_tabs) {
               if (*pp->line == ' '  ||  *pp->line == '\t')
                  ++control_t;
            } else if (*pp->line == ' ')
               ++control_t;
            w.ll = p;
            w.rcol = p_len + 1;
            if (*(p->line+p_len-1) == '.')
               ++w.rcol;
            while (control_t--)
               word_delete( &w );
            remove_spaces( lm );
            un_copy_line( w.ll, &w, TRUE );
         }
         window->file_info->dirty = GLOBAL;
      }
   }
}


/*
 * Name:    justify_right_margin
 * Purpose: distribute blanks in line to justify right margin
 * Date:    December 30, 1992
 * Passed:  window:   pointer to current window
 *          ll:       current node pointing to current line
 *          lm:       left margin
 *          rm:       right margin
 *          side:     which side to start inserting space? LEFT or RIGHT
 * Notes:   this routine is based on the spread function by
 *           Kernighan and Plauger in _Software Tools_, Addison-Wesly,
 *           Reading, Mass., 1976, ISBN 0-201-03669-X, pp 240-241.
 */
void justify_right_margin( WINDOW *window, line_list_ptr ll, int lm, int rm,
                           int side )
{
int  len;
int  i;
int  word_count;
int  holes;
int  nb;
int  spaces;
text_ptr s;

   /*
    * make sure line is longer than the left margin and less than the right.
    */
   len = find_end( ll->line, ll->len );
   if (len <= lm || len >= rm+1)
      return;

   /*
    * now, count the number of words in line.
    */
   i = entab_adjust_rcol( ll->line, ll->len, lm );
   s = ll->line + i;
   len -= i;
   word_count = 0;
   while (len > 0) {
      while (len-- > 0  &&  *s++ == ' ');
      if (len == 0)
         break;
      ++word_count;
      while (len-- > 0  &&  *s++ != ' ');
   }

   /*
    * can't justify right margin with one word or less.
    */
   if (word_count <= 1)
      return;

   holes = word_count - 1;
   copy_line( ll );
   detab_linebuff( );
   remove_spaces( lm );

   /*
    * find out how many spaces we need.  if spaces <= 0, then get out.
    */
   i = g_status.line_buff_len - 1;
   spaces = rm - i;
   if (spaces <= 0)
      return;
   g_status.line_buff_len += spaces;

   /*
    * this while loop is based on the while loop on page 241 in
    *   _Software Tools_, Kernighan and Plauger.  I added a while loop
    *   to skip extra blanks after a period or other space intentially
    *   inserted into the text.
    */
   while (i < rm) {
      g_status.line_buff[rm] = g_status.line_buff[i];
      if (g_status.line_buff[rm] == ' ') {

         /*
          * this while loop copies extra blanks after a period or
          *   blanks otherwise intentially left in the text.
          */
         while (g_status.line_buff[i-1] == ' ')
            g_status.line_buff[--rm] = g_status.line_buff[--i];

         nb = side == LEFT ? spaces / holes : (spaces - 1) / holes + 1;
         spaces -= nb;
         --holes;
         while (nb-- > 0)
            g_status.line_buff[--rm] = ' ';
      }
      --i;
      --rm;
   }
   entab_linebuff( );
   un_copy_line( ll, window, window->bottom_line );
}


/*
 * Name:    remove_spaces
 * Purpose: remove any extra spaces in the text
 * Date:    December 30, 1992
 * Passed:  lm:   left margin
 * Notes:   this routine squeezes out extra space from a previous format.
 *          the line must be placed in the line buffer before calling this
 *            function.
 */
void remove_spaces( int lm )
{
int  period;
int  len;
int  i;
int  c;
char *s;
char *d;

   if ((i = len = g_status.line_buff_len) <= lm)
      return;

   period = FALSE;
   s = d = g_status.line_buff + lm;
   i -= lm;
   c = (int)*s++;
   while (c == ' ' && i > 0) {
      c = *s++;
      --i;
      --len;
   }
   period = c == '.' ? TRUE : FALSE;
   while (i > 0) {
      *d++ = (char)c;
      c = (int)*s++;
      --i;
      if (c != ' ')
         period =  c == '.' ? TRUE : FALSE;
      else {
         *d++ = (char)c;
         c = (int)*s++;
         --i;
         if (period  &&  c == ' ') {
            *d++ = (char)c;
            period = FALSE;
            if (i > 0)
               ++len;
         }
         while (c == ' '  &&  i > 0) {
            c = (int)*s++;
            --len;
            --i;
         }
      }
   }
   *d = (char)c;
   g_status.line_buff_len = len;
}


/*
 * Name:    find_word
 * Purpose: find a word on a line
 * Date:    November 29, 1991
 * Passed:  p:          pointer to a line of text
 *          len:        len of line
 *          start_col:  col to start the search
 * Notes:   returns the column of the next word or -1 (ERROR) if no more words
 */
int  find_word( text_ptr p, int len, int start_col )
{
register int rc;
register char c;

   if (len <= start_col  ||  len < 0  || start_col < 0)
      return( ERROR );
   p += start_col;
   rc = start_col;

   if (mode.inflate_tabs) {
      while (len-- > 0 && ((c = *p++) == ' ' || c == '\t'))
         if (c != '\t')
            ++rc;
         else
            rc += mode.ptab_size - (rc % mode.ptab_size);
   } else
      while (len-- > 0  &&  (c = *p++) == ' ')
         ++rc;
   if (len <= 0)
     rc = ERROR;
   return( rc );
}


/*
 * Name:    flush_left
 * Purpose: flush line on left margin
 * Date:    November 27, 1991
 * Passed:  window:  pointer to current window
 */
int  flush_left( WINDOW *window )
{
int  len;       /* length of current line */
register int spaces;
char *source;
char *dest;
int  rcol;
int  lm;
register WINDOW *win;          /* put window pointer in a register */

   win = window;
   copy_line( win->ll );
   detab_linebuff( );
   lm = mode.left_margin;
   rcol = find_word( (text_ptr)g_status.line_buff, g_status.line_buff_len, 0 );
   if (rcol != ERROR && rcol != lm) {

      /*
       * must add spaces to get the indentation correct
       */
      if (rcol < lm) {
         source = g_status.line_buff;
         spaces = lm - rcol;
         dest = source + spaces;
         len = g_status.line_buff_len;
         if (len + spaces > MAX_LINE_LENGTH) {
            /*
             * line would be too long
             */
            error( WARNING, win->bottom_line, ww1 );
            return( ERROR );
         } else {
            load_undo_buffer( win->file_info, win->ll->line, win->ll->len );

            assert( len >= 0 );
            assert( len < MAX_LINE_LENGTH );

            memmove( dest, source, len );
            g_status.line_buff_len += spaces;
            while (spaces--)
               *source++ = ' ';
            win->file_info->dirty = GLOBAL;
         }

      /*
       * else delete spaces to get the indentation correct
       */
      } else {
         dest = g_status.line_buff + lm;
         source = g_status.line_buff + rcol;

         assert( g_status.line_buff_len - rcol >= 0 );
         assert( g_status.line_buff_len - rcol < MAX_LINE_LENGTH );

         memmove( dest, source, g_status.line_buff_len - rcol );
         g_status.line_buff_len -= (rcol - lm);
         win->file_info->dirty = GLOBAL;
      }
      win->ll->dirty = TRUE;
      show_changed_line( win );
   }
   return( OK );
}


/*
 * Name:    flush_right
 * Purpose: flush line on right margin
 * Date:    November 27, 1991
 * Passed:  window:  pointer to current window
 */
int  flush_right( WINDOW *window )
{
int  len;               /* length of current line */
int  i;
int  spaces;
char *source;
char *dest;
register int rcol;
int  rm;
register WINDOW *win;   /* put window pointer in a register */

   win = window;
   copy_line( win->ll );
   detab_linebuff( );
   source = g_status.line_buff;
   len = g_status.line_buff_len;
   if (!is_line_blank( (text_ptr)source, len )) {
      rm = mode.right_margin;
      for (rcol=len-1; rcol>=0 && *(source+rcol) == ' ';)
         rcol--;
      if (rcol != rm) {

         /*
          * if rcol is less than right margin then we need to add spaces.
          */
         if (rcol < rm) {
            spaces = rm - rcol;
            dest = source + spaces;
            if (len + spaces > MAX_LINE_LENGTH) {
               /*
                * line would be too long
                */
               error( WARNING, win->bottom_line, ww1 );
               return( ERROR );
            } else {
               load_undo_buffer( win->file_info, win->ll->line, win->ll->len );

               assert( len >= 0 );
               assert( len < MAX_LINE_LENGTH );

               memmove( dest, source, len );
               g_status.line_buff_len += spaces;
               while (spaces--)
                  *source++ = ' ';
               win->file_info->dirty = GLOBAL;
            }

         /*
          * if rcol is greater than right margin then we need to sub spaces.
          */
         } else {
            load_undo_buffer( win->file_info, win->ll->line, win->ll->len );
            rcol = rcol - rm;
            i = first_non_blank( (text_ptr)source, len );
            if (rcol > i)
               rcol = i;
            dest = source + rcol;

            assert( len - rcol >= 0 );
            assert( len - rcol < MAX_LINE_LENGTH );

            memmove( source, dest, len - rcol );
            g_status.line_buff_len -= (rcol - rm);
            win->file_info->dirty = GLOBAL;
         }
         win->ll->dirty = TRUE;
         show_changed_line( win );
      }
   }
   return( OK );
}


/*
 * Name:    flush_center
 * Purpose: flush line in center of margins
 * Date:    November 27, 1991
 * Passed:  window:  pointer to current window
 */
int  flush_center( WINDOW *window )
{
int  len;               /* length of current line */
char *source;           /* temp line buffer pointers */
char *dest;
int  rm;
int  lm;
register int spaces;    /* center of text on current line */
int  center;            /* center of current margins */
int  first;             /* column of first char on line */
int  last;              /* column of last char on line */
register WINDOW *win;   /* put window pointer in a register */

   win = window;
   copy_line( win->ll );
   detab_linebuff( );
   source = g_status.line_buff;
   len = g_status.line_buff_len;
   if (!is_line_blank( (text_ptr)source, len )) {
      rm = mode.right_margin;
      lm = mode.left_margin;
      center = (rm + lm) / 2;
      first = first_non_blank( (text_ptr)source, len );
      for (last=len-1; last>=0 && *(source+last) == ' ';)
         last--;
      spaces = last + first - 1;
      spaces = (spaces / 2) + (spaces & 1);
      if (spaces != center) {

         /*
          * if spaces is less than center margin then we need to add spaces.
          */
         if (spaces < center) {
            spaces = center - spaces;
            dest = source + spaces;
            if (len + spaces > MAX_LINE_LENGTH) {
               /*
                * line would be too long
                */
               error( WARNING, win->bottom_line, ww1 );
               return( ERROR );
            } else {
               load_undo_buffer( win->file_info, win->ll->line, win->ll->len );

               assert( len >= 0 );
               assert( len < MAX_LINE_LENGTH );

               memmove( dest, source, len );
               g_status.line_buff_len += spaces;
               while (spaces--)
                  *source++ = ' ';
               win->file_info->dirty = GLOBAL;
            }

         /*
          * if spaces is greater than center margin then we need to sub spaces.
          */
         } else {
            load_undo_buffer( win->file_info, win->ll->line, win->ll->len );
            spaces = spaces - center;
            if (spaces > first)
               spaces = first;
            dest = source + spaces;

            assert( len - spaces >= 0 );
            assert( len - spaces < MAX_LINE_LENGTH );

            memmove( source, dest, len - spaces );
            g_status.line_buff_len -= spaces;
            win->file_info->dirty = GLOBAL;
         }
         win->ll->dirty = TRUE;
         show_changed_line( win );
      }
   }
   return( OK );
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -