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

📄 findrep.c

📁 这是一个功能强大的文本编辑器
💻 C
📖 第 1 页 / 共 3 页
字号:


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


/*
 * Name:    get_replacement_flags
 * Purpose: To input find and replace flags.
 * Date:    June 5, 1991
 * Passed:  line:  prompt line
 * Returns: OK if flags were entered, ERROR if user wanted to abort
 */
int  get_replacement_flags( int line )
{
char line_buff[(MAX_COLS+1)*2]; /* buffer for char and attribute  */
register int c;
int  func;
int  rc;

   save_screen_line( 0, line, line_buff );
   eol_clear( 0, line, g_display.text_color );
   /*
    * options: prompt or no prompt (p/n)?
    */
   s_output( find1, line, 0, g_display.message_color );
   xygoto( strlen( find1 ) + 2, line );
   do {
      c = getkey( );
      func = getfunc( c );
   } while (c != 'P'  &&  c != 'p'  &&  c != 'N'  &&  c != 'n'  &&
            c != RTURN  &&  c != ESC  &&  func != AbortCommand);
   restore_screen_line( 0, line, line_buff );
   switch (c) {
      case 'P' :
      case 'p' :
      case RTURN :
         g_status.replace_flag = PROMPT;
         rc = OK;
         break;
      case 'N' :
      case 'n' :
         g_status.replace_flag = NOPROMPT;
         rc = OK;
         break;
      default :
         rc = ERROR;
   }
   bm.search_defined = rc;
   return( rc );
}


/*
 * Name:    ask_replace
 * Purpose: Ask user if he wants to (r)place, (s)kip, or (e)xit.
 * Date:    June 5, 1991
 * Returns: TRUE if user wants to replace, ERROR otherwise.
 * Passed:  window:   pointer to current window
 *          finished: TRUE if user pressed ESC or (e)xit.
 */
int  ask_replace( WINDOW *window, int *finished )
{
char line_buff[(MAX_COLS+1)*2]; /* buffer for char and attribute  */
register int c;
int  func;
int  prompt_line;
int  rc;

   prompt_line = window->cline - 1;
   c = 39 - (strlen( find2 ) >> 1);
   save_screen_line( 0, prompt_line, line_buff );
   /*
    * replace skip exit (r/s/e)?
    */
   s_output( find2, prompt_line, c, g_display.message_color );
   do {
      c = getkey( );
      func = getfunc( c );
   } while (c != 'R' && c != 'r' && c != 'S' && c != 's' && c != 'E' && c != 'e'
          && c != ESC  &&  func != AbortCommand);
   restore_screen_line( 0, prompt_line, line_buff );
   switch (c) {
      case 'R' :
      case 'r' :
         rc = OK;
         break;
      case 'E' :
      case 'e' :
         *finished = TRUE;
      case 'S' :
      case 's' :
         rc = ERROR;
         break;
      default :
         *finished = TRUE;
         rc = ERROR;
         break;
   }
   return( rc );
}


/*
 * Name:    ask_wrap_replace
 * Purpose: After a wrap, ask user if he wants to (q)uit or (c)ontine.
 * Date:    June 5, 1991
 * Returns: TRUE if user wants to continue, ERROR otherwise.
 * Passed:  window:   pointer to current window
 *          finished: TRUE if user pressed ESC or (q)uit.
 */
int  ask_wrap_replace( WINDOW *window, int *finished )
{
char line_buff[(MAX_COLS+1)*2]; /* buffer for char and attribute  */
register int c;
int  func;
int  prompt_line;
int  rc;

   prompt_line = window->bottom_line;
   save_screen_line( 0, prompt_line, line_buff );
   /*
    * search has wrapped. continue or quit (c/q)?
    */
   set_prompt( find3, prompt_line );
   do {
      c = getkey( );
      func = getfunc( c );
   } while (c != 'Q'  &&  c != 'q'  &&  c != 'C'  &&  c != 'c' &&
          c != ESC  &&  func != AbortCommand);
   restore_screen_line( 0, prompt_line, line_buff );
   switch (c) {
      case 'C' :
      case 'c' :
         rc = OK;
         break;
      case 'Q' :
      case 'q' :
      default :
         *finished = TRUE;
         rc = ERROR;
         break;
   }
   return( rc );
}


/*
 * Name:    do_replace
 * Purpose: To replace text once match has been found.
 * Date:    June 5, 1991
 * Passed:  window:     pointer to current window
 *          direction:  direction of search
 */
void do_replace( WINDOW *window, int direction )
{
int  old_len;           /* length of original text */
int  new_len;           /* length of replacement text */
int  rcol;
register int net_change;
char *source;           /* source of block move */
char *dest;             /* destination of block move */

   old_len = strlen( g_status.pattern );
   new_len = strlen( g_status.subst );
   net_change = new_len - old_len;
   rcol = window->rcol;

   /*
    * move the text to either make room for the extra replacement text
    *  or to close up the gap left
    */

   g_status.copied = FALSE;
   copy_line( window->ll );
   detab_linebuff( );

   if (net_change != 0) {
      assert( rcol + old_len >= 0);
      assert( net_change <= rcol + old_len );

      source = g_status.line_buff + rcol + old_len;
      dest  = source + net_change;

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

      memmove( dest, source, g_status.line_buff_len - rcol - old_len );
      g_status.line_buff_len += net_change;
   }

   /*
    * insert the replacement text
    */

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

   for (dest=g_status.line_buff+rcol, source=g_status.subst; *source;)
      *dest++ = *source++;

   entab_linebuff( );
   window->file_info->modified = TRUE;
   un_copy_line( window->ll, window, TRUE );
   window->ll->dirty = TRUE;

   if (direction == FORWARD)
      window->rcol += (new_len - 1);

   assert( window->rcol >= 0 );
   show_avail_mem( );
}


/*
 * 作用: 建立并且执行查找操作
 * 参数: window:  当前窗口的指针
 */
int  find_string( WINDOW *window )
{
int  direction;
int  new_string;
char pattern[MAX_COLS];  /* 想要查找的文本 */
long found_line;
long bin_offset;
line_list_ptr ll;
register WINDOW *win;  /* 把文件指针放到一个寄存器中 */
int  rc;
int  old_rcol;
int  rcol;

   switch (g_status.command) {
      case FindForward :
         direction = FORWARD;
         new_string = TRUE;
         break;
      case FindBackward :
         direction = BACKWARD;
         new_string = TRUE;
         break;
      case RepeatFindForward1 :
      case RepeatFindForward2 :
         direction = FORWARD;
         new_string =  bm.search_defined != OK ? TRUE : FALSE;
         break;
      case RepeatFindBackward1 :
      case RepeatFindBackward2 :
         direction = BACKWARD;
         new_string =  bm.search_defined != OK ? TRUE : FALSE;
         break;
      default :
         direction = 0;
         new_string = 0;
         assert( FALSE );
         break;
   }
   win = window;
   entab_linebuff( );
   if (un_copy_line( win->ll, win, TRUE ) == ERROR)
      return( ERROR );

   /*
    * 得到搜索文本,上次的搜索文本做为缺省值
    */
   if (new_string == TRUE) {
      *pattern = '\0';
      if (bm.search_defined == OK) {

         assert( strlen( (char *)bm.pattern ) < MAX_COLS );

         strcpy( pattern, (char *)bm.pattern );
      }

      /*
       * 查找
       */
      if (get_name( find4, win->bottom_line, pattern,
                    g_display.message_color ) != OK  ||  *pattern == '\0')
         return( ERROR );
      bm.search_defined = OK;

      assert( strlen( pattern ) < MAX_COLS );

      strcpy( (char *)bm.pattern, pattern );
      build_boyer_array( );
   }

   rc = OK;
   if (bm.search_defined == OK) {
      old_rcol = win->rcol;
      if (mode.inflate_tabs)
         win->rcol = entab_adjust_rcol( win->ll->line, win->ll->len, win->rcol);
      update_line( win );
      show_search_message( SEARCHING, g_display.diag_color );
      bin_offset = win->bin_offset;
      if (direction == FORWARD) {
         if ((ll = forward_boyer_moore_search( win, &found_line, &rcol )) != NULL) {
            if (g_status.wrapped && g_status.macro_executing)
               rc = ask_wrap_replace( win, &new_string );
            if (rc == OK)
               find_adjust( win, ll, found_line, rcol );
            else
               win->bin_offset = bin_offset;
         }
      } else {
         if ((ll = backward_boyer_moore_search( win, &found_line, &rcol )) != NULL) {
            if (g_status.wrapped && g_status.macro_executing)
               rc = ask_wrap_replace( win, &new_string );
            if (rc == OK)
               find_adjust( win, ll, found_line, rcol );
            else
               win->bin_offset = bin_offset;
         }
      }
      if (g_status.wrapped)
         show_search_message( WRAPPED, g_display.diag_color );
      else
         show_search_message( CLR_SEARCH, g_display.mode_color );
      if (ll == NULL) {
         /*
          * 没有找到
          */
         if (mode.inflate_tabs)
            win->rcol = old_rcol;
         combine_strings( pattern, find5a, (char *)bm.pattern, find5b );
         error( WARNING, win->bottom_line, pattern );
         rc = ERROR;
      }
      show_curl_line( win );
      make_ruler( win );
      show_ruler( win );
   } else {
      /*
       * 没有定义查找模式
       */
      error( WARNING, win->bottom_line, find6 );
      rc = ERROR;
   }
   return( rc );
}


/*
 * Name:    build_boyer_array
 * Purpose: To set up the boyer array for forward and backward searches.
 * Date:    June 5, 1991
 * Notes:   Set up one array for forward searches and another for backward
 *          searches.  If user decides to ignore case then fill in array
 *          with reverse case characters so both upper and lower case
 *          characters are defined.
 */
void build_boyer_array( void )
{

   /*
    * set up for forward search
    */
   if (g_status.command == DefineGrep  ||  g_status.command == RepeatGrep) {

      assert( strlen( (char *)sas_bm.pattern ) + 1 < MAX_COLS );

      memcpy( bm.pattern, sas_bm.pattern, strlen( (char *)sas_bm.pattern ) +1 );
      bm.search_defined = OK;
   }

   if (bm.search_defined == OK) {
      build_forward_skip( &bm );
      bm.forward_md2 = calculate_forward_md2( (char *)bm.pattern,
                                                bm.pattern_length );

      /*
       * set up for backward search
       */
      build_backward_skip( &bm );
      bm.backward_md2 = calculate_backward_md2( (char *)bm.pattern,
                                                  bm.pattern_length );
   }


   /*
    * build an array for search and seize.
    */
   if (sas_bm.search_defined == OK) {
      build_forward_skip( &sas_bm );
      sas_bm.forward_md2 = calculate_forward_md2( (char *)sas_bm.pattern,
                                                    sas_bm.pattern_length );

      /*
       * set up for backward search
       */
      build_backward_skip( &sas_bm );
      sas_bm.backward_md2 = calculate_backward_md2( (char *)sas_bm.pattern,
                                                      sas_bm.pattern_length );
   }
}


/*
 * Name:    build_forward_skip
 * Purpose: build Boyer-Moore forward skip array
 * Date:    October 31, 1992
 * Passed:  bmp:  pointer to Boyer-Moore structure
 * Notes:   build standard Boyer-Moore forward skip array.
 *          Thanks to Tom Waters, twaters@relay.nswc.navy.mil, for finding a
 *           bug in TDE 1.3 when building the ignore skip index array.
 */
void build_forward_skip( boyer_moore_type *bmp )
{
register unsigned char *p;
register int i;

   assert( strlen( (char *)bmp->pattern ) < MAX_COLS );

   i = bmp->pattern_length = (int)strlen( (char *)bmp->pattern );

   /*
    * set skip index of all characters to length of string
    */
   memset( bmp->skip_forward, i, 256 );
   i--;

   /*
    * for each character in string, set the skip index
    */
   for (p=bmp->pattern; i>=0; i--, p++) {

      assert( (char)i < bmp->skip_forward[*p] );

      bmp->skip_forward[*p] = (char)i;
      if (mode.search_case == IGNORE) {
         if (*p >= 'A' && *p <= 'Z') {

            assert( (char)i < bmp->skip_forward[*p+32] );

            bmp->skip_forward[*p+32] = (char)i;
         } else if (*p >= 'a' && *p <= 'z') {

            assert( (char)i < bmp->skip_forward[*p-32] );

            bmp->skip_forward[*p-32] = (char)i;
         }
      }
   }
}


/*
 * Name:    build_backward_skip
 * Purpose: build Boyer-Moore backward skip array
 * Date:    October 31, 1992
 * Passed:  bmp:  pointer to Boyer-Moore structure
 * Notes:   build standard Boyer-Moore backward skip array.
 *          Thanks to Tom Waters, twaters@relay.nswc.navy.mil, for finding a
 *           bug in TDE 1.3 when building the ignore skip index array.
 */
void build_backward_skip( boyer_moore_type *bmp )
{
register unsigned char *p;
register int i;

   i = -bmp->pattern_length;
   memset( bmp->skip_backward, i, 256 );
   i++;
   for (p=bmp->pattern + bmp->pattern_length - 1; i<=0; i++, p--) {

      assert( (char)i > bmp->skip_backward[*p] );

      bmp->skip_backward[*p] = (char)i;
      if (mode.search_case == IGNORE) {
         if (*p >= 'A' && *p <= 'Z') {

            assert( (char)i > bmp->skip_backward[*p+32] );

            bmp->skip_backward[*p+32] = (char)i;
         } else if (*p >= 'a' && *p <= 'z') {

            assert( (char)i > bmp->skip_backward[*p-32] );

            bmp->skip_backward[*p-32] = (char)i;
         }
      }
   }
}


/*
 * Name:    calculate_forward_md2
 * Purpose: Calculate mini delta2 for forward searches
 * Date:    October 31, 1992
 * Passed:  p:  pointer to pattern
 *          len: length of pattern
 * Notes:   Hume and Sunday (see above) demonstrate in their paper that
 *            using a simple shift function on mismatches with BM
 *            gives one of the fastest run times for general text searching.
 *          mini delta2 is, from the end of the string, the first leftmost
 *            occurrence of the rightmost character.  mini delta2 is 1 in
 *            the worst case.  in previous versions of TDE, the shift function
 *            was hard-coded as 1 -- the worst case.  typically, mini delta2
 *            will be the length of the search pattern.
 */
int  calculate_forward_md2( char *p, int len )
{
int  last_c;
register int i;
register int md2;

   md2 = 1;
   i = len - 1;
   last_c = p[i];
   if (mode.search_case == IGNORE) {
      last_c = tolower( last_c );
      for (i--; i >= 0  &&  last_c != tolower( p[i] ); i--)

⌨️ 快捷键说明

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