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

📄 tab.c

📁 C语言实战105例源码
💻 C
📖 第 1 页 / 共 2 页
字号:

#include "tdestr.h"
#include "common.h"
#include "tdefunc.h"
#include "define.h"


/*
 * Name:    tab_key
 * Purpose: To make the necessary changes after the user types the tab key.
 * Date:    June 5, 1991
 * Passed:  window:  pointer to current window
 * Notes:   If in insert mode, then this function adds the required
 *           number of spaces in the file.
 *          If not in insert mode, then tab simply moves the cursor right
 *           the required distance.
 */
int  tab_key( WINDOW *window )
{
int  spaces;    /* the spaces to move to the next tab stop */
char *source;   /* source for block move to make room for c */
char *dest;     /* destination for block move */
int  pad;
int  len;
register int rcol;
int  old_bcol;
register WINDOW *win;   /* put window pointer in a register */
int  rc;

   win  = window;
   if (win->ll->len  ==  EOF)
      return( OK );
   rcol = win->rcol;
   old_bcol = win->bcol;
   show_ruler_char( win );
   /*
    * work out the number of spaces to the next tab stop
    */
   if (mode.smart_tab)
      spaces = next_smart_tab( win );
   else
      spaces = mode.ltab_size - (rcol % mode.ltab_size);

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

   rc = OK;
   if (mode.insert && rcol + spaces < g_display.line_length) {
      copy_line( win->ll );
      detab_linebuff( );

      /*
       * work out how many characters need to be inserted
       */
      len = g_status.line_buff_len;
      pad = rcol > len ? rcol - len : 0;
      if (len + pad + spaces >= g_display.line_length) {
         /*
          *  line too long to add
          */
         error( WARNING, win->bottom_line, ed1 );
         rc = ERROR;
         g_status.copied = FALSE;
      } else {
         if (pad > 0  || spaces > 0) {
            source = g_status.line_buff + rcol - pad;
            dest = source + pad + spaces;

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

            memmove( dest, source, len + pad - rcol );

            /*
             * if padding was required, then put in the required spaces
             */

            assert( pad + spaces >= 0 );
            assert( pad + spaces < MAX_LINE_LENGTH );

            memset( source, ' ', pad + spaces );
            g_status.line_buff_len += pad + spaces;
            entab_linebuff( );
         }

         win->ll->dirty = TRUE;
         win->file_info->dirty = GLOBAL;
         show_changed_line( win );
         rcol += spaces;
         win->ccol += spaces;
      }
   } else if (rcol + spaces <= g_display.line_length) {
      /*
       * advance the cursor without changing the text underneath
       */
      rcol += spaces;
      win->ccol += spaces;
   }
   check_virtual_col( win, rcol, win->ccol );
   if (old_bcol != win->bcol) {
      make_ruler( win );
      show_ruler( win );
   }
   return( rc );
}


/*
 * Name:    backtab
 * Purpose: To make the necessary changes after the user presses the backtab.
 * Date:    November 1, 1991
 * Passed:  window:  pointer to current window
 * Notes:   If in insert mode, then this function subs the required
 *           number of spaces in the file.
 *          If not in insert mode, then tab simply moves the cursor left
 *           the required distance.
 */
int  backtab( WINDOW *window )
{
int  spaces;    /* the spaces to move to the next tab stop */
char *source;   /* source for block move to make room for c */
char *dest;     /* destination for block move */
int  pad;
int  len;
register int rcol;
int  old_bcol;
register WINDOW *win;   /* put window pointer in a register */

   win  = window;
   rcol = win->rcol;
   if (win->ll->len == EOF || win->rcol == 0)
      return( OK );
   old_bcol = win->bcol;
   show_ruler_char( win );

   /*
    * work out the number of spaces to the previous tab stop
    */
   if (mode.smart_tab)
      spaces = prev_smart_tab( win );
   else
      spaces = win->rcol % mode.ltab_size;

   if (spaces == 0)
      spaces = mode.ltab_size;
   copy_line( win->ll );
   detab_linebuff( );
   len = g_status.line_buff_len;
   if (mode.insert && rcol - spaces < len) {
      pad = rcol > len ? rcol - len : 0;
      if (pad > 0  || spaces > 0) {
         /*
          * if padding was required, then put in the required spaces
          */
         if (pad > 0) {

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

            source = g_status.line_buff + rcol - pad;
            dest = source + pad;

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

            memmove( dest, source, pad );
            memset( source, ' ', pad );
            g_status.line_buff_len += pad;
         }
         source = g_status.line_buff + rcol;
         dest = source - spaces;

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

         memmove( dest, source, len + pad - rcol );
         g_status.line_buff_len -= spaces;
         entab_linebuff( );
      }

      win->ll->dirty = TRUE;
      win->file_info->dirty = GLOBAL;
      show_changed_line( win );
      rcol -= spaces;
      win->ccol -= spaces;
   } else {
      /*
       * move the cursor without changing the text underneath
       */
      rcol -= spaces;
      if (rcol < 0)
         rcol = 0;
      win->ccol -= spaces;
   }
   check_virtual_col( win, rcol, win->ccol );
   if (old_bcol != win->bcol) {
      make_ruler( win );
      show_ruler( win );
   }
   return( OK );
}


/*
 * Name:    next_smart_tab
 * Purpose: To find next smart tab
 * Date:    June 5, 1992
 * Passed:  window: pointer to the current window
 * Notes:   To find a smart tab 1) find the first non-blank line above the
 *            current line, 2) find the first non-blank character after
 *            column of the cursor.
 */
int  next_smart_tab( WINDOW *window )
{
register int spaces;    /* the spaces to move to the next tab stop */
text_ptr s;             /* pointer to text */
line_list_ptr ll;
register WINDOW *win;   /* put window pointer in a register */
int  len;

   /*
    * find first previous non-blank line above the cursor.
    */
   win = window;
   ll = win->ll->prev;
   while (ll != NULL  && is_line_blank( ll->line, ll->len ))
      ll = ll->prev;

   if (ll != NULL) {
      s = ll->line;
      /*
       * if cursor is past the eol of the smart line, lets find the
       *   next fixed tab.
       */
      if (window->rcol >= find_end( s, ll->len ))
         spaces = mode.ltab_size - (window->rcol % mode.ltab_size);
      else {

         len = ll->len;
         s = detab_a_line( s, &len );

         spaces = 0;
         s = s + window->rcol;
         len -= window->rcol;

         /*
          * if we are on a word, find the end of it.
          */
         while (*s != ' '  &&  len > 0) {
            ++s;
            ++spaces;
            --len;
         }

         /*
          * now find the start of the next word.
          */
         if (len > 0)
            while (*s == ' ' && len > 0) {
               ++s;
               ++spaces;
               --len;
            }
      }
   } else
      spaces = mode.ltab_size - (window->rcol % mode.ltab_size);
   return( spaces );
}


/*
 * Name:    prev_smart_tab
 * Purpose: To find previous smart tab
 * Date:    June 5, 1992
 * Passed:  window: pointer to the current window
 * Notes:   To find a smart tab 1) find the first non-blank line above the
 *            current line, 2) find the first non-blank character before
 *            column of the cursor.
 *          there are several cases to consider:  1) the cursor is past the
 *            the end of the smart line, 2) the smart pointer is in the
 *            middle of a word, 3) there are no more words between the
 *            smart pointer and the beginning of the line.
 */
int  prev_smart_tab( WINDOW *window )
{
register int spaces;    /* the spaces to move to the next tab stop */
text_ptr s;             /* pointer to text */
int  len;
line_list_ptr ll;
WINDOW *win;            /* put window pointer in a register */

   /*
    * find first previous non-blank line above the cursor, if it exists.
    */
   win = window;
   ll = win->ll->prev;
   while (ll != NULL  && is_line_blank( ll->line, ll->len ))
      ll = ll->prev;

   if (ll != NULL) {
      s = ll->line;

      /*
       * if there are no words between the cursor and column 1 of the
       *   smart tab line, find previous fixed tab.
       */
      if (window->rcol < first_non_blank( s, ll->len ))
         spaces = window->rcol % mode.ltab_size;
      else {

         len = ll->len;
         if (mode.inflate_tabs)
            s = detab_a_line( s, &len );

         /*
          * now, we need to figure the initial pointer and space.
          *   if the cursor is past the eol of the smart line, then
          *   set the smart pointer "s" to the end of line and "spaces" to
          *   the number of characters between the cursor and the eol
          *   of the smart line.  otherwise, set the smart pointer "s" to
          *   the column of the cursor and "spaces" to 0.
          */
         if (len < window->rcol) {
            s += len;
            spaces = window->rcol - len;
         } else {
            len = window->rcol;
            s += window->rcol;
            spaces = 0;
         }

         while (*(s-1) == ' ' && len > 0) {
            --s;
            ++spaces;
            --len;
         }

         /*
          * now find the beginning of the first word at eol.
          */
         while (*(s-1) != ' '  &&  len > 0) {
            --s;
            ++spaces;
            --len;
         }
         if (len == 0 && *s == ' ')
            spaces = window->rcol % mode.ltab_size;
         if (spaces > window->rcol)
            spaces = window->rcol;
      }
   } else
      spaces = window->rcol % mode.ltab_size;

   /*
    * spaces cannot be negative.
    */
   if (spaces < 0)
      spaces = 0;
   return( spaces );
}


/*
 * Name:    entab
 * Purpose: To compress spaces to tabs
 * Date:    October 31, 1992
 * Passed:  s: pointer to current line
 * Returns: pointer to tabout_buf
 * Notes:   the text_ptr can point to either the g_status.line_buff or
 *            a line in the main text buffer.
 *          this function assumes that a '\n' terminates the line.
 */
text_ptr entab( text_ptr s, int len )
{
int  tab_size;
int  last_col;
int  space;
register int col;
text_ptr to;

   assert( s != NULL );
   assert( len >= 0 );
   assert( len < MAX_LINE_LENGTH );

   tab_size = mode.ptab_size;
   to = (text_ptr)g_status.tabout_buff;
   if (s == NULL)
      g_status.tabout_buff_len = 0;
   else {
      g_status.tabout_buff_len = len;
      for (last_col=col=0; ; s++, len--) {
         if (len == 0) {

            /*
             * when we reach the eol, compress trailing spaces to tabs.
             *   the un_copy_line function is responsible for trimming
             *   trailing space.
             */
            if (col != last_col) {
               while (last_col < col) {
                  space = tab_size - last_col % tab_size;
                  if (space <= 1) {
                     *to++ = ' ';
                     last_col++;
                  } else if (last_col + space <= col) {
                     *to++ = '\t';
                     last_col += space;
                     g_status.tabout_buff_len -= (space - 1);
                  } else {
                     *to++ = ' ';
                     last_col++;
                  }
               }
            }

            /*
             * stop entabbing when we get to EOL
             */
            break;
         } else if (*s == ' ')
            col++;
         else {
            if (col != last_col) {
               while (last_col < col) {
                  space = tab_size - last_col % tab_size;

                  /*
                   * when space == 1, forget about emmitting a tab
                   *   for 1 space.
                   */
                  if (space <= 1) {
                     *to++ = ' ';
                     last_col++;
                  } else if (last_col + space <= col) {
                     *to++ = '\t';
                     last_col += space;
                     g_status.tabout_buff_len -= (space - 1);
                  } else {
                     *to++ = ' ';
                     last_col++;
                  }
               }
            }

            /*
             * if *s == tab, then adjust the col pointer
             */
            if (*s == '\t')
               col = col + tab_size - (col % tab_size);
            else
               ++col;
            last_col = col;
            *to++ = *s;

            /*
             * when we see a quote character, stop entabbing.
             */
            if (*s == '\"' || *s == '\'') {
               while (len > 0) {

⌨️ 快捷键说明

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