histsearch.c revision 21308
121308Sache/* histsearch.c -- searching the history list. */ 221308Sache 321308Sache/* Copyright (C) 1989, 1992 Free Software Foundation, Inc. 421308Sache 521308Sache This file contains the GNU History Library (the Library), a set of 621308Sache routines for managing the text of previously typed lines. 721308Sache 821308Sache The Library is free software; you can redistribute it and/or modify 921308Sache it under the terms of the GNU General Public License as published by 1021308Sache the Free Software Foundation; either version 1, or (at your option) 1121308Sache any later version. 1221308Sache 1321308Sache The Library is distributed in the hope that it will be useful, but 1421308Sache WITHOUT ANY WARRANTY; without even the implied warranty of 1521308Sache MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1621308Sache General Public License for more details. 1721308Sache 1821308Sache The GNU General Public License is often shipped with GNU software, and 1921308Sache is generally kept in a file called COPYING or LICENSE. If you do not 2021308Sache have a copy of the license, write to the Free Software Foundation, 2121308Sache 675 Mass Ave, Cambridge, MA 02139, USA. */ 2221308Sache 2321308Sache#define READLINE_LIBRARY 2421308Sache 2521308Sache#if defined (HAVE_CONFIG_H) 2621308Sache# include <config.h> 2721308Sache#endif 2821308Sache 2921308Sache#include <stdio.h> 3021308Sache#if defined (HAVE_STDLIB_H) 3121308Sache# include <stdlib.h> 3221308Sache#else 3321308Sache# include "ansi_stdlib.h" 3421308Sache#endif /* HAVE_STDLIB_H */ 3521308Sache#if defined (HAVE_UNISTD_H) 3621308Sache# include <unistd.h> 3721308Sache#endif 3821308Sache#if defined (HAVE_STRING_H) 3921308Sache# include <string.h> 4021308Sache#else 4121308Sache# include <strings.h> 4221308Sache#endif /* !HAVE_STRING_H */ 4321308Sache 4421308Sache#include "history.h" 4521308Sache#include "histlib.h" 4621308Sache 4721308Sache/* Variables imported from other history library files. */ 4821308Sacheextern int history_offset; 4921308Sache 5021308Sache/* The list of alternate characters that can delimit a history search 5121308Sache string. */ 5221308Sachechar *history_search_delimiter_chars = (char *)NULL; 5321308Sache 5421308Sache/* Search the history for STRING, starting at history_offset. 5521308Sache If DIRECTION < 0, then the search is through previous entries, else 5621308Sache through subsequent. If ANCHORED is non-zero, the string must 5721308Sache appear at the beginning of a history line, otherwise, the string 5821308Sache may appear anywhere in the line. If the string is found, then 5921308Sache current_history () is the history entry, and the value of this 6021308Sache function is the offset in the line of that history entry that the 6121308Sache string was found in. Otherwise, nothing is changed, and a -1 is 6221308Sache returned. */ 6321308Sache 6421308Sachestatic int 6521308Sachehistory_search_internal (string, direction, anchored) 6621308Sache char *string; 6721308Sache int direction, anchored; 6821308Sache{ 6921308Sache register int i, reverse; 7021308Sache register char *line; 7121308Sache register int line_index; 7221308Sache int string_len; 7321308Sache HIST_ENTRY **the_history; /* local */ 7421308Sache 7521308Sache i = history_offset; 7621308Sache reverse = (direction < 0); 7721308Sache 7821308Sache /* Take care of trivial cases first. */ 7921308Sache if (string == 0 || *string == '\0') 8021308Sache return (-1); 8121308Sache 8221308Sache if (!history_length || ((i == history_length) && !reverse)) 8321308Sache return (-1); 8421308Sache 8521308Sache if (reverse && (i == history_length)) 8621308Sache i--; 8721308Sache 8821308Sache#define NEXT_LINE() do { if (reverse) i--; else i++; } while (0) 8921308Sache 9021308Sache the_history = history_list (); 9121308Sache string_len = strlen (string); 9221308Sache while (1) 9321308Sache { 9421308Sache /* Search each line in the history list for STRING. */ 9521308Sache 9621308Sache /* At limit for direction? */ 9721308Sache if ((reverse && i < 0) || (!reverse && i == history_length)) 9821308Sache return (-1); 9921308Sache 10021308Sache line = the_history[i]->line; 10121308Sache line_index = strlen (line); 10221308Sache 10321308Sache /* If STRING is longer than line, no match. */ 10421308Sache if (string_len > line_index) 10521308Sache { 10621308Sache NEXT_LINE (); 10721308Sache continue; 10821308Sache } 10921308Sache 11021308Sache /* Handle anchored searches first. */ 11121308Sache if (anchored == ANCHORED_SEARCH) 11221308Sache { 11321308Sache if (STREQN (string, line, string_len)) 11421308Sache { 11521308Sache history_offset = i; 11621308Sache return (0); 11721308Sache } 11821308Sache 11921308Sache NEXT_LINE (); 12021308Sache continue; 12121308Sache } 12221308Sache 12321308Sache /* Do substring search. */ 12421308Sache if (reverse) 12521308Sache { 12621308Sache line_index -= string_len; 12721308Sache 12821308Sache while (line_index >= 0) 12921308Sache { 13021308Sache if (STREQN (string, line + line_index, string_len)) 13121308Sache { 13221308Sache history_offset = i; 13321308Sache return (line_index); 13421308Sache } 13521308Sache line_index--; 13621308Sache } 13721308Sache } 13821308Sache else 13921308Sache { 14021308Sache register int limit; 14121308Sache 14221308Sache limit = line_index - string_len + 1; 14321308Sache line_index = 0; 14421308Sache 14521308Sache while (line_index < limit) 14621308Sache { 14721308Sache if (STREQN (string, line + line_index, string_len)) 14821308Sache { 14921308Sache history_offset = i; 15021308Sache return (line_index); 15121308Sache } 15221308Sache line_index++; 15321308Sache } 15421308Sache } 15521308Sache NEXT_LINE (); 15621308Sache } 15721308Sache} 15821308Sache 15921308Sache/* Do a non-anchored search for STRING through the history in DIRECTION. */ 16021308Sacheint 16121308Sachehistory_search (string, direction) 16221308Sache char *string; 16321308Sache int direction; 16421308Sache{ 16521308Sache return (history_search_internal (string, direction, NON_ANCHORED_SEARCH)); 16621308Sache} 16721308Sache 16821308Sache/* Do an anchored search for string through the history in DIRECTION. */ 16921308Sacheint 17021308Sachehistory_search_prefix (string, direction) 17121308Sache char *string; 17221308Sache int direction; 17321308Sache{ 17421308Sache return (history_search_internal (string, direction, ANCHORED_SEARCH)); 17521308Sache} 17621308Sache 17721308Sache/* Search for STRING in the history list. DIR is < 0 for searching 17821308Sache backwards. POS is an absolute index into the history list at 17921308Sache which point to begin searching. */ 18021308Sacheint 18121308Sachehistory_search_pos (string, dir, pos) 18221308Sache char *string; 18321308Sache int dir, pos; 18421308Sache{ 18521308Sache int ret, old; 18621308Sache 18721308Sache old = where_history (); 18821308Sache history_set_pos (pos); 18921308Sache if (history_search (string, dir) == -1) 19021308Sache { 19121308Sache history_set_pos (old); 19221308Sache return (-1); 19321308Sache } 19421308Sache ret = where_history (); 19521308Sache history_set_pos (old); 19621308Sache return ret; 19721308Sache} 198