Annotation of embedaddon/readline/histsearch.c, revision 1.1
1.1 ! misho 1: /* histsearch.c -- searching the history list. */
! 2:
! 3: /* Copyright (C) 1989, 1992-2009 Free Software Foundation, Inc.
! 4:
! 5: This file contains the GNU History Library (History), a set of
! 6: routines for managing the text of previously typed lines.
! 7:
! 8: History 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: History 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 History. 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 <stdio.h>
! 29: #if defined (HAVE_STDLIB_H)
! 30: # include <stdlib.h>
! 31: #else
! 32: # include "ansi_stdlib.h"
! 33: #endif /* HAVE_STDLIB_H */
! 34:
! 35: #if defined (HAVE_UNISTD_H)
! 36: # ifdef _MINIX
! 37: # include <sys/types.h>
! 38: # endif
! 39: # include <unistd.h>
! 40: #endif
! 41:
! 42: #include "history.h"
! 43: #include "histlib.h"
! 44:
! 45: /* The list of alternate characters that can delimit a history search
! 46: string. */
! 47: char *history_search_delimiter_chars = (char *)NULL;
! 48:
! 49: static int history_search_internal PARAMS((const char *, int, int));
! 50:
! 51: /* Search the history for STRING, starting at history_offset.
! 52: If DIRECTION < 0, then the search is through previous entries, else
! 53: through subsequent. If ANCHORED is non-zero, the string must
! 54: appear at the beginning of a history line, otherwise, the string
! 55: may appear anywhere in the line. If the string is found, then
! 56: current_history () is the history entry, and the value of this
! 57: function is the offset in the line of that history entry that the
! 58: string was found in. Otherwise, nothing is changed, and a -1 is
! 59: returned. */
! 60:
! 61: static int
! 62: history_search_internal (string, direction, anchored)
! 63: const char *string;
! 64: int direction, anchored;
! 65: {
! 66: register int i, reverse;
! 67: register char *line;
! 68: register int line_index;
! 69: int string_len;
! 70: HIST_ENTRY **the_history; /* local */
! 71:
! 72: i = history_offset;
! 73: reverse = (direction < 0);
! 74:
! 75: /* Take care of trivial cases first. */
! 76: if (string == 0 || *string == '\0')
! 77: return (-1);
! 78:
! 79: if (!history_length || ((i >= history_length) && !reverse))
! 80: return (-1);
! 81:
! 82: if (reverse && (i >= history_length))
! 83: i = history_length - 1;
! 84:
! 85: #define NEXT_LINE() do { if (reverse) i--; else i++; } while (0)
! 86:
! 87: the_history = history_list ();
! 88: string_len = strlen (string);
! 89: while (1)
! 90: {
! 91: /* Search each line in the history list for STRING. */
! 92:
! 93: /* At limit for direction? */
! 94: if ((reverse && i < 0) || (!reverse && i == history_length))
! 95: return (-1);
! 96:
! 97: line = the_history[i]->line;
! 98: line_index = strlen (line);
! 99:
! 100: /* If STRING is longer than line, no match. */
! 101: if (string_len > line_index)
! 102: {
! 103: NEXT_LINE ();
! 104: continue;
! 105: }
! 106:
! 107: /* Handle anchored searches first. */
! 108: if (anchored == ANCHORED_SEARCH)
! 109: {
! 110: if (STREQN (string, line, string_len))
! 111: {
! 112: history_offset = i;
! 113: return (0);
! 114: }
! 115:
! 116: NEXT_LINE ();
! 117: continue;
! 118: }
! 119:
! 120: /* Do substring search. */
! 121: if (reverse)
! 122: {
! 123: line_index -= string_len;
! 124:
! 125: while (line_index >= 0)
! 126: {
! 127: if (STREQN (string, line + line_index, string_len))
! 128: {
! 129: history_offset = i;
! 130: return (line_index);
! 131: }
! 132: line_index--;
! 133: }
! 134: }
! 135: else
! 136: {
! 137: register int limit;
! 138:
! 139: limit = line_index - string_len + 1;
! 140: line_index = 0;
! 141:
! 142: while (line_index < limit)
! 143: {
! 144: if (STREQN (string, line + line_index, string_len))
! 145: {
! 146: history_offset = i;
! 147: return (line_index);
! 148: }
! 149: line_index++;
! 150: }
! 151: }
! 152: NEXT_LINE ();
! 153: }
! 154: }
! 155:
! 156: /* Do a non-anchored search for STRING through the history in DIRECTION. */
! 157: int
! 158: history_search (string, direction)
! 159: const char *string;
! 160: int direction;
! 161: {
! 162: return (history_search_internal (string, direction, NON_ANCHORED_SEARCH));
! 163: }
! 164:
! 165: /* Do an anchored search for string through the history in DIRECTION. */
! 166: int
! 167: history_search_prefix (string, direction)
! 168: const char *string;
! 169: int direction;
! 170: {
! 171: return (history_search_internal (string, direction, ANCHORED_SEARCH));
! 172: }
! 173:
! 174: /* Search for STRING in the history list. DIR is < 0 for searching
! 175: backwards. POS is an absolute index into the history list at
! 176: which point to begin searching. */
! 177: int
! 178: history_search_pos (string, dir, pos)
! 179: const char *string;
! 180: int dir, pos;
! 181: {
! 182: int ret, old;
! 183:
! 184: old = where_history ();
! 185: history_set_pos (pos);
! 186: if (history_search (string, dir) == -1)
! 187: {
! 188: history_set_pos (old);
! 189: return (-1);
! 190: }
! 191: ret = where_history ();
! 192: history_set_pos (old);
! 193: return ret;
! 194: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>