/* histsearch.c -- searching the history list. */

/* Copyright (C) 1989, 1992-2009 Free Software Foundation, Inc.

   This file contains the GNU History Library (History), a set of
   routines for managing the text of previously typed lines.

   History is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   History is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with History.  If not, see <http://www.gnu.org/licenses/>.
*/

#define READLINE_LIBRARY

#if defined (HAVE_CONFIG_H)
#  include <config.h>
#endif

#include <stdio.h>
#if defined (HAVE_STDLIB_H)
#  include <stdlib.h>
#else
#  include "ansi_stdlib.h"
#endif /* HAVE_STDLIB_H */

#if defined (HAVE_UNISTD_H)
#  ifdef _MINIX
#    include <sys/types.h>
#  endif
#  include <unistd.h>
#endif

#include "history.h"
#include "histlib.h"

/* The list of alternate characters that can delimit a history search
   string. */
char *history_search_delimiter_chars = (char *)NULL;

static int history_search_internal PARAMS((const char *, int, int));

/* Search the history for STRING, starting at history_offset.
   If DIRECTION < 0, then the search is through previous entries, else
   through subsequent.  If ANCHORED is non-zero, the string must
   appear at the beginning of a history line, otherwise, the string
   may appear anywhere in the line.  If the string is found, then
   current_history () is the history entry, and the value of this
   function is the offset in the line of that history entry that the
   string was found in.  Otherwise, nothing is changed, and a -1 is
   returned. */

static int
history_search_internal (string, direction, anchored)
     const char *string;
     int direction, anchored;
{
  register int i, reverse;
  register char *line;
  register int line_index;
  int string_len;
  HIST_ENTRY **the_history; 	/* local */

  i = history_offset;
  reverse = (direction < 0);

  /* Take care of trivial cases first. */
  if (string == 0 || *string == '\0')
    return (-1);

  if (!history_length || ((i >= history_length) && !reverse))
    return (-1);

  if (reverse && (i >= history_length))
    i = history_length - 1;

#define NEXT_LINE() do { if (reverse) i--; else i++; } while (0)

  the_history = history_list ();
  string_len = strlen (string);
  while (1)
    {
      /* Search each line in the history list for STRING. */

      /* At limit for direction? */
      if ((reverse && i < 0) || (!reverse && i == history_length))
	return (-1);

      line = the_history[i]->line;
      line_index = strlen (line);

      /* If STRING is longer than line, no match. */
      if (string_len > line_index)
	{
	  NEXT_LINE ();
	  continue;
	}

      /* Handle anchored searches first. */
      if (anchored == ANCHORED_SEARCH)
	{
	  if (STREQN (string, line, string_len))
	    {
	      history_offset = i;
	      return (0);
	    }

	  NEXT_LINE ();
	  continue;
	}

      /* Do substring search. */
      if (reverse)
	{
	  line_index -= string_len;

	  while (line_index >= 0)
	    {
	      if (STREQN (string, line + line_index, string_len))
		{
		  history_offset = i;
		  return (line_index);
		}
	      line_index--;
	    }
	}
      else
	{
	  register int limit;

	  limit = line_index - string_len + 1;
	  line_index = 0;

	  while (line_index < limit)
	    {
	      if (STREQN (string, line + line_index, string_len))
		{
		  history_offset = i;
		  return (line_index);
		}
	      line_index++;
	    }
	}
      NEXT_LINE ();
    }
}

/* Do a non-anchored search for STRING through the history in DIRECTION. */
int
history_search (string, direction)
     const char *string;
     int direction;
{
  return (history_search_internal (string, direction, NON_ANCHORED_SEARCH));
}

/* Do an anchored search for string through the history in DIRECTION. */
int
history_search_prefix (string, direction)
     const char *string;
     int direction;
{
  return (history_search_internal (string, direction, ANCHORED_SEARCH));
}

/* Search for STRING in the history list.  DIR is < 0 for searching
   backwards.  POS is an absolute index into the history list at
   which point to begin searching. */
int
history_search_pos (string, dir, pos)
     const char *string;
     int dir, pos;
{
  int ret, old;

  old = where_history ();
  history_set_pos (pos);
  if (history_search (string, dir) == -1)
    {
      history_set_pos (old);
      return (-1);
    }
  ret = where_history ();
  history_set_pos (old);
  return ret;
}
