File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / readline / search.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 01:01:01 2021 UTC (3 years, 3 months ago) by misho
Branches: readline, MAIN
CVS tags: v8_2p0, v8_1p0, HEAD
readline 8.1

    1: /* search.c - code for non-incremental searching in emacs and vi modes. */
    2: 
    3: /* Copyright (C) 1992-2020 Free Software Foundation, Inc.
    4: 
    5:    This file is part of the GNU Readline Library (Readline), a library
    6:    for reading lines of text with interactive input and history editing.      
    7: 
    8:    Readline is free software: you can redistribute it and/or modify
    9:    it under the terms of the GNU General Public License as published by
   10:    the Free Software Foundation, either version 3 of the License, or
   11:    (at your option) any later version.
   12: 
   13:    Readline is distributed in the hope that it will be useful,
   14:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   15:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16:    GNU General Public License for more details.
   17: 
   18:    You should have received a copy of the GNU General Public License
   19:    along with Readline.  If not, see <http://www.gnu.org/licenses/>.
   20: */
   21: 
   22: #define READLINE_LIBRARY
   23: 
   24: #if defined (HAVE_CONFIG_H)
   25: #  include <config.h>
   26: #endif
   27: 
   28: #include <sys/types.h>
   29: #include <stdio.h>
   30: 
   31: #if defined (HAVE_UNISTD_H)
   32: #  include <unistd.h>
   33: #endif
   34: 
   35: #if defined (HAVE_STDLIB_H)
   36: #  include <stdlib.h>
   37: #else
   38: #  include "ansi_stdlib.h"
   39: #endif
   40: 
   41: #include "rldefs.h"
   42: #include "rlmbutil.h"
   43: 
   44: #include "readline.h"
   45: #include "history.h"
   46: #include "histlib.h"
   47: 
   48: #include "rlprivate.h"
   49: #include "xmalloc.h"
   50: 
   51: #ifdef abs
   52: #  undef abs
   53: #endif
   54: #define abs(x)		(((x) >= 0) ? (x) : -(x))
   55: 
   56: _rl_search_cxt *_rl_nscxt = 0;
   57: 
   58: extern HIST_ENTRY *_rl_saved_line_for_history;
   59: 
   60: /* Functions imported from the rest of the library. */
   61: extern void _rl_free_history_entry PARAMS((HIST_ENTRY *));
   62: 
   63: static char *noninc_search_string = (char *) NULL;
   64: static int noninc_history_pos;
   65: 
   66: static char *prev_line_found = (char *) NULL;
   67: 
   68: static int rl_history_search_len;
   69: static int rl_history_search_pos;
   70: static int rl_history_search_flags;
   71: 
   72: static char *history_search_string;
   73: static int history_string_size;
   74: 
   75: static void make_history_line_current PARAMS((HIST_ENTRY *));
   76: static int noninc_search_from_pos PARAMS((char *, int, int, int, int *));
   77: static int noninc_dosearch PARAMS((char *, int, int));
   78: static int noninc_search PARAMS((int, int));
   79: static int rl_history_search_internal PARAMS((int, int));
   80: static void rl_history_search_reinit PARAMS((int));
   81: 
   82: static _rl_search_cxt *_rl_nsearch_init PARAMS((int, int));
   83: static void _rl_nsearch_abort PARAMS((_rl_search_cxt *));
   84: static int _rl_nsearch_dispatch PARAMS((_rl_search_cxt *, int));
   85: 
   86: /* Make the data from the history entry ENTRY be the contents of the
   87:    current line.  This doesn't do anything with rl_point; the caller
   88:    must set it. */
   89: static void
   90: make_history_line_current (HIST_ENTRY *entry)
   91: {
   92:   _rl_replace_text (entry->line, 0, rl_end);
   93:   _rl_fix_point (1);
   94: #if defined (VI_MODE)
   95:   if (rl_editing_mode == vi_mode)
   96:     /* POSIX.2 says that the `U' command doesn't affect the copy of any
   97:        command lines to the edit line.  We're going to implement that by
   98:        making the undo list start after the matching line is copied to the
   99:        current editing buffer. */
  100:     rl_free_undo_list ();
  101: #endif
  102: 
  103:   if (_rl_saved_line_for_history)
  104:     _rl_free_history_entry (_rl_saved_line_for_history);
  105:   _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
  106: }
  107: 
  108: /* Search the history list for STRING starting at absolute history position
  109:    POS.  If STRING begins with `^', the search must match STRING at the
  110:    beginning of a history line, otherwise a full substring match is performed
  111:    for STRING.  DIR < 0 means to search backwards through the history list,
  112:    DIR >= 0 means to search forward. */
  113: static int
  114: noninc_search_from_pos (char *string, int pos, int dir, int flags, int *ncp)
  115: {
  116:   int ret, old, sflags;
  117:   char *s;
  118: 
  119:   if (pos < 0)
  120:     return -1;
  121: 
  122:   old = where_history ();
  123:   if (history_set_pos (pos) == 0)
  124:     return -1;
  125: 
  126:   RL_SETSTATE(RL_STATE_SEARCH);
  127:   /* These functions return the match offset in the line; history_offset gives
  128:      the matching line in the history list */
  129:   if (flags & SF_PATTERN)
  130:     {
  131:       s = string;
  132:       sflags = 0;		/* Non-anchored search */
  133:       if (*s == '^')
  134: 	{
  135: 	  sflags |= ANCHORED_SEARCH;
  136: 	  s++;
  137: 	}
  138:       ret = _hs_history_patsearch (s, dir, sflags);
  139:     }
  140:   else if (*string == '^')
  141:     ret = history_search_prefix (string + 1, dir);
  142:   else
  143:     ret = history_search (string, dir);
  144:   RL_UNSETSTATE(RL_STATE_SEARCH);
  145: 
  146:   if (ncp)
  147:     *ncp = ret;		/* caller will catch -1 to indicate no-op */
  148: 
  149:   if (ret != -1)
  150:     ret = where_history ();
  151: 
  152:   history_set_pos (old);
  153:   return (ret);
  154: }
  155: 
  156: /* Search for a line in the history containing STRING.  If DIR is < 0, the
  157:    search is backwards through previous entries, else through subsequent
  158:    entries.  Returns 1 if the search was successful, 0 otherwise. */
  159: static int
  160: noninc_dosearch (char *string, int dir, int flags)
  161: {
  162:   int oldpos, pos, ind;
  163:   HIST_ENTRY *entry;
  164: 
  165:   if (string == 0 || *string == '\0' || noninc_history_pos < 0)
  166:     {
  167:       rl_ding ();
  168:       return 0;
  169:     }
  170: 
  171:   pos = noninc_search_from_pos (string, noninc_history_pos + dir, dir, flags, &ind);
  172:   if (pos == -1)
  173:     {
  174:       /* Search failed, current history position unchanged. */
  175:       rl_maybe_unsave_line ();
  176:       rl_clear_message ();
  177:       rl_point = 0;
  178:       rl_ding ();
  179:       return 0;
  180:     }
  181: 
  182:   noninc_history_pos = pos;
  183: 
  184:   oldpos = where_history ();
  185:   history_set_pos (noninc_history_pos);
  186:   entry = current_history ();		/* will never be NULL after successful search */
  187:   
  188: #if defined (VI_MODE)
  189:   if (rl_editing_mode != vi_mode)
  190: #endif
  191:     history_set_pos (oldpos);
  192: 
  193:   make_history_line_current (entry);
  194: 
  195:   if (_rl_enable_active_region && ((flags & SF_PATTERN) == 0) && ind > 0 && ind < rl_end)
  196:     {
  197:       rl_point = ind;
  198:       rl_mark = ind + strlen (string);
  199:       if (rl_mark > rl_end)
  200: 	rl_mark = rl_end;	/* can't happen? */
  201:       rl_activate_mark ();
  202:     }
  203:   else
  204:     {  
  205:       rl_point = 0;
  206:       rl_mark = rl_end;
  207:     }
  208: 
  209:   rl_clear_message ();
  210:   return 1;
  211: }
  212: 
  213: static _rl_search_cxt *
  214: _rl_nsearch_init (int dir, int pchar)
  215: {
  216:   _rl_search_cxt *cxt;
  217:   char *p;
  218: 
  219:   cxt = _rl_scxt_alloc (RL_SEARCH_NSEARCH, 0);
  220:   if (dir < 0)
  221:     cxt->sflags |= SF_REVERSE;		/* not strictly needed */
  222: #if defined (VI_MODE)
  223:   if (VI_COMMAND_MODE() && (pchar == '?' || pchar == '/'))
  224:     cxt->sflags |= SF_PATTERN;
  225: #endif
  226: 
  227:   cxt->direction = dir;
  228:   cxt->history_pos = cxt->save_line;
  229: 
  230:   rl_maybe_save_line ();
  231: 
  232:   /* Clear the undo list, since reading the search string should create its
  233:      own undo list, and the whole list will end up being freed when we
  234:      finish reading the search string. */
  235:   rl_undo_list = 0;
  236: 
  237:   /* Use the line buffer to read the search string. */
  238:   rl_line_buffer[0] = 0;
  239:   rl_end = rl_point = 0;
  240: 
  241:   p = _rl_make_prompt_for_search (pchar ? pchar : ':');
  242:   rl_message ("%s", p);
  243:   xfree (p);
  244: 
  245:   RL_SETSTATE(RL_STATE_NSEARCH);
  246: 
  247:   _rl_nscxt = cxt;
  248: 
  249:   return cxt;
  250: }
  251: 
  252: int
  253: _rl_nsearch_cleanup (_rl_search_cxt *cxt, int r)
  254: {
  255:   _rl_scxt_dispose (cxt, 0);
  256:   _rl_nscxt = 0;
  257: 
  258:   RL_UNSETSTATE(RL_STATE_NSEARCH);
  259: 
  260:   return (r != 1);
  261: }
  262: 
  263: static void
  264: _rl_nsearch_abort (_rl_search_cxt *cxt)
  265: {
  266:   rl_maybe_unsave_line ();
  267:   rl_clear_message ();
  268:   rl_point = cxt->save_point;
  269:   rl_mark = cxt->save_mark;
  270:   _rl_fix_point (1);
  271:   rl_restore_prompt ();
  272: 
  273:   RL_UNSETSTATE (RL_STATE_NSEARCH);
  274: }
  275: 
  276: /* Process just-read character C according to search context CXT.  Return -1
  277:    if the caller should abort the search, 0 if we should break out of the
  278:    loop, and 1 if we should continue to read characters. */
  279: static int
  280: _rl_nsearch_dispatch (_rl_search_cxt *cxt, int c)
  281: {
  282:   int n;
  283: 
  284:   if (c < 0)
  285:     c = CTRL ('C');  
  286: 
  287:   switch (c)
  288:     {
  289:     case CTRL('W'):
  290:       rl_unix_word_rubout (1, c);
  291:       break;
  292: 
  293:     case CTRL('U'):
  294:       rl_unix_line_discard (1, c);
  295:       break;
  296: 
  297:     case RETURN:
  298:     case NEWLINE:
  299:       return 0;
  300: 
  301:     case CTRL('H'):
  302:     case RUBOUT:
  303:       if (rl_point == 0)
  304: 	{
  305: 	  _rl_nsearch_abort (cxt);
  306: 	  return -1;
  307: 	}
  308:       _rl_rubout_char (1, c);
  309:       break;
  310: 
  311:     case CTRL('C'):
  312:     case CTRL('G'):
  313:       rl_ding ();
  314:       _rl_nsearch_abort (cxt);
  315:       return -1;
  316: 
  317:     case ESC:
  318:       /* XXX - experimental code to allow users to bracketed-paste into the
  319: 	 search string. Similar code is in isearch.c:_rl_isearch_dispatch().
  320: 	 The difference here is that the bracketed paste sometimes doesn't
  321: 	 paste everything, so checking for the prefix and the suffix in the
  322: 	 input queue doesn't work well. We just have to check to see if the
  323: 	 number of chars in the input queue is enough for the bracketed paste
  324: 	 prefix and hope for the best. */
  325:       if (_rl_enable_bracketed_paste && ((n = _rl_nchars_available ()) >= (BRACK_PASTE_SLEN-1)))
  326: 	{
  327: 	  if (_rl_read_bracketed_paste_prefix (c) == 1)
  328: 	    rl_bracketed_paste_begin (1, c);
  329: 	  else
  330: 	    {
  331: 	      c = rl_read_key ();	/* get the ESC that got pushed back */
  332: 	      _rl_insert_char (1, c);
  333: 	    }
  334:         }
  335:       else
  336:         _rl_insert_char (1, c);
  337:       break;
  338: 
  339:     default:
  340: #if defined (HANDLE_MULTIBYTE)
  341:       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
  342: 	rl_insert_text (cxt->mb);
  343:       else
  344: #endif
  345: 	_rl_insert_char (1, c);
  346:       break;
  347:     }
  348: 
  349:   (*rl_redisplay_function) ();
  350:   rl_deactivate_mark ();
  351:   return 1;
  352: }
  353: 
  354: /* Perform one search according to CXT, using NONINC_SEARCH_STRING.  Return
  355:    -1 if the search should be aborted, any other value means to clean up
  356:    using _rl_nsearch_cleanup ().  Returns 1 if the search was successful,
  357:    0 otherwise. */
  358: static int
  359: _rl_nsearch_dosearch (_rl_search_cxt *cxt)
  360: {
  361:   rl_mark = cxt->save_mark;
  362: 
  363:   /* If rl_point == 0, we want to re-use the previous search string and
  364:      start from the saved history position.  If there's no previous search
  365:      string, punt. */
  366:   if (rl_point == 0)
  367:     {
  368:       if (noninc_search_string == 0)
  369: 	{
  370: 	  rl_ding ();
  371: 	  rl_restore_prompt ();
  372: 	  RL_UNSETSTATE (RL_STATE_NSEARCH);
  373: 	  return -1;
  374: 	}
  375:     }
  376:   else
  377:     {
  378:       /* We want to start the search from the current history position. */
  379:       noninc_history_pos = cxt->save_line;
  380:       FREE (noninc_search_string);
  381:       noninc_search_string = savestring (rl_line_buffer);
  382: 
  383:       /* If we don't want the subsequent undo list generated by the search
  384: 	 matching a history line to include the contents of the search string,
  385: 	 we need to clear rl_line_buffer here.  For now, we just clear the
  386: 	 undo list generated by reading the search string.  (If the search
  387: 	 fails, the old undo list will be restored by rl_maybe_unsave_line.) */
  388:       rl_free_undo_list ();
  389:     }
  390: 
  391:   rl_restore_prompt ();
  392:   return (noninc_dosearch (noninc_search_string, cxt->direction, cxt->sflags&SF_PATTERN));
  393: }
  394: 
  395: /* Search non-interactively through the history list.  DIR < 0 means to
  396:    search backwards through the history of previous commands; otherwise
  397:    the search is for commands subsequent to the current position in the
  398:    history list.  PCHAR is the character to use for prompting when reading
  399:    the search string; if not specified (0), it defaults to `:'. */
  400: static int
  401: noninc_search (int dir, int pchar)
  402: {
  403:   _rl_search_cxt *cxt;
  404:   int c, r;
  405: 
  406:   cxt = _rl_nsearch_init (dir, pchar);
  407: 
  408:   if (RL_ISSTATE (RL_STATE_CALLBACK))
  409:     return (0);
  410: 
  411:   /* Read the search string. */
  412:   r = 0;
  413:   while (1)
  414:     {
  415:       c = _rl_search_getchar (cxt);
  416: 
  417:       if (c < 0)
  418: 	{
  419: 	  _rl_nsearch_abort (cxt);
  420: 	  return 1;
  421: 	}
  422: 	  
  423:       if (c == 0)
  424: 	break;
  425: 
  426:       r = _rl_nsearch_dispatch (cxt, c);
  427:       if (r < 0)
  428:         return 1;
  429:       else if (r == 0)
  430: 	break;        
  431:     }
  432: 
  433:   r = _rl_nsearch_dosearch (cxt);
  434:   return ((r >= 0) ? _rl_nsearch_cleanup (cxt, r) : (r != 1));
  435: }
  436: 
  437: /* Search forward through the history list for a string.  If the vi-mode
  438:    code calls this, KEY will be `?'. */
  439: int
  440: rl_noninc_forward_search (int count, int key)
  441: {
  442:   return noninc_search (1, (key == '?') ? '?' : 0);
  443: }
  444: 
  445: /* Reverse search the history list for a string.  If the vi-mode code
  446:    calls this, KEY will be `/'. */
  447: int
  448: rl_noninc_reverse_search (int count, int key)
  449: {
  450:   return noninc_search (-1, (key == '/') ? '/' : 0);
  451: }
  452: 
  453: /* Search forward through the history list for the last string searched
  454:    for.  If there is no saved search string, abort.  If the vi-mode code
  455:    calls this, KEY will be `N'. */
  456: int
  457: rl_noninc_forward_search_again (int count, int key)
  458: {
  459:   int r;
  460: 
  461:   if (!noninc_search_string)
  462:     {
  463:       rl_ding ();
  464:       return (1);
  465:     }
  466: #if defined (VI_MODE)
  467:   if (VI_COMMAND_MODE() && key == 'N')
  468:     r = noninc_dosearch (noninc_search_string, 1, SF_PATTERN);
  469:   else
  470: #endif
  471:     r = noninc_dosearch (noninc_search_string, 1, 0);
  472:   return (r != 1);
  473: }
  474: 
  475: /* Reverse search in the history list for the last string searched
  476:    for.  If there is no saved search string, abort.  If the vi-mode code
  477:    calls this, KEY will be `n'. */
  478: int
  479: rl_noninc_reverse_search_again (int count, int key)
  480: {
  481:   int r;
  482: 
  483:   if (!noninc_search_string)
  484:     {
  485:       rl_ding ();
  486:       return (1);
  487:     }
  488: #if defined (VI_MODE)
  489:   if (VI_COMMAND_MODE() && key == 'n')
  490:     r = noninc_dosearch (noninc_search_string, -1, SF_PATTERN);
  491:   else
  492: #endif
  493:     r = noninc_dosearch (noninc_search_string, -1, 0);
  494:   return (r != 1);
  495: }
  496: 
  497: #if defined (READLINE_CALLBACKS)
  498: int
  499: _rl_nsearch_callback (_rl_search_cxt *cxt)
  500: {
  501:   int c, r;
  502: 
  503:   c = _rl_search_getchar (cxt);
  504:   if (c <= 0)
  505:     {
  506:       if (c < 0)
  507:         _rl_nsearch_abort (cxt);
  508:       return 1;
  509:     }
  510:   r = _rl_nsearch_dispatch (cxt, c);
  511:   if (r != 0)
  512:     return 1;
  513: 
  514:   r = _rl_nsearch_dosearch (cxt);
  515:   return ((r >= 0) ? _rl_nsearch_cleanup (cxt, r) : (r != 1));
  516: }
  517: #endif
  518:   
  519: static int
  520: rl_history_search_internal (int count, int dir)
  521: {
  522:   HIST_ENTRY *temp;
  523:   int ret, oldpos, newcol;
  524:   char *t;
  525: 
  526:   rl_maybe_save_line ();
  527:   temp = (HIST_ENTRY *)NULL;
  528: 
  529:   /* Search COUNT times through the history for a line matching
  530:      history_search_string.  If history_search_string[0] == '^', the
  531:      line must match from the start; otherwise any substring can match.
  532:      When this loop finishes, TEMP, if non-null, is the history line to
  533:      copy into the line buffer. */
  534:   while (count)
  535:     {
  536:       RL_CHECK_SIGNALS ();
  537:       ret = noninc_search_from_pos (history_search_string, rl_history_search_pos + dir, dir, 0, &newcol);
  538:       if (ret == -1)
  539: 	break;
  540: 
  541:       /* Get the history entry we found. */
  542:       rl_history_search_pos = ret;
  543:       oldpos = where_history ();
  544:       history_set_pos (rl_history_search_pos);
  545:       temp = current_history ();	/* will never be NULL after successful search */
  546:       history_set_pos (oldpos);
  547: 
  548:       /* Don't find multiple instances of the same line. */
  549:       if (prev_line_found && STREQ (prev_line_found, temp->line))
  550:         continue;
  551:       prev_line_found = temp->line;
  552:       count--;
  553:     }
  554: 
  555:   /* If we didn't find anything at all, return. */
  556:   if (temp == 0)
  557:     {
  558:       rl_maybe_unsave_line ();
  559:       rl_ding ();
  560:       /* If you don't want the saved history line (last match) to show up
  561:          in the line buffer after the search fails, change the #if 0 to
  562:          #if 1 */
  563: #if 0
  564:       if (rl_point > rl_history_search_len)
  565:         {
  566:           rl_point = rl_end = rl_history_search_len;
  567:           rl_line_buffer[rl_end] = '\0';
  568:           rl_mark = 0;
  569:         }
  570: #else
  571:       rl_point = rl_history_search_len;	/* rl_maybe_unsave_line changes it */
  572:       rl_mark = rl_end;
  573: #endif
  574:       return 1;
  575:     }
  576: 
  577:   /* Copy the line we found into the current line buffer. */
  578:   make_history_line_current (temp);
  579: 
  580:   /* decide where to put rl_point -- need to change this for pattern search */
  581:   if (rl_history_search_flags & ANCHORED_SEARCH)
  582:     rl_point = rl_history_search_len;	/* easy case */
  583:   else
  584:     {
  585: #if 0
  586:       t = strstr (rl_line_buffer, history_search_string);	/* XXX */
  587:       rl_point = t ? (int)(t - rl_line_buffer) + rl_history_search_len : rl_end;
  588: #else
  589:       rl_point = (newcol >= 0) ? newcol : rl_end;
  590: #endif
  591:     }
  592:   rl_mark = rl_end;
  593: 
  594:   return 0;
  595: }
  596: 
  597: static void
  598: rl_history_search_reinit (int flags)
  599: {
  600:   int sind;
  601: 
  602:   rl_history_search_pos = where_history ();
  603:   rl_history_search_len = rl_point;
  604:   rl_history_search_flags = flags;
  605: 
  606:   prev_line_found = (char *)NULL;
  607:   if (rl_point)
  608:     {
  609:       /* Allocate enough space for anchored and non-anchored searches */
  610:       if (rl_history_search_len >= history_string_size - 2)
  611: 	{
  612: 	  history_string_size = rl_history_search_len + 2;
  613: 	  history_search_string = (char *)xrealloc (history_search_string, history_string_size);
  614: 	}
  615:       sind = 0;
  616:       if (flags & ANCHORED_SEARCH)
  617: 	history_search_string[sind++] = '^';
  618:       strncpy (history_search_string + sind, rl_line_buffer, rl_point);
  619:       history_search_string[rl_point + sind] = '\0';
  620:     }
  621:   _rl_free_saved_history_line ();
  622: }
  623: 
  624: /* Search forward in the history for the string of characters
  625:    from the start of the line to rl_point.  This is a non-incremental
  626:    search.  The search is anchored to the beginning of the history line. */
  627: int
  628: rl_history_search_forward (int count, int ignore)
  629: {
  630:   if (count == 0)
  631:     return (0);
  632: 
  633:   if (rl_last_func != rl_history_search_forward &&
  634:       rl_last_func != rl_history_search_backward)
  635:     rl_history_search_reinit (ANCHORED_SEARCH);
  636: 
  637:   if (rl_history_search_len == 0)
  638:     return (rl_get_next_history (count, ignore));
  639:   return (rl_history_search_internal (abs (count), (count > 0) ? 1 : -1));
  640: }
  641: 
  642: /* Search backward through the history for the string of characters
  643:    from the start of the line to rl_point.  This is a non-incremental
  644:    search. */
  645: int
  646: rl_history_search_backward (int count, int ignore)
  647: {
  648:   if (count == 0)
  649:     return (0);
  650: 
  651:   if (rl_last_func != rl_history_search_forward &&
  652:       rl_last_func != rl_history_search_backward)
  653:     rl_history_search_reinit (ANCHORED_SEARCH);
  654: 
  655:   if (rl_history_search_len == 0)
  656:     return (rl_get_previous_history (count, ignore));
  657:   return (rl_history_search_internal (abs (count), (count > 0) ? -1 : 1));
  658: }
  659: 
  660: /* Search forward in the history for the string of characters
  661:    from the start of the line to rl_point.  This is a non-incremental
  662:    search.  The search succeeds if the search string is present anywhere
  663:    in the history line. */
  664: int
  665: rl_history_substr_search_forward (int count, int ignore)
  666: {
  667:   if (count == 0)
  668:     return (0);
  669: 
  670:   if (rl_last_func != rl_history_substr_search_forward &&
  671:       rl_last_func != rl_history_substr_search_backward)
  672:     rl_history_search_reinit (NON_ANCHORED_SEARCH);
  673: 
  674:   if (rl_history_search_len == 0)
  675:     return (rl_get_next_history (count, ignore));
  676:   return (rl_history_search_internal (abs (count), (count > 0) ? 1 : -1));
  677: }
  678: 
  679: /* Search backward through the history for the string of characters
  680:    from the start of the line to rl_point.  This is a non-incremental
  681:    search. */
  682: int
  683: rl_history_substr_search_backward (int count, int ignore)
  684: {
  685:   if (count == 0)
  686:     return (0);
  687: 
  688:   if (rl_last_func != rl_history_substr_search_forward &&
  689:       rl_last_func != rl_history_substr_search_backward)
  690:     rl_history_search_reinit (NON_ANCHORED_SEARCH);
  691: 
  692:   if (rl_history_search_len == 0)
  693:     return (rl_get_previous_history (count, ignore));
  694:   return (rl_history_search_internal (abs (count), (count > 0) ? -1 : 1));
  695: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>