1136644Sache/* history.c -- standalone history library */
221308Sache
3157184Sache/* Copyright (C) 1989-2005 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/* The goal is to make the implementation transparent, so that you
2421308Sache   don't have to know what data types are used, just what functions
2521308Sache   you can call.  I think I have done that. */
2621308Sache#define READLINE_LIBRARY
2721308Sache
2821308Sache#if defined (HAVE_CONFIG_H)
2921308Sache#  include <config.h>
3021308Sache#endif
3121308Sache
3221308Sache#include <stdio.h>
3321308Sache
3421308Sache#if defined (HAVE_STDLIB_H)
3521308Sache#  include <stdlib.h>
3621308Sache#else
3721308Sache#  include "ansi_stdlib.h"
3821308Sache#endif /* HAVE_STDLIB_H */
3921308Sache
4021308Sache#if defined (HAVE_UNISTD_H)
4135486Sache#  ifdef _MINIX
4235486Sache#    include <sys/types.h>
4335486Sache#  endif
4421308Sache#  include <unistd.h>
4521308Sache#endif
4621308Sache
4721308Sache#include "history.h"
4821308Sache#include "histlib.h"
4921308Sache
5058310Sache#include "xmalloc.h"
5121308Sache
5221308Sache/* The number of slots to increase the_history by. */
5321308Sache#define DEFAULT_HISTORY_GROW_SIZE 50
5421308Sache
55136644Sachestatic char *hist_inittime PARAMS((void));
56136644Sache
5721308Sache/* **************************************************************** */
5821308Sache/*								    */
5921308Sache/*			History Functions			    */
6021308Sache/*								    */
6121308Sache/* **************************************************************** */
6221308Sache
6321308Sache/* An array of HIST_ENTRY.  This is where we store the history. */
6421308Sachestatic HIST_ENTRY **the_history = (HIST_ENTRY **)NULL;
6521308Sache
6621308Sache/* Non-zero means that we have enforced a limit on the amount of
6721308Sache   history that we save. */
6821308Sachestatic int history_stifled;
6921308Sache
70119610Sache/* The current number of slots allocated to the input_history. */
71119610Sachestatic int history_size;
72119610Sache
7321308Sache/* If HISTORY_STIFLED is non-zero, then this is the maximum number of
7421308Sache   entries to remember. */
7575406Sacheint history_max_entries;
7675406Sacheint max_input_history;	/* backwards compatibility */
7721308Sache
7821308Sache/* The current location of the interactive history pointer.  Just makes
7921308Sache   life easier for outside callers. */
8021308Sacheint history_offset;
8121308Sache
8221308Sache/* The number of strings currently stored in the history list. */
8321308Sacheint history_length;
8421308Sache
8521308Sache/* The logical `base' of the history array.  It defaults to 1. */
8621308Sacheint history_base = 1;
8721308Sache
8821308Sache/* Return the current HISTORY_STATE of the history. */
8921308SacheHISTORY_STATE *
9021308Sachehistory_get_history_state ()
9121308Sache{
9221308Sache  HISTORY_STATE *state;
9321308Sache
9421308Sache  state = (HISTORY_STATE *)xmalloc (sizeof (HISTORY_STATE));
9521308Sache  state->entries = the_history;
9621308Sache  state->offset = history_offset;
9721308Sache  state->length = history_length;
9821308Sache  state->size = history_size;
9921308Sache  state->flags = 0;
10021308Sache  if (history_stifled)
10121308Sache    state->flags |= HS_STIFLED;
10221308Sache
10321308Sache  return (state);
10421308Sache}
10521308Sache
10621308Sache/* Set the state of the current history array to STATE. */
10721308Sachevoid
10821308Sachehistory_set_history_state (state)
10921308Sache     HISTORY_STATE *state;
11021308Sache{
11121308Sache  the_history = state->entries;
11221308Sache  history_offset = state->offset;
11321308Sache  history_length = state->length;
11421308Sache  history_size = state->size;
11521308Sache  if (state->flags & HS_STIFLED)
11621308Sache    history_stifled = 1;
11721308Sache}
11821308Sache
11921308Sache/* Begin a session in which the history functions might be used.  This
12021308Sache   initializes interactive variables. */
12121308Sachevoid
12221308Sacheusing_history ()
12321308Sache{
12421308Sache  history_offset = history_length;
12521308Sache}
12621308Sache
12721308Sache/* Return the number of bytes that the primary history entries are using.
128136644Sache   This just adds up the lengths of the_history->lines and the associated
129136644Sache   timestamps. */
13021308Sacheint
13121308Sachehistory_total_bytes ()
13221308Sache{
13321308Sache  register int i, result;
13421308Sache
13575406Sache  for (i = result = 0; the_history && the_history[i]; i++)
136136644Sache    result += HISTENT_BYTES (the_history[i]);
13721308Sache
13821308Sache  return (result);
13921308Sache}
14021308Sache
14121308Sache/* Returns the magic number which says what history element we are
14221308Sache   looking at now.  In this implementation, it returns history_offset. */
14321308Sacheint
14421308Sachewhere_history ()
14521308Sache{
14621308Sache  return (history_offset);
14721308Sache}
14821308Sache
14921308Sache/* Make the current history item be the one at POS, an absolute index.
15021308Sache   Returns zero if POS is out of range, else non-zero. */
15121308Sacheint
15221308Sachehistory_set_pos (pos)
15321308Sache     int pos;
15421308Sache{
15521308Sache  if (pos > history_length || pos < 0 || !the_history)
15621308Sache    return (0);
15721308Sache  history_offset = pos;
15821308Sache  return (1);
15921308Sache}
16021308Sache
16121308Sache/* Return the current history array.  The caller has to be carefull, since this
16221308Sache   is the actual array of data, and could be bashed or made corrupt easily.
16321308Sache   The array is terminated with a NULL pointer. */
16421308SacheHIST_ENTRY **
16521308Sachehistory_list ()
16621308Sache{
16721308Sache  return (the_history);
16821308Sache}
16921308Sache
17021308Sache/* Return the history entry at the current position, as determined by
17121308Sache   history_offset.  If there is no entry there, return a NULL pointer. */
17221308SacheHIST_ENTRY *
17321308Sachecurrent_history ()
17421308Sache{
17521308Sache  return ((history_offset == history_length) || the_history == 0)
17621308Sache		? (HIST_ENTRY *)NULL
17721308Sache		: the_history[history_offset];
17821308Sache}
17921308Sache
18021308Sache/* Back up history_offset to the previous history entry, and return
18121308Sache   a pointer to that entry.  If there is no previous entry then return
18221308Sache   a NULL pointer. */
18321308SacheHIST_ENTRY *
18421308Sacheprevious_history ()
18521308Sache{
18621308Sache  return history_offset ? the_history[--history_offset] : (HIST_ENTRY *)NULL;
18721308Sache}
18821308Sache
18921308Sache/* Move history_offset forward to the next history entry, and return
19021308Sache   a pointer to that entry.  If there is no next entry then return a
19121308Sache   NULL pointer. */
19221308SacheHIST_ENTRY *
19321308Sachenext_history ()
19421308Sache{
19521308Sache  return (history_offset == history_length) ? (HIST_ENTRY *)NULL : the_history[++history_offset];
19621308Sache}
19721308Sache
19821308Sache/* Return the history entry which is logically at OFFSET in the history array.
19921308Sache   OFFSET is relative to history_base. */
20021308SacheHIST_ENTRY *
20121308Sachehistory_get (offset)
20221308Sache     int offset;
20321308Sache{
20421308Sache  int local_index;
20521308Sache
20621308Sache  local_index = offset - history_base;
207157184Sache  return (local_index >= history_length || local_index < 0 || the_history == 0)
20821308Sache		? (HIST_ENTRY *)NULL
20921308Sache		: the_history[local_index];
21021308Sache}
21121308Sache
212165670SacheHIST_ENTRY *
213165670Sachealloc_history_entry (string, ts)
214165670Sache     char *string;
215165670Sache     char *ts;
216165670Sache{
217165670Sache  HIST_ENTRY *temp;
218165670Sache
219165670Sache  temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
220165670Sache
221165670Sache  temp->line = string ? savestring (string) : string;
222165670Sache  temp->data = (char *)NULL;
223165670Sache  temp->timestamp = ts;
224165670Sache
225165670Sache  return temp;
226165670Sache}
227165670Sache
228136644Sachetime_t
229136644Sachehistory_get_time (hist)
230136644Sache     HIST_ENTRY *hist;
231136644Sache{
232136644Sache  char *ts;
233136644Sache  time_t t;
234136644Sache
235136644Sache  if (hist == 0 || hist->timestamp == 0)
236136644Sache    return 0;
237136644Sache  ts = hist->timestamp;
238136644Sache  if (ts[0] != history_comment_char)
239136644Sache    return 0;
240136644Sache  t = (time_t) atol (ts + 1);		/* XXX - should use strtol() here */
241136644Sache  return t;
242136644Sache}
243136644Sache
244136644Sachestatic char *
245136644Sachehist_inittime ()
246136644Sache{
247136644Sache  time_t t;
248136644Sache  char ts[64], *ret;
249136644Sache
250136644Sache  t = (time_t) time ((time_t *)0);
251136644Sache#if defined (HAVE_VSNPRINTF)		/* assume snprintf if vsnprintf exists */
252136644Sache  snprintf (ts, sizeof (ts) - 1, "X%lu", (unsigned long) t);
253136644Sache#else
254136644Sache  sprintf (ts, "X%lu", (unsigned long) t);
255136644Sache#endif
256136644Sache  ret = savestring (ts);
257136644Sache  ret[0] = history_comment_char;
258136644Sache
259136644Sache  return ret;
260136644Sache}
261136644Sache
26221308Sache/* Place STRING at the end of the history list.  The data field
26321308Sache   is  set to NULL. */
26421308Sachevoid
26521308Sacheadd_history (string)
26675406Sache     const char *string;
26721308Sache{
26821308Sache  HIST_ENTRY *temp;
26921308Sache
27075406Sache  if (history_stifled && (history_length == history_max_entries))
27121308Sache    {
27221308Sache      register int i;
27321308Sache
27421308Sache      /* If the history is stifled, and history_length is zero,
27575406Sache	 and it equals history_max_entries, we don't save items. */
27621308Sache      if (history_length == 0)
27721308Sache	return;
27821308Sache
27921308Sache      /* If there is something in the slot, then remove it. */
28021308Sache      if (the_history[0])
281136644Sache	(void) free_history_entry (the_history[0]);
28221308Sache
28321308Sache      /* Copy the rest of the entries, moving down one slot. */
28421308Sache      for (i = 0; i < history_length; i++)
28521308Sache	the_history[i] = the_history[i + 1];
28621308Sache
28721308Sache      history_base++;
28821308Sache    }
28921308Sache  else
29021308Sache    {
29121308Sache      if (history_size == 0)
29221308Sache	{
29321308Sache	  history_size = DEFAULT_HISTORY_GROW_SIZE;
29421308Sache	  the_history = (HIST_ENTRY **)xmalloc (history_size * sizeof (HIST_ENTRY *));
29521308Sache	  history_length = 1;
29621308Sache	}
29721308Sache      else
29821308Sache	{
29921308Sache	  if (history_length == (history_size - 1))
30021308Sache	    {
30121308Sache	      history_size += DEFAULT_HISTORY_GROW_SIZE;
30221308Sache	      the_history = (HIST_ENTRY **)
30321308Sache		xrealloc (the_history, history_size * sizeof (HIST_ENTRY *));
30421308Sache	    }
30521308Sache	  history_length++;
30621308Sache	}
30721308Sache    }
30821308Sache
309257366Ssbruno  temp = alloc_history_entry ((char *)string, hist_inittime ());
31021308Sache
31121308Sache  the_history[history_length] = (HIST_ENTRY *)NULL;
31221308Sache  the_history[history_length - 1] = temp;
31321308Sache}
31421308Sache
315136644Sache/* Change the time stamp of the most recent history entry to STRING. */
316136644Sachevoid
317136644Sacheadd_history_time (string)
318136644Sache     const char *string;
319136644Sache{
320136644Sache  HIST_ENTRY *hs;
321136644Sache
322136644Sache  hs = the_history[history_length - 1];
323136644Sache  FREE (hs->timestamp);
324136644Sache  hs->timestamp = savestring (string);
325136644Sache}
326136644Sache
327136644Sache/* Free HIST and return the data so the calling application can free it
328136644Sache   if necessary and desired. */
329136644Sachehistdata_t
330136644Sachefree_history_entry (hist)
331136644Sache     HIST_ENTRY *hist;
332136644Sache{
333136644Sache  histdata_t x;
334136644Sache
335136644Sache  if (hist == 0)
336136644Sache    return ((histdata_t) 0);
337136644Sache  FREE (hist->line);
338136644Sache  FREE (hist->timestamp);
339136644Sache  x = hist->data;
340136644Sache  free (hist);
341136644Sache  return (x);
342136644Sache}
343165670Sache
344165670SacheHIST_ENTRY *
345165670Sachecopy_history_entry (hist)
346165670Sache     HIST_ENTRY *hist;
347165670Sache{
348165670Sache  HIST_ENTRY *ret;
349165670Sache  char *ts;
350165670Sache
351165670Sache  if (hist == 0)
352165670Sache    return hist;
353165670Sache
354165670Sache  ret = alloc_history_entry (hist->line, (char *)NULL);
355165670Sache
356165670Sache  ts = hist->timestamp ? savestring (hist->timestamp) : hist->timestamp;
357165670Sache  ret->timestamp = ts;
358165670Sache
359165670Sache  ret->data = hist->data;
360165670Sache
361165670Sache  return ret;
362165670Sache}
363136644Sache
36421308Sache/* Make the history entry at WHICH have LINE and DATA.  This returns
36521308Sache   the old entry so you can dispose of the data.  In the case of an
36621308Sache   invalid WHICH, a NULL pointer is returned. */
36721308SacheHIST_ENTRY *
36821308Sachereplace_history_entry (which, line, data)
36921308Sache     int which;
37075406Sache     const char *line;
37147558Sache     histdata_t data;
37221308Sache{
37375406Sache  HIST_ENTRY *temp, *old_value;
37421308Sache
375157184Sache  if (which < 0 || which >= history_length)
37621308Sache    return ((HIST_ENTRY *)NULL);
37721308Sache
37875406Sache  temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
37921308Sache  old_value = the_history[which];
38021308Sache
38121308Sache  temp->line = savestring (line);
38221308Sache  temp->data = data;
383136644Sache  temp->timestamp = savestring (old_value->timestamp);
38421308Sache  the_history[which] = temp;
38521308Sache
38621308Sache  return (old_value);
38721308Sache}
38821308Sache
389165670Sache/* Replace the DATA in the specified history entries, replacing OLD with
390165670Sache   NEW.  WHICH says which one(s) to replace:  WHICH == -1 means to replace
391165670Sache   all of the history entries where entry->data == OLD; WHICH == -2 means
392165670Sache   to replace the `newest' history entry where entry->data == OLD; and
393165670Sache   WHICH >= 0 means to replace that particular history entry's data, as
394165670Sache   long as it matches OLD. */
395165670Sachevoid
396165670Sachereplace_history_data (which,old, new)
397165670Sache     int which;
398165670Sache     histdata_t *old, *new;
399165670Sache{
400165670Sache  HIST_ENTRY *entry;
401165670Sache  register int i, last;
402165670Sache
403165670Sache  if (which < -2 || which >= history_length || history_length == 0 || the_history == 0)
404165670Sache    return;
405165670Sache
406165670Sache  if (which >= 0)
407165670Sache    {
408165670Sache      entry = the_history[which];
409165670Sache      if (entry && entry->data == old)
410165670Sache	entry->data = new;
411165670Sache      return;
412165670Sache    }
413165670Sache
414165670Sache  last = -1;
415165670Sache  for (i = 0; i < history_length; i++)
416165670Sache    {
417165670Sache      entry = the_history[i];
418165670Sache      if (entry == 0)
419165670Sache	continue;
420165670Sache      if (entry->data == old)
421165670Sache	{
422165670Sache	  last = i;
423165670Sache	  if (which == -1)
424165670Sache	    entry->data = new;
425165670Sache	}
426165670Sache    }
427165670Sache  if (which == -2 && last >= 0)
428165670Sache    {
429165670Sache      entry = the_history[last];
430165670Sache      entry->data = new;	/* XXX - we don't check entry->old */
431165670Sache    }
432165670Sache}
433165670Sache
43421308Sache/* Remove history element WHICH from the history.  The removed
43521308Sache   element is returned to you so you can free the line, data,
43621308Sache   and containing structure. */
43721308SacheHIST_ENTRY *
43821308Sacheremove_history (which)
43921308Sache     int which;
44021308Sache{
44121308Sache  HIST_ENTRY *return_value;
44275406Sache  register int i;
44321308Sache
444157184Sache  if (which < 0 || which >= history_length || history_length ==  0 || the_history == 0)
445157184Sache    return ((HIST_ENTRY *)NULL);
44621308Sache
447157184Sache  return_value = the_history[which];
44821308Sache
449157184Sache  for (i = which; i < history_length; i++)
450157184Sache    the_history[i] = the_history[i + 1];
45121308Sache
452157184Sache  history_length--;
453157184Sache
45421308Sache  return (return_value);
45521308Sache}
45621308Sache
45721308Sache/* Stifle the history list, remembering only MAX number of lines. */
45821308Sachevoid
45921308Sachestifle_history (max)
46021308Sache     int max;
46121308Sache{
46275406Sache  register int i, j;
46375406Sache
46421308Sache  if (max < 0)
46521308Sache    max = 0;
46621308Sache
46721308Sache  if (history_length > max)
46821308Sache    {
46921308Sache      /* This loses because we cannot free the data. */
47021308Sache      for (i = 0, j = history_length - max; i < j; i++)
471136644Sache	free_history_entry (the_history[i]);
47221308Sache
47321308Sache      history_base = i;
47421308Sache      for (j = 0, i = history_length - max; j < max; i++, j++)
47521308Sache	the_history[j] = the_history[i];
47621308Sache      the_history[j] = (HIST_ENTRY *)NULL;
47721308Sache      history_length = j;
47821308Sache    }
47921308Sache
48021308Sache  history_stifled = 1;
48175406Sache  max_input_history = history_max_entries = max;
48221308Sache}
48321308Sache
484119610Sache/* Stop stifling the history.  This returns the previous maximum
485119610Sache   number of history entries.  The value is positive if the history
486119610Sache   was stifled,  negative if it wasn't. */
48721308Sacheint
48821308Sacheunstifle_history ()
48921308Sache{
49021308Sache  if (history_stifled)
49121308Sache    {
49221308Sache      history_stifled = 0;
493119610Sache      return (history_max_entries);
49421308Sache    }
495119610Sache  else
496119610Sache    return (-history_max_entries);
49721308Sache}
49821308Sache
49921308Sacheint
50021308Sachehistory_is_stifled ()
50121308Sache{
50221308Sache  return (history_stifled);
50321308Sache}
50421308Sache
50521308Sachevoid
50621308Sacheclear_history ()
50721308Sache{
50821308Sache  register int i;
50921308Sache
51021308Sache  /* This loses because we cannot free the data. */
51121308Sache  for (i = 0; i < history_length; i++)
51221308Sache    {
513136644Sache      free_history_entry (the_history[i]);
51421308Sache      the_history[i] = (HIST_ENTRY *)NULL;
51521308Sache    }
51621308Sache
51721308Sache  history_offset = history_length = 0;
51821308Sache}
519