Annotation of embedaddon/readline/search.c, revision 1.1.1.2

1.1       misho       1: /* search.c - code for non-incremental searching in emacs and vi modes. */
                      2: 
1.1.1.2 ! misho       3: /* Copyright (C) 1992-2020 Free Software Foundation, Inc.
1.1       misho       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. */
1.1.1.2 ! misho      61: extern void _rl_free_history_entry PARAMS((HIST_ENTRY *));
1.1       misho      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 *));
1.1.1.2 ! misho      76: static int noninc_search_from_pos PARAMS((char *, int, int, int, int *));
        !            77: static int noninc_dosearch PARAMS((char *, int, int));
1.1       misho      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
1.1.1.2 ! misho      90: make_history_line_current (HIST_ENTRY *entry)
1.1       misho      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
1.1.1.2 ! misho     114: noninc_search_from_pos (char *string, int pos, int dir, int flags, int *ncp)
1.1       misho     115: {
1.1.1.2 ! misho     116:   int ret, old, sflags;
        !           117:   char *s;
1.1       misho     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);
1.1.1.2 ! misho     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 == '^')
1.1       misho     141:     ret = history_search_prefix (string + 1, dir);
                    142:   else
                    143:     ret = history_search (string, dir);
                    144:   RL_UNSETSTATE(RL_STATE_SEARCH);
                    145: 
1.1.1.2 ! misho     146:   if (ncp)
        !           147:     *ncp = ret;                /* caller will catch -1 to indicate no-op */
        !           148: 
1.1       misho     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
1.1.1.2 ! misho     160: noninc_dosearch (char *string, int dir, int flags)
1.1       misho     161: {
1.1.1.2 ! misho     162:   int oldpos, pos, ind;
1.1       misho     163:   HIST_ENTRY *entry;
                    164: 
                    165:   if (string == 0 || *string == '\0' || noninc_history_pos < 0)
                    166:     {
                    167:       rl_ding ();
                    168:       return 0;
                    169:     }
                    170: 
1.1.1.2 ! misho     171:   pos = noninc_search_from_pos (string, noninc_history_pos + dir, dir, flags, &ind);
1.1       misho     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: 
1.1.1.2 ! misho     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:     }
1.1       misho     208: 
                    209:   rl_clear_message ();
                    210:   return 1;
                    211: }
                    212: 
                    213: static _rl_search_cxt *
1.1.1.2 ! misho     214: _rl_nsearch_init (int dir, int pchar)
1.1       misho     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 */
1.1.1.2 ! misho     222: #if defined (VI_MODE)
        !           223:   if (VI_COMMAND_MODE() && (pchar == '?' || pchar == '/'))
        !           224:     cxt->sflags |= SF_PATTERN;
        !           225: #endif
1.1       misho     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: 
1.1.1.2 ! misho     252: int
        !           253: _rl_nsearch_cleanup (_rl_search_cxt *cxt, int r)
1.1       misho     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
1.1.1.2 ! misho     264: _rl_nsearch_abort (_rl_search_cxt *cxt)
1.1       misho     265: {
                    266:   rl_maybe_unsave_line ();
                    267:   rl_clear_message ();
                    268:   rl_point = cxt->save_point;
                    269:   rl_mark = cxt->save_mark;
1.1.1.2 ! misho     270:   _rl_fix_point (1);
1.1       misho     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
1.1.1.2 ! misho     280: _rl_nsearch_dispatch (_rl_search_cxt *cxt, int c)
1.1       misho     281: {
1.1.1.2 ! misho     282:   int n;
        !           283: 
        !           284:   if (c < 0)
        !           285:     c = CTRL ('C');  
        !           286: 
1.1       misho     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: 
1.1.1.2 ! misho     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: 
1.1       misho     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) ();
1.1.1.2 ! misho     350:   rl_deactivate_mark ();
1.1       misho     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
1.1.1.2 ! misho     359: _rl_nsearch_dosearch (_rl_search_cxt *cxt)
1.1       misho     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 ();
1.1.1.2 ! misho     392:   return (noninc_dosearch (noninc_search_string, cxt->direction, cxt->sflags&SF_PATTERN));
1.1       misho     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
1.1.1.2 ! misho     401: noninc_search (int dir, int pchar)
1.1       misho     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: 
1.1.1.2 ! misho     417:       if (c < 0)
        !           418:        {
        !           419:          _rl_nsearch_abort (cxt);
        !           420:          return 1;
        !           421:        }
        !           422:          
1.1       misho     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
1.1.1.2 ! misho     440: rl_noninc_forward_search (int count, int key)
1.1       misho     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
1.1.1.2 ! misho     448: rl_noninc_reverse_search (int count, int key)
1.1       misho     449: {
                    450:   return noninc_search (-1, (key == '/') ? '/' : 0);
                    451: }
                    452: 
                    453: /* Search forward through the history list for the last string searched
1.1.1.2 ! misho     454:    for.  If there is no saved search string, abort.  If the vi-mode code
        !           455:    calls this, KEY will be `N'. */
1.1       misho     456: int
1.1.1.2 ! misho     457: rl_noninc_forward_search_again (int count, int key)
1.1       misho     458: {
                    459:   int r;
                    460: 
                    461:   if (!noninc_search_string)
                    462:     {
                    463:       rl_ding ();
1.1.1.2 ! misho     464:       return (1);
1.1       misho     465:     }
1.1.1.2 ! misho     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);
1.1       misho     472:   return (r != 1);
                    473: }
                    474: 
                    475: /* Reverse search in the history list for the last string searched
1.1.1.2 ! misho     476:    for.  If there is no saved search string, abort.  If the vi-mode code
        !           477:    calls this, KEY will be `n'. */
1.1       misho     478: int
1.1.1.2 ! misho     479: rl_noninc_reverse_search_again (int count, int key)
1.1       misho     480: {
                    481:   int r;
                    482: 
                    483:   if (!noninc_search_string)
                    484:     {
                    485:       rl_ding ();
1.1.1.2 ! misho     486:       return (1);
1.1       misho     487:     }
1.1.1.2 ! misho     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);
1.1       misho     494:   return (r != 1);
                    495: }
                    496: 
                    497: #if defined (READLINE_CALLBACKS)
                    498: int
1.1.1.2 ! misho     499: _rl_nsearch_callback (_rl_search_cxt *cxt)
1.1       misho     500: {
                    501:   int c, r;
                    502: 
                    503:   c = _rl_search_getchar (cxt);
1.1.1.2 ! misho     504:   if (c <= 0)
        !           505:     {
        !           506:       if (c < 0)
        !           507:         _rl_nsearch_abort (cxt);
        !           508:       return 1;
        !           509:     }
1.1       misho     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
1.1.1.2 ! misho     520: rl_history_search_internal (int count, int dir)
1.1       misho     521: {
                    522:   HIST_ENTRY *temp;
1.1.1.2 ! misho     523:   int ret, oldpos, newcol;
1.1       misho     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 ();
1.1.1.2 ! misho     537:       ret = noninc_search_from_pos (history_search_string, rl_history_search_pos + dir, dir, 0, &newcol);
1.1       misho     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: 
1.1.1.2 ! misho     580:   /* decide where to put rl_point -- need to change this for pattern search */
1.1       misho     581:   if (rl_history_search_flags & ANCHORED_SEARCH)
                    582:     rl_point = rl_history_search_len;  /* easy case */
                    583:   else
                    584:     {
1.1.1.2 ! misho     585: #if 0
        !           586:       t = strstr (rl_line_buffer, history_search_string);      /* XXX */
1.1       misho     587:       rl_point = t ? (int)(t - rl_line_buffer) + rl_history_search_len : rl_end;
1.1.1.2 ! misho     588: #else
        !           589:       rl_point = (newcol >= 0) ? newcol : rl_end;
        !           590: #endif
1.1       misho     591:     }
                    592:   rl_mark = rl_end;
                    593: 
                    594:   return 0;
                    595: }
                    596: 
                    597: static void
1.1.1.2 ! misho     598: rl_history_search_reinit (int flags)
1.1       misho     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
1.1.1.2 ! misho     628: rl_history_search_forward (int count, int ignore)
1.1       misho     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
1.1.1.2 ! misho     646: rl_history_search_backward (int count, int ignore)
1.1       misho     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
1.1.1.2 ! misho     665: rl_history_substr_search_forward (int count, int ignore)
1.1       misho     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
1.1.1.2 ! misho     683: rl_history_substr_search_backward (int count, int ignore)
1.1       misho     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>