1*6b445a62SJohn Marino /* histsearch.c -- searching the history list. */ 2*6b445a62SJohn Marino 3*6b445a62SJohn Marino /* Copyright (C) 1989, 1992-2009 Free Software Foundation, Inc. 4*6b445a62SJohn Marino 5*6b445a62SJohn Marino This file contains the GNU History Library (History), a set of 6*6b445a62SJohn Marino routines for managing the text of previously typed lines. 7*6b445a62SJohn Marino 8*6b445a62SJohn Marino History is free software: you can redistribute it and/or modify 9*6b445a62SJohn Marino it under the terms of the GNU General Public License as published by 10*6b445a62SJohn Marino the Free Software Foundation, either version 3 of the License, or 11*6b445a62SJohn Marino (at your option) any later version. 12*6b445a62SJohn Marino 13*6b445a62SJohn Marino History is distributed in the hope that it will be useful, 14*6b445a62SJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of 15*6b445a62SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16*6b445a62SJohn Marino GNU General Public License for more details. 17*6b445a62SJohn Marino 18*6b445a62SJohn Marino You should have received a copy of the GNU General Public License 19*6b445a62SJohn Marino along with History. If not, see <http://www.gnu.org/licenses/>. 20*6b445a62SJohn Marino */ 21*6b445a62SJohn Marino 22*6b445a62SJohn Marino #define READLINE_LIBRARY 23*6b445a62SJohn Marino 24*6b445a62SJohn Marino #if defined (HAVE_CONFIG_H) 25*6b445a62SJohn Marino # include <config.h> 26*6b445a62SJohn Marino #endif 27*6b445a62SJohn Marino 28*6b445a62SJohn Marino #include <stdio.h> 29*6b445a62SJohn Marino #if defined (HAVE_STDLIB_H) 30*6b445a62SJohn Marino # include <stdlib.h> 31*6b445a62SJohn Marino #else 32*6b445a62SJohn Marino # include "ansi_stdlib.h" 33*6b445a62SJohn Marino #endif /* HAVE_STDLIB_H */ 34*6b445a62SJohn Marino 35*6b445a62SJohn Marino #if defined (HAVE_UNISTD_H) 36*6b445a62SJohn Marino # ifdef _MINIX 37*6b445a62SJohn Marino # include <sys/types.h> 38*6b445a62SJohn Marino # endif 39*6b445a62SJohn Marino # include <unistd.h> 40*6b445a62SJohn Marino #endif 41*6b445a62SJohn Marino 42*6b445a62SJohn Marino #include "history.h" 43*6b445a62SJohn Marino #include "histlib.h" 44*6b445a62SJohn Marino 45*6b445a62SJohn Marino /* The list of alternate characters that can delimit a history search 46*6b445a62SJohn Marino string. */ 47*6b445a62SJohn Marino char *history_search_delimiter_chars = (char *)NULL; 48*6b445a62SJohn Marino 49*6b445a62SJohn Marino static int history_search_internal PARAMS((const char *, int, int)); 50*6b445a62SJohn Marino 51*6b445a62SJohn Marino /* Search the history for STRING, starting at history_offset. 52*6b445a62SJohn Marino If DIRECTION < 0, then the search is through previous entries, else 53*6b445a62SJohn Marino through subsequent. If ANCHORED is non-zero, the string must 54*6b445a62SJohn Marino appear at the beginning of a history line, otherwise, the string 55*6b445a62SJohn Marino may appear anywhere in the line. If the string is found, then 56*6b445a62SJohn Marino current_history () is the history entry, and the value of this 57*6b445a62SJohn Marino function is the offset in the line of that history entry that the 58*6b445a62SJohn Marino string was found in. Otherwise, nothing is changed, and a -1 is 59*6b445a62SJohn Marino returned. */ 60*6b445a62SJohn Marino 61*6b445a62SJohn Marino static int 62*6b445a62SJohn Marino history_search_internal (string, direction, anchored) 63*6b445a62SJohn Marino const char *string; 64*6b445a62SJohn Marino int direction, anchored; 65*6b445a62SJohn Marino { 66*6b445a62SJohn Marino register int i, reverse; 67*6b445a62SJohn Marino register char *line; 68*6b445a62SJohn Marino register int line_index; 69*6b445a62SJohn Marino int string_len; 70*6b445a62SJohn Marino HIST_ENTRY **the_history; /* local */ 71*6b445a62SJohn Marino 72*6b445a62SJohn Marino i = history_offset; 73*6b445a62SJohn Marino reverse = (direction < 0); 74*6b445a62SJohn Marino 75*6b445a62SJohn Marino /* Take care of trivial cases first. */ 76*6b445a62SJohn Marino if (string == 0 || *string == '\0') 77*6b445a62SJohn Marino return (-1); 78*6b445a62SJohn Marino 79*6b445a62SJohn Marino if (!history_length || ((i >= history_length) && !reverse)) 80*6b445a62SJohn Marino return (-1); 81*6b445a62SJohn Marino 82*6b445a62SJohn Marino if (reverse && (i >= history_length)) 83*6b445a62SJohn Marino i = history_length - 1; 84*6b445a62SJohn Marino 85*6b445a62SJohn Marino #define NEXT_LINE() do { if (reverse) i--; else i++; } while (0) 86*6b445a62SJohn Marino 87*6b445a62SJohn Marino the_history = history_list (); 88*6b445a62SJohn Marino string_len = strlen (string); 89*6b445a62SJohn Marino while (1) 90*6b445a62SJohn Marino { 91*6b445a62SJohn Marino /* Search each line in the history list for STRING. */ 92*6b445a62SJohn Marino 93*6b445a62SJohn Marino /* At limit for direction? */ 94*6b445a62SJohn Marino if ((reverse && i < 0) || (!reverse && i == history_length)) 95*6b445a62SJohn Marino return (-1); 96*6b445a62SJohn Marino 97*6b445a62SJohn Marino line = the_history[i]->line; 98*6b445a62SJohn Marino line_index = strlen (line); 99*6b445a62SJohn Marino 100*6b445a62SJohn Marino /* If STRING is longer than line, no match. */ 101*6b445a62SJohn Marino if (string_len > line_index) 102*6b445a62SJohn Marino { 103*6b445a62SJohn Marino NEXT_LINE (); 104*6b445a62SJohn Marino continue; 105*6b445a62SJohn Marino } 106*6b445a62SJohn Marino 107*6b445a62SJohn Marino /* Handle anchored searches first. */ 108*6b445a62SJohn Marino if (anchored == ANCHORED_SEARCH) 109*6b445a62SJohn Marino { 110*6b445a62SJohn Marino if (STREQN (string, line, string_len)) 111*6b445a62SJohn Marino { 112*6b445a62SJohn Marino history_offset = i; 113*6b445a62SJohn Marino return (0); 114*6b445a62SJohn Marino } 115*6b445a62SJohn Marino 116*6b445a62SJohn Marino NEXT_LINE (); 117*6b445a62SJohn Marino continue; 118*6b445a62SJohn Marino } 119*6b445a62SJohn Marino 120*6b445a62SJohn Marino /* Do substring search. */ 121*6b445a62SJohn Marino if (reverse) 122*6b445a62SJohn Marino { 123*6b445a62SJohn Marino line_index -= string_len; 124*6b445a62SJohn Marino 125*6b445a62SJohn Marino while (line_index >= 0) 126*6b445a62SJohn Marino { 127*6b445a62SJohn Marino if (STREQN (string, line + line_index, string_len)) 128*6b445a62SJohn Marino { 129*6b445a62SJohn Marino history_offset = i; 130*6b445a62SJohn Marino return (line_index); 131*6b445a62SJohn Marino } 132*6b445a62SJohn Marino line_index--; 133*6b445a62SJohn Marino } 134*6b445a62SJohn Marino } 135*6b445a62SJohn Marino else 136*6b445a62SJohn Marino { 137*6b445a62SJohn Marino register int limit; 138*6b445a62SJohn Marino 139*6b445a62SJohn Marino limit = line_index - string_len + 1; 140*6b445a62SJohn Marino line_index = 0; 141*6b445a62SJohn Marino 142*6b445a62SJohn Marino while (line_index < limit) 143*6b445a62SJohn Marino { 144*6b445a62SJohn Marino if (STREQN (string, line + line_index, string_len)) 145*6b445a62SJohn Marino { 146*6b445a62SJohn Marino history_offset = i; 147*6b445a62SJohn Marino return (line_index); 148*6b445a62SJohn Marino } 149*6b445a62SJohn Marino line_index++; 150*6b445a62SJohn Marino } 151*6b445a62SJohn Marino } 152*6b445a62SJohn Marino NEXT_LINE (); 153*6b445a62SJohn Marino } 154*6b445a62SJohn Marino } 155*6b445a62SJohn Marino 156*6b445a62SJohn Marino /* Do a non-anchored search for STRING through the history in DIRECTION. */ 157*6b445a62SJohn Marino int 158*6b445a62SJohn Marino history_search (string, direction) 159*6b445a62SJohn Marino const char *string; 160*6b445a62SJohn Marino int direction; 161*6b445a62SJohn Marino { 162*6b445a62SJohn Marino return (history_search_internal (string, direction, NON_ANCHORED_SEARCH)); 163*6b445a62SJohn Marino } 164*6b445a62SJohn Marino 165*6b445a62SJohn Marino /* Do an anchored search for string through the history in DIRECTION. */ 166*6b445a62SJohn Marino int 167*6b445a62SJohn Marino history_search_prefix (string, direction) 168*6b445a62SJohn Marino const char *string; 169*6b445a62SJohn Marino int direction; 170*6b445a62SJohn Marino { 171*6b445a62SJohn Marino return (history_search_internal (string, direction, ANCHORED_SEARCH)); 172*6b445a62SJohn Marino } 173*6b445a62SJohn Marino 174*6b445a62SJohn Marino /* Search for STRING in the history list. DIR is < 0 for searching 175*6b445a62SJohn Marino backwards. POS is an absolute index into the history list at 176*6b445a62SJohn Marino which point to begin searching. */ 177*6b445a62SJohn Marino int 178*6b445a62SJohn Marino history_search_pos (string, dir, pos) 179*6b445a62SJohn Marino const char *string; 180*6b445a62SJohn Marino int dir, pos; 181*6b445a62SJohn Marino { 182*6b445a62SJohn Marino int ret, old; 183*6b445a62SJohn Marino 184*6b445a62SJohn Marino old = where_history (); 185*6b445a62SJohn Marino history_set_pos (pos); 186*6b445a62SJohn Marino if (history_search (string, dir) == -1) 187*6b445a62SJohn Marino { 188*6b445a62SJohn Marino history_set_pos (old); 189*6b445a62SJohn Marino return (-1); 190*6b445a62SJohn Marino } 191*6b445a62SJohn Marino ret = where_history (); 192*6b445a62SJohn Marino history_set_pos (old); 193*6b445a62SJohn Marino return ret; 194*6b445a62SJohn Marino } 195