1 /* History.c -- standalone history library */
3 /* Copyright (C) 1989, 1992 Free Software Foundation, Inc.
5 This file contains the GNU History Library (the Library), a set of
6 routines for managing the text of previously typed lines.
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 2, or (at your option)
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.
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 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
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
28 #if defined (HAVE_CONFIG_H)
34 #if defined (HAVE_STDLIB_H)
37 # include "ansi_stdlib.h"
38 #endif /* HAVE_STDLIB_H */
40 #if defined (HAVE_UNISTD_H)
42 # include <sys/types.h>
47 #if defined (HAVE_STRING_H)
51 #endif /* !HAVE_STRING_H */
58 /* The number of slots to increase the_history by. */
59 #define DEFAULT_HISTORY_GROW_SIZE 50
61 /* **************************************************************** */
63 /* History Functions */
65 /* **************************************************************** */
67 /* An array of HIST_ENTRY. This is where we store the history. */
68 static HIST_ENTRY **the_history = (HIST_ENTRY **)NULL;
70 /* Non-zero means that we have enforced a limit on the amount of
71 history that we save. */
72 static int history_stifled;
74 /* The current number of slots allocated to the input_history. */
75 static int history_size;
77 /* If HISTORY_STIFLED is non-zero, then this is the maximum number of
78 entries to remember. */
79 int history_max_entries;
80 int max_input_history; /* backwards compatibility */
82 /* The current location of the interactive history pointer. Just makes
83 life easier for outside callers. */
86 /* The number of strings currently stored in the history list. */
89 /* The logical `base' of the history array. It defaults to 1. */
92 /* Return the current HISTORY_STATE of the history. */
94 history_get_history_state ()
98 state = (HISTORY_STATE *)xmalloc (sizeof (HISTORY_STATE));
99 state->entries = the_history;
100 state->offset = history_offset;
101 state->length = history_length;
102 state->size = history_size;
105 state->flags |= HS_STIFLED;
110 /* Set the state of the current history array to STATE. */
112 history_set_history_state (state)
113 HISTORY_STATE *state;
115 the_history = state->entries;
116 history_offset = state->offset;
117 history_length = state->length;
118 history_size = state->size;
119 if (state->flags & HS_STIFLED)
123 /* Begin a session in which the history functions might be used. This
124 initializes interactive variables. */
128 history_offset = history_length;
131 /* Return the number of bytes that the primary history entries are using.
132 This just adds up the lengths of the_history->lines. */
134 history_total_bytes ()
136 register int i, result;
138 for (i = result = 0; the_history && the_history[i]; i++)
139 result += strlen (the_history[i]->line);
144 /* Returns the magic number which says what history element we are
145 looking at now. In this implementation, it returns history_offset. */
149 return (history_offset);
152 /* Make the current history item be the one at POS, an absolute index.
153 Returns zero if POS is out of range, else non-zero. */
155 history_set_pos (pos)
158 if (pos > history_length || pos < 0 || !the_history)
160 history_offset = pos;
164 /* Return the current history array. The caller has to be carefull, since this
165 is the actual array of data, and could be bashed or made corrupt easily.
166 The array is terminated with a NULL pointer. */
170 return (the_history);
173 /* Return the history entry at the current position, as determined by
174 history_offset. If there is no entry there, return a NULL pointer. */
178 return ((history_offset == history_length) || the_history == 0)
180 : the_history[history_offset];
183 /* Back up history_offset to the previous history entry, and return
184 a pointer to that entry. If there is no previous entry then return
189 return history_offset ? the_history[--history_offset] : (HIST_ENTRY *)NULL;
192 /* Move history_offset forward to the next history entry, and return
193 a pointer to that entry. If there is no next entry then return a
198 return (history_offset == history_length) ? (HIST_ENTRY *)NULL : the_history[++history_offset];
201 /* Return the history entry which is logically at OFFSET in the history array.
202 OFFSET is relative to history_base. */
209 local_index = offset - history_base;
210 return (local_index >= history_length || local_index < 0 || !the_history)
212 : the_history[local_index];
215 /* Place STRING at the end of the history list. The data field
223 if (history_stifled && (history_length == history_max_entries))
227 /* If the history is stifled, and history_length is zero,
228 and it equals history_max_entries, we don't save items. */
229 if (history_length == 0)
232 /* If there is something in the slot, then remove it. */
235 free (the_history[0]->line);
236 free (the_history[0]);
239 /* Copy the rest of the entries, moving down one slot. */
240 for (i = 0; i < history_length; i++)
241 the_history[i] = the_history[i + 1];
247 if (history_size == 0)
249 history_size = DEFAULT_HISTORY_GROW_SIZE;
250 the_history = (HIST_ENTRY **)xmalloc (history_size * sizeof (HIST_ENTRY *));
255 if (history_length == (history_size - 1))
257 history_size += DEFAULT_HISTORY_GROW_SIZE;
258 the_history = (HIST_ENTRY **)
259 xrealloc (the_history, history_size * sizeof (HIST_ENTRY *));
265 temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
266 temp->line = savestring (string);
267 temp->data = (char *)NULL;
269 the_history[history_length] = (HIST_ENTRY *)NULL;
270 the_history[history_length - 1] = temp;
273 /* Make the history entry at WHICH have LINE and DATA. This returns
274 the old entry so you can dispose of the data. In the case of an
275 invalid WHICH, a NULL pointer is returned. */
277 replace_history_entry (which, line, data)
282 HIST_ENTRY *temp, *old_value;
284 if (which >= history_length)
285 return ((HIST_ENTRY *)NULL);
287 temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
288 old_value = the_history[which];
290 temp->line = savestring (line);
292 the_history[which] = temp;
297 /* Remove history element WHICH from the history. The removed
298 element is returned to you so you can free the line, data,
299 and containing structure. */
301 remove_history (which)
304 HIST_ENTRY *return_value;
307 if (which >= history_length || !history_length)
308 return_value = (HIST_ENTRY *)NULL;
311 return_value = the_history[which];
313 for (i = which; i < history_length; i++)
314 the_history[i] = the_history[i + 1];
319 return (return_value);
322 /* Stifle the history list, remembering only MAX number of lines. */
332 if (history_length > max)
334 /* This loses because we cannot free the data. */
335 for (i = 0, j = history_length - max; i < j; i++)
337 free (the_history[i]->line);
338 free (the_history[i]);
342 for (j = 0, i = history_length - max; j < max; i++, j++)
343 the_history[j] = the_history[i];
344 the_history[j] = (HIST_ENTRY *)NULL;
349 max_input_history = history_max_entries = max;
352 /* Stop stifling the history. This returns the previous amount the
353 history was stifled by. The value is positive if the history was
354 stifled, negative if it wasn't. */
361 return (-history_max_entries);
364 return (history_max_entries);
368 history_is_stifled ()
370 return (history_stifled);
378 /* This loses because we cannot free the data. */
379 for (i = 0; i < history_length; i++)
381 free (the_history[i]->line);
382 free (the_history[i]);
383 the_history[i] = (HIST_ENTRY *)NULL;
386 history_offset = history_length = 0;