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 1058310Sache the Free Software Foundation; either version 2, 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, 2158310Sache 59 Temple Place, Suite 330, Boston, MA 02111 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 */ 35119610Sache 3621308Sache#if defined (HAVE_UNISTD_H) 3735486Sache# ifdef _MINIX 3835486Sache# include <sys/types.h> 3935486Sache# endif 4021308Sache# include <unistd.h> 4121308Sache#endif 4221308Sache 4321308Sache#include "history.h" 4421308Sache#include "histlib.h" 4521308Sache 4621308Sache/* The list of alternate characters that can delimit a history search 4721308Sache string. */ 4821308Sachechar *history_search_delimiter_chars = (char *)NULL; 4921308Sache 50119610Sachestatic int history_search_internal PARAMS((const char *, int, int)); 51119610Sache 5221308Sache/* Search the history for STRING, starting at history_offset. 5321308Sache If DIRECTION < 0, then the search is through previous entries, else 5421308Sache through subsequent. If ANCHORED is non-zero, the string must 5521308Sache appear at the beginning of a history line, otherwise, the string 5621308Sache may appear anywhere in the line. If the string is found, then 5721308Sache current_history () is the history entry, and the value of this 5821308Sache function is the offset in the line of that history entry that the 5921308Sache string was found in. Otherwise, nothing is changed, and a -1 is 6021308Sache returned. */ 6121308Sache 6221308Sachestatic int 6321308Sachehistory_search_internal (string, direction, anchored) 6475406Sache const char *string; 6521308Sache int direction, anchored; 6621308Sache{ 6721308Sache register int i, reverse; 6821308Sache register char *line; 6921308Sache register int line_index; 7021308Sache int string_len; 7121308Sache HIST_ENTRY **the_history; /* local */ 7221308Sache 7321308Sache i = history_offset; 7421308Sache reverse = (direction < 0); 7521308Sache 7621308Sache /* Take care of trivial cases first. */ 7721308Sache if (string == 0 || *string == '\0') 7821308Sache return (-1); 7921308Sache 80136644Sache if (!history_length || ((i >= history_length) && !reverse)) 8121308Sache return (-1); 8221308Sache 83136644Sache if (reverse && (i >= history_length)) 84136644Sache i = history_length - 1; 8521308Sache 8621308Sache#define NEXT_LINE() do { if (reverse) i--; else i++; } while (0) 8721308Sache 8821308Sache the_history = history_list (); 8921308Sache string_len = strlen (string); 9021308Sache while (1) 9121308Sache { 9221308Sache /* Search each line in the history list for STRING. */ 9321308Sache 9421308Sache /* At limit for direction? */ 9521308Sache if ((reverse && i < 0) || (!reverse && i == history_length)) 9621308Sache return (-1); 9721308Sache 9821308Sache line = the_history[i]->line; 9921308Sache line_index = strlen (line); 10021308Sache 10121308Sache /* If STRING is longer than line, no match. */ 10221308Sache if (string_len > line_index) 10321308Sache { 10421308Sache NEXT_LINE (); 10521308Sache continue; 10621308Sache } 10721308Sache 10821308Sache /* Handle anchored searches first. */ 10921308Sache if (anchored == ANCHORED_SEARCH) 11021308Sache { 11121308Sache if (STREQN (string, line, string_len)) 11221308Sache { 11321308Sache history_offset = i; 11421308Sache return (0); 11521308Sache } 11621308Sache 11721308Sache NEXT_LINE (); 11821308Sache continue; 11921308Sache } 12021308Sache 12121308Sache /* Do substring search. */ 12221308Sache if (reverse) 12321308Sache { 12421308Sache line_index -= string_len; 12521308Sache 12621308Sache while (line_index >= 0) 12721308Sache { 12821308Sache if (STREQN (string, line + line_index, string_len)) 12921308Sache { 13021308Sache history_offset = i; 13121308Sache return (line_index); 13221308Sache } 13321308Sache line_index--; 13421308Sache } 13521308Sache } 13621308Sache else 13721308Sache { 13821308Sache register int limit; 13921308Sache 14021308Sache limit = line_index - string_len + 1; 14121308Sache line_index = 0; 14221308Sache 14321308Sache while (line_index < limit) 14421308Sache { 14521308Sache if (STREQN (string, line + line_index, string_len)) 14621308Sache { 14721308Sache history_offset = i; 14821308Sache return (line_index); 14921308Sache } 15021308Sache line_index++; 15121308Sache } 15221308Sache } 15321308Sache NEXT_LINE (); 15421308Sache } 15521308Sache} 15621308Sache 15721308Sache/* Do a non-anchored search for STRING through the history in DIRECTION. */ 15821308Sacheint 15921308Sachehistory_search (string, direction) 16075406Sache const char *string; 16121308Sache int direction; 16221308Sache{ 16321308Sache return (history_search_internal (string, direction, NON_ANCHORED_SEARCH)); 16421308Sache} 16521308Sache 16621308Sache/* Do an anchored search for string through the history in DIRECTION. */ 16721308Sacheint 16821308Sachehistory_search_prefix (string, direction) 16975406Sache const char *string; 17021308Sache int direction; 17121308Sache{ 17221308Sache return (history_search_internal (string, direction, ANCHORED_SEARCH)); 17321308Sache} 17421308Sache 17521308Sache/* Search for STRING in the history list. DIR is < 0 for searching 17621308Sache backwards. POS is an absolute index into the history list at 17721308Sache which point to begin searching. */ 17821308Sacheint 17921308Sachehistory_search_pos (string, dir, pos) 18075406Sache const char *string; 18121308Sache int dir, pos; 18221308Sache{ 18321308Sache int ret, old; 18421308Sache 18521308Sache old = where_history (); 18621308Sache history_set_pos (pos); 18721308Sache if (history_search (string, dir) == -1) 18821308Sache { 18921308Sache history_set_pos (old); 19021308Sache return (-1); 19121308Sache } 19221308Sache ret = where_history (); 19321308Sache history_set_pos (old); 19421308Sache return ret; 19521308Sache} 196