source: trunk/third/readline/history.c @ 12992

Revision 12992, 9.6 KB checked in by kcr, 25 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r12991, which included commits to RCS files with non-trunk default branches.
Line 
1/* History.c -- standalone history library */
2
3/* Copyright (C) 1989, 1992 Free Software Foundation, Inc.
4
5   This file contains the GNU History Library (the Library), a set of
6   routines for managing the text of previously typed lines.
7
8   The Library is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 1, or (at your option)
11   any later version.
12
13   The Library is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16   General Public License for more details.
17
18   The GNU General Public License is often shipped with GNU software, and
19   is generally kept in a file called COPYING or LICENSE.  If you do not
20   have a copy of the license, write to the Free Software Foundation,
21   675 Mass Ave, Cambridge, MA 02139, USA. */
22
23/* The goal is to make the implementation transparent, so that you
24   don't have to know what data types are used, just what functions
25   you can call.  I think I have done that. */
26#define READLINE_LIBRARY
27
28#if defined (HAVE_CONFIG_H)
29#  include <config.h>
30#endif
31
32#include <stdio.h>
33
34#if defined (HAVE_STDLIB_H)
35#  include <stdlib.h>
36#else
37#  include "ansi_stdlib.h"
38#endif /* HAVE_STDLIB_H */
39
40#if defined (HAVE_UNISTD_H)
41#  ifdef _MINIX
42#    include <sys/types.h>
43#  endif
44#  include <unistd.h>
45#endif
46
47#if defined (HAVE_STRING_H)
48#  include <string.h>
49#else
50#  include <strings.h>
51#endif /* !HAVE_STRING_H */
52
53#include "history.h"
54#include "histlib.h"
55
56extern char *xmalloc (), *xrealloc ();
57
58/* The number of slots to increase the_history by. */
59#define DEFAULT_HISTORY_GROW_SIZE 50
60
61/* **************************************************************** */
62/*                                                                  */
63/*                      History Functions                           */
64/*                                                                  */
65/* **************************************************************** */
66
67/* An array of HIST_ENTRY.  This is where we store the history. */
68static HIST_ENTRY **the_history = (HIST_ENTRY **)NULL;
69
70/* Non-zero means that we have enforced a limit on the amount of
71   history that we save. */
72static int history_stifled;
73
74/* If HISTORY_STIFLED is non-zero, then this is the maximum number of
75   entries to remember. */
76int max_input_history;
77
78/* The current location of the interactive history pointer.  Just makes
79   life easier for outside callers. */
80int history_offset;
81
82/* The number of strings currently stored in the history list. */
83int history_length;
84
85/* The current number of slots allocated to the input_history. */
86static int history_size;
87
88/* The logical `base' of the history array.  It defaults to 1. */
89int history_base = 1;
90
91/* Return the current HISTORY_STATE of the history. */
92HISTORY_STATE *
93history_get_history_state ()
94{
95  HISTORY_STATE *state;
96
97  state = (HISTORY_STATE *)xmalloc (sizeof (HISTORY_STATE));
98  state->entries = the_history;
99  state->offset = history_offset;
100  state->length = history_length;
101  state->size = history_size;
102  state->flags = 0;
103  if (history_stifled)
104    state->flags |= HS_STIFLED;
105
106  return (state);
107}
108
109/* Set the state of the current history array to STATE. */
110void
111history_set_history_state (state)
112     HISTORY_STATE *state;
113{
114  the_history = state->entries;
115  history_offset = state->offset;
116  history_length = state->length;
117  history_size = state->size;
118  if (state->flags & HS_STIFLED)
119    history_stifled = 1;
120}
121
122/* Begin a session in which the history functions might be used.  This
123   initializes interactive variables. */
124void
125using_history ()
126{
127  history_offset = history_length;
128}
129
130/* Return the number of bytes that the primary history entries are using.
131   This just adds up the lengths of the_history->lines. */
132int
133history_total_bytes ()
134{
135  register int i, result;
136
137  result = 0;
138
139  for (i = 0; the_history && the_history[i]; i++)
140    result += strlen (the_history[i]->line);
141
142  return (result);
143}
144
145/* Returns the magic number which says what history element we are
146   looking at now.  In this implementation, it returns history_offset. */
147int
148where_history ()
149{
150  return (history_offset);
151}
152
153/* Make the current history item be the one at POS, an absolute index.
154   Returns zero if POS is out of range, else non-zero. */
155int
156history_set_pos (pos)
157     int pos;
158{
159  if (pos > history_length || pos < 0 || !the_history)
160    return (0);
161  history_offset = pos;
162  return (1);
163}
164 
165/* Return the current history array.  The caller has to be carefull, since this
166   is the actual array of data, and could be bashed or made corrupt easily.
167   The array is terminated with a NULL pointer. */
168HIST_ENTRY **
169history_list ()
170{
171  return (the_history);
172}
173
174/* Return the history entry at the current position, as determined by
175   history_offset.  If there is no entry there, return a NULL pointer. */
176HIST_ENTRY *
177current_history ()
178{
179  return ((history_offset == history_length) || the_history == 0)
180                ? (HIST_ENTRY *)NULL
181                : the_history[history_offset];
182}
183
184/* Back up history_offset to the previous history entry, and return
185   a pointer to that entry.  If there is no previous entry then return
186   a NULL pointer. */
187HIST_ENTRY *
188previous_history ()
189{
190  return history_offset ? the_history[--history_offset] : (HIST_ENTRY *)NULL;
191}
192
193/* Move history_offset forward to the next history entry, and return
194   a pointer to that entry.  If there is no next entry then return a
195   NULL pointer. */
196HIST_ENTRY *
197next_history ()
198{
199  return (history_offset == history_length) ? (HIST_ENTRY *)NULL : the_history[++history_offset];
200}
201
202/* Return the history entry which is logically at OFFSET in the history array.
203   OFFSET is relative to history_base. */
204HIST_ENTRY *
205history_get (offset)
206     int offset;
207{
208  int local_index;
209
210  local_index = offset - history_base;
211  return (local_index >= history_length || local_index < 0 || !the_history)
212                ? (HIST_ENTRY *)NULL
213                : the_history[local_index];
214}
215
216/* Place STRING at the end of the history list.  The data field
217   is  set to NULL. */
218void
219add_history (string)
220     char *string;
221{
222  HIST_ENTRY *temp;
223
224  if (history_stifled && (history_length == max_input_history))
225    {
226      register int i;
227
228      /* If the history is stifled, and history_length is zero,
229         and it equals max_input_history, we don't save items. */
230      if (history_length == 0)
231        return;
232
233      /* If there is something in the slot, then remove it. */
234      if (the_history[0])
235        {
236          free (the_history[0]->line);
237          free (the_history[0]);
238        }
239
240      /* Copy the rest of the entries, moving down one slot. */
241      for (i = 0; i < history_length; i++)
242        the_history[i] = the_history[i + 1];
243
244      history_base++;
245    }
246  else
247    {
248      if (history_size == 0)
249        {
250          history_size = DEFAULT_HISTORY_GROW_SIZE;
251          the_history = (HIST_ENTRY **)xmalloc (history_size * sizeof (HIST_ENTRY *));
252          history_length = 1;
253        }
254      else
255        {
256          if (history_length == (history_size - 1))
257            {
258              history_size += DEFAULT_HISTORY_GROW_SIZE;
259              the_history = (HIST_ENTRY **)
260                xrealloc (the_history, history_size * sizeof (HIST_ENTRY *));
261            }
262          history_length++;
263        }
264    }
265
266  temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
267  temp->line = savestring (string);
268  temp->data = (char *)NULL;
269
270  the_history[history_length] = (HIST_ENTRY *)NULL;
271  the_history[history_length - 1] = temp;
272}
273
274/* Make the history entry at WHICH have LINE and DATA.  This returns
275   the old entry so you can dispose of the data.  In the case of an
276   invalid WHICH, a NULL pointer is returned. */
277HIST_ENTRY *
278replace_history_entry (which, line, data)
279     int which;
280     char *line;
281     histdata_t data;
282{
283  HIST_ENTRY *temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
284  HIST_ENTRY *old_value;
285
286  if (which >= history_length)
287    return ((HIST_ENTRY *)NULL);
288
289  old_value = the_history[which];
290
291  temp->line = savestring (line);
292  temp->data = data;
293  the_history[which] = temp;
294
295  return (old_value);
296}
297
298/* Remove history element WHICH from the history.  The removed
299   element is returned to you so you can free the line, data,
300   and containing structure. */
301HIST_ENTRY *
302remove_history (which)
303     int which;
304{
305  HIST_ENTRY *return_value;
306
307  if (which >= history_length || !history_length)
308    return_value = (HIST_ENTRY *)NULL;
309  else
310    {
311      register int i;
312      return_value = the_history[which];
313
314      for (i = which; i < history_length; i++)
315        the_history[i] = the_history[i + 1];
316
317      history_length--;
318    }
319
320  return (return_value);
321}
322
323/* Stifle the history list, remembering only MAX number of lines. */
324void
325stifle_history (max)
326     int max;
327{
328  if (max < 0)
329    max = 0;
330
331  if (history_length > max)
332    {
333      register int i, j;
334
335      /* This loses because we cannot free the data. */
336      for (i = 0, j = history_length - max; i < j; i++)
337        {
338          free (the_history[i]->line);
339          free (the_history[i]);
340        }
341
342      history_base = i;
343      for (j = 0, i = history_length - max; j < max; i++, j++)
344        the_history[j] = the_history[i];
345      the_history[j] = (HIST_ENTRY *)NULL;
346      history_length = j;
347    }
348
349  history_stifled = 1;
350  max_input_history = max;
351}
352
353/* Stop stifling the history.  This returns the previous amount the
354   history was stifled by.  The value is positive if the history was
355   stifled,  negative if it wasn't. */
356int
357unstifle_history ()
358{
359  if (history_stifled)
360    {
361      history_stifled = 0;
362      return (-max_input_history);
363    }
364
365  return (max_input_history);
366}
367
368int
369history_is_stifled ()
370{
371  return (history_stifled);
372}
373
374void
375clear_history ()
376{
377  register int i;
378
379  /* This loses because we cannot free the data. */
380  for (i = 0; i < history_length; i++)
381    {
382      free (the_history[i]->line);
383      free (the_history[i]);
384      the_history[i] = (HIST_ENTRY *)NULL;
385    }
386
387  history_offset = history_length = 0;
388}
Note: See TracBrowser for help on using the repository browser.