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

📄 findrep.c

📁 这是一个功能强大的文本编辑器
💻 C
📖 第 1 页 / 共 3 页
字号:
         ++md2;
   } else
      for (i--; i >= 0  &&  last_c != p[i]; i--)
         ++md2;

   assert( md2 >= 1  &&  md2 <= len );

   return( md2 );
}


/*
 * Name:    calculate_backward_md2
 * Purpose: Calculate mini delta2 for backward searches
 * Date:    October 31, 1992
 * Passed:  p:  pointer to pattern
 *          len: length of pattern
 * Notes:   the backward mini delta2 is, from the start of the string, the
 *            first rightmost occurrence of the leftmost character.  in the
 *            worst case, mini delta2 is -1.  typically, mini delta2 is the
 *            negative length of the search pattern.
 */
int  calculate_backward_md2( char *p, int len )
{
int  first_c;
register int i;
register int md2;

   md2 = -1;
   i = 1;
   first_c = *p;
   if (mode.search_case == IGNORE) {
      first_c = tolower( first_c );
      for (; i < len  &&  first_c != tolower( p[i] ); i++)
         --md2;
   } else
      for (; i < len  &&  first_c != p[i]; i++)
         --md2;

   assert( md2 <= -1  &&  md2 >= -len );

   return( md2 );
}


/*
 * Name:    forward_boyer_moore_search
 * Purpose: search forward for pattern using boyer array
 * Passed:  window:  pointer to current window
 *          rline:   pointer to real line counter
 *          rcol:    pointer to real column variable
 * Returns: position in file if found or NULL if not found
 * Date:    June 5, 1991
 * Notes:   Start searching from cursor position to end of file.  If we hit
 *          end of file without a match, start searching from the beginning
 *          of file to cursor position.  (do wrapped searches)
 */
line_list_ptr forward_boyer_moore_search( WINDOW *window, long *rline,
     int *rcol )
{
register int len;
int  i;
int  end;
register WINDOW *win;  /* put window pointer in a register */
line_list_ptr ll;

   /*
    * if cursor is beyond end of line then start at end of line
    */
   win  = window;
   i = win->rcol + 1;
   len = win->ll->len;
   if (i > len)
      i = len;
   if (i < 0)
      i = 0;


   *rcol = i;

   assert( *rcol >= 0 );

   *rline = win->rline;
   ll = search_forward( win->ll, rline, (size_t *)rcol );

   if (ll == NULL) {

      end = 0;
      if (win->ll->next != NULL) {
         end = win->ll->next->len;
         win->ll->next->len = EOF;
      }

      /*
       * haven't found pattern yet - now search from beginning of file
       */
      g_status.wrapped = TRUE;

      *rcol = 0;
      *rline = 1L;
      ll = search_forward( win->file_info->line_list, rline, (size_t *)rcol );

      if (ll == win->ll  &&  *rcol >= win->rcol)
         ll = NULL;

      if (win->ll->next != NULL)
         win->ll->next->len = end;
   }

   if (ll != NULL)
      bin_offset_adjust( win, *rline );
   return( ll );
}


/*
 * Name:    search_forward
 * Purpose: search forward for pattern using boyer array
 * Passed:  ll:     pointer to current node in linked list
 *          rline:  pointer to real line counter
 *          offset: offset into ll->line to begin search
 * Returns: position in file if found or NULL if not found
 * Date:    January 8, 1992
 * Notes:   mini delta2 is the first leftmost occurrence of the rightmost
 *            character.
 */
line_list_ptr search_forward( line_list_ptr ll, long *rline, size_t *offset )
{
register int i;
text_ptr p;
text_ptr q;
int  mini_delta2;
unsigned int  mini_guard;
int  guard;
int  pat_len;
int  len_s;
text_ptr s;
char *skip;
boyer_moore_type *bmp;

   if (ll->len == EOF)
      return( NULL );
   else {
      if (g_status.command == DefineGrep  ||  g_status.command == RepeatGrep)
         bmp = &sas_bm;
      else
         bmp = &bm;

      pat_len  = bmp->pattern_length;
      mini_delta2 = bmp->forward_md2;
      skip = bmp->skip_forward;
      p    = bmp->pattern;

      i = pat_len - 1;
      guard = -i;
      mini_guard = *p;
      if (mode.search_case != MATCH)
         mini_guard = tolower( mini_guard );

      s = ll->line;
      s += *offset;
      len_s = ll->len - *offset;
      for (;;) {
         /*
          * Boyer-Moore fast skip loop.  check character count as we move
          *   down the line.
          */
         for (s+=i, len_s-=i; len_s > 0 && (i = skip[(unsigned char)*s]);
                              s+=i, len_s-=i);
         if (len_s > 0) {
            /*
             * i == 0, possible match.  Boyer-Moore slow match loop.
             */

            if (mode.search_case == MATCH) {
               if (s[guard] != mini_guard)
                  goto shift_func;

               q = s + 1 - pat_len;
               for (i=0; i < pat_len; i++)
                  if (q[i] != p[i])
                     goto shift_func;
            } else {
               if ((unsigned int)tolower( s[guard] ) != mini_guard)
                  goto shift_func;

               q = s + 1 - pat_len;
               for (i=0; i < pat_len; i++)
                  if (tolower( q[i] ) != tolower( p[i] ))
                     goto shift_func;
            }
            *offset = (size_t)(q - ll->line);

            assert( *offset <= (unsigned)(ll->len - pat_len) );

            return( ll );
         }
shift_func:
         if (len_s <= 0) {
            ++*rline;
            ll = ll->next;
            s = ll->line;
            if (ll->len == EOF)
               return( NULL );
            len_s = ll->len;
            i = pat_len - 1;
         } else
            i = mini_delta2;
      }
   }
}


/*
 * Name:    backward_boyer_moore_search
 * Purpose: search backward for pattern using boyer array
 * Passed:  window:  pointer to current window
 *          rline:   pointer current real line counter
 *          rcol:    pointer to real column
 * Returns: position in file if found or NULL if not found
 * Date:    June 5, 1991
 * Notes:   Start searching from cursor position to beginning of file. If we
 *          hit beginning end of file without a match, start searching from the
 *          end of file to cursor position.  (do wrapped searches)
 */
line_list_ptr backward_boyer_moore_search( WINDOW *window, long *rline, int *rcol )
{
int  i;
int  len;
int  end;
register WINDOW *win;  /* put window pointer in a register */
line_list_ptr ll;

   win  = window;
   *rline = win->rline;

   /*
    * see if cursor is on EOF line.  if so, move search start to previous node.
    */
   if (win->ll->len != EOF) {
      ll = win->ll;
      i  = win->rcol - 1;
      i += bm.pattern_length - 1;
      len = ll->len;
      if (i >= len)
         i = len - 1;
   } else {
      ll = win->ll->prev;
      --*rline;
      i = 0;
      if (ll != NULL)
         i = ll->len - 1;
   }
   *rcol = i;
   ll = search_backward( ll, rline, (size_t *)rcol );

   if (ll == NULL  &&  win->rline <= win->file_info->length) {

      end = 0;
      if (win->ll->prev != NULL) {
         end = win->ll->prev->len;
         win->ll->prev->len = EOF;
      }

      /*
       * haven't found pattern yet - now search from end of file
       */
      g_status.wrapped = TRUE;
      ll = win->file_info->line_list_end;
      if (ll->prev != NULL)
         *rcol = ll->prev->len;
      else
        *rcol = 0;
      *rline = win->file_info->length;
      ll = search_backward( ll->prev, rline, (size_t *)rcol );

      if (ll == win->ll  &&  *rcol <= win->rcol)
         ll = NULL;

      if (win->ll->prev != NULL)
         win->ll->prev->len = end;
   }
   if (ll != NULL)
      bin_offset_adjust( win, *rline );
   return( ll );
}


/*
 * Name:    search_backward
 * Purpose: search backward for pattern using boyer array
 * Passed:  ll:  pointer to node in linked list to start search
 *          rline:  pointer to real line counter
 *          offset:  offset into ll->line to start search
 * Returns: position in file if found else return NULL
 * Date:    January 8, 1992
 * Notes:   Start searching from cursor position to beginning of file.
 *          mini delta2 is the first rightmost occurrence of the leftmost character.
 */
line_list_ptr search_backward( line_list_ptr ll, long *rline, size_t *offset )
{
register int i;
text_ptr p;
int  mini_delta2;
int  pat_len;
int  len_s;
text_ptr s;

   if (ll == NULL)
      return( NULL );
   if (ll->len == EOF)
      return( NULL );
   else {
      mini_delta2 = bm.backward_md2;
      pat_len  = bm.pattern_length;
      p = bm.pattern;

      i = -bm.pattern_length + 1;

      s = ll->line;
      s += *offset;
      len_s = *offset + 1;
      for (;;) {

         /*
          * Boyer-Moore fast skip loop.  check character count as we move
          *   up the line.
          */
         for (s+=i, len_s+=i; len_s > 0 &&
                 (i = bm.skip_backward[(unsigned char)*s]); s+=i, len_s+=i);
         if (len_s > 0) {
            /*
             * i == 0, possible match.  Boyer-Moore slow match loop.
             */
            if (mode.search_case == MATCH) {
               for (i=0; i < pat_len; i++)
                  if (s[i] != p[i])
                    goto shift_func;
            } else {
               for (i=0; i < pat_len; i++)
                  if (tolower( s[i] ) != tolower( p[i] ))
                     goto shift_func;
            }
            *offset =(size_t)(s - ll->line);

            assert( *offset <= (unsigned)(ll->len - pat_len) );

            return( ll );
         }
shift_func:
         if (len_s <= 0) {
            --*rline;
            ll = ll->prev;
            if (ll == NULL)
               return( NULL );
            if (ll->len == EOF)
               return( NULL );
            len_s = ll->len;
            s = ll->line + len_s - 1;
            i = 1 - pat_len;
         } else
            i = mini_delta2;
      }
   }
}


/*
 * Name:    show_search_message
 * Purpose: display search status
 * Date:    January 8, 1992
 * Passed:  i:     index into message array
 *          color: color to display message
 */
void show_search_message( int i, int color )
{
   /*
    *  0 = blank
    *  1 = wrapped...
    *  2 = searching
    *  3 = replacing
    *  4 = nfa choked
    */
   assert( i >= 0  &&  i <= 4);
   s_output( find7[i], g_display.mode_line, 67, color );
}


/*
 * Name:    bin_offset_adjust
 * Purpose: place cursor on screen given a position in file - default cline
 * Date:    June 5, 1991
 * Passed:  window:  pointer to current window
 *          rline:   real line position some where in the file
 * Notes:   in binary mode, we keep an accurate count of the offset of the
 *          cursor from the beginning of the file.
 */
void bin_offset_adjust( WINDOW *window, long rline )
{
line_list_ptr   node;
long            found_distance;

   assert( rline >= 1L  &&  rline <= window->file_info->length );

   found_distance = window->rline - rline;
   node = window->ll;
   if (found_distance < 0) {
      while (found_distance++ < 0) {
         window->bin_offset += node->len;
         node = node->next;
      }
   } else if (found_distance > 0) {
      while (found_distance-- > 0) {
         node = node->prev;
         window->bin_offset -= node->len;
      }
   }
   assert( window->bin_offset >= 0 );
}


/*
 * Name:    find_adjust
 * Purpose: place cursor on screen given a position in file - default cline
 * Date:    June 5, 1991
 * Passed:  window:  pointer to current window
 *          ll:   position anywhere in file
 *          rline:  real line number of ll in the file
 *          rcol:   real column of ll in the file
 * Notes:   ll could be anywhere in file.  Find the start of line that
 *          ll is on.  Determine if start of line is behind or ahead of
 *          current line.  Once that is done, it is easy to determine if ll
 *          is on screen.  Lastly, current cursor position becomes start of
 *          ll line - reposition and display.
 */
void find_adjust( WINDOW *window, line_list_ptr ll, long rline, int rcol )
{
int  cmd;
long test_line;
file_infos *file;
register WINDOW *win;  /* put window pointer in a register */

   win = window;
   file = win->file_info;

   /*
    * given a real column, adjust for inflated tabs.
    */
   if (mode.inflate_tabs)
      rcol = detab_adjust_rcol( ll->line, rcol );

   /*
    * if p, start of found line, is greater than current line, see if
    * p is between current line and bottom line on screen.
    */
   if (win->rline < rline) {
      /*
       * test_line is the number of lines between rline and found line.
       */
      test_line = rline - win->rline;
      if ((long)win->cline + test_line <= (long)win->bottom_line)
         win->cline += (int)test_line;
      else
         file->dirty = LOCAL;

   /*
    * if p, start of found line, is less than current line, see if
    * p is between current line and top line on screen.
    */
   } else if (win->rline > rline) {
      test_line = win->rline - rline;
      if ((long)win->cline - test_line > (long)(win->top_line+win->ruler-1))
         win->cline -= (int)test_line;
      else
         file->dirty = LOCAL;
      if (rline < (long)(win->cline - (win->top_line+win->ruler-1)))
         win->cline = (int)rline + win->top_line+win->ruler - 1;
   }

   /*
    * cursor line becomes found line.  check if column is on screen.
    */
   win->rline = rline;
   win->ll    = ll;
   if (file->dirty == LOCAL && (win->cline == win->bottom_line ||
                                win->cline == win->top_line + win->ruler)) {
      cmd = g_status.command;
      if (cmd == RepeatFindForward1    ||  cmd == RepeatFindBackward1 ||
          cmd == DefineDiff            ||  cmd == RepeatDiff          ||
          cmd == FindRegX              ||  cmd == RepeatFindRegX      ||
          cmd == DefineGrep            ||  cmd == RepeatGrep) {
         center_window( win );
      } else if (cmd == ReplaceString) {
         if (win->visible)
            center_window( win );
      }
   }
   check_virtual_col( win, rcol, rcol );
}


/*
 * Name:    replace_string
 * Purpose: To set up and perform a replace operation.
 * Date:    June 5, 1991
 * Passed:  window:  pointer to current window
 */
int  replace_string( WINDOW *window )
{
int  direction;
char pattern[MAX_COLS];  /* the old and replacement text */
int  net_change;
int  sub_len;
int  file_changed;
int  finished;
int  use_prev_find;

⌨️ 快捷键说明

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