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 1, 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
675 Mass Ave, Cambridge, MA 02139, 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 */
56
extern char *xmalloc (), *xrealloc ();
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
/* If HISTORY_STIFLED is non-zero, then this is the maximum number of
75
entries to remember. */
76
int max_input_history;
78
/* The current location of the interactive history pointer. Just makes
79
life easier for outside callers. */
82
/* The number of strings currently stored in the history list. */
85
/* The current number of slots allocated to the input_history. */
86
static int history_size;
88
/* The logical `base' of the history array. It defaults to 1. */
91
/* Return the current HISTORY_STATE of the history. */
93
history_get_history_state ()
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;
104
state->flags |= HS_STIFLED;
109
/* Set the state of the current history array to STATE. */
111
history_set_history_state (state)
112
HISTORY_STATE *state;
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)
122
/* Begin a session in which the history functions might be used. This
123
initializes interactive variables. */
127
history_offset = history_length;
130
/* Return the number of bytes that the primary history entries are using.
131
This just adds up the lengths of the_history->lines. */
133
history_total_bytes ()
135
register int i, result;
139
for (i = 0; the_history && the_history[i]; i++)
140
result += strlen (the_history[i]->line);
145
/* Returns the magic number which says what history element we are
146
looking at now. In this implementation, it returns history_offset. */
150
return (history_offset);
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. */
156
history_set_pos (pos)
159
if (pos > history_length || pos < 0 || !the_history)
161
history_offset = pos;
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. */
171
return (the_history);
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. */
179
return ((history_offset == history_length) || the_history == 0)
181
: the_history[history_offset];
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
190
return history_offset ? the_history[--history_offset] : (HIST_ENTRY *)NULL;
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
199
return (history_offset == history_length) ? (HIST_ENTRY *)NULL : the_history[++history_offset];
202
/* Return the history entry which is logically at OFFSET in the history array.
203
OFFSET is relative to history_base. */
210
local_index = offset - history_base;
211
return (local_index >= history_length || local_index < 0 || !the_history)
213
: the_history[local_index];
216
/* Place STRING at the end of the history list. The data field
224
if (history_stifled && (history_length == max_input_history))
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)
233
/* If there is something in the slot, then remove it. */
236
free (the_history[0]->line);
237
free (the_history[0]);
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];
248
if (history_size == 0)
250
history_size = DEFAULT_HISTORY_GROW_SIZE;
251
the_history = (HIST_ENTRY **)xmalloc (history_size * sizeof (HIST_ENTRY *));
256
if (history_length == (history_size - 1))
258
history_size += DEFAULT_HISTORY_GROW_SIZE;
259
the_history = (HIST_ENTRY **)
260
xrealloc (the_history, history_size * sizeof (HIST_ENTRY *));
266
temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
267
temp->line = savestring (string);
268
temp->data = (char *)NULL;
270
the_history[history_length] = (HIST_ENTRY *)NULL;
271
the_history[history_length - 1] = temp;
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. */
278
replace_history_entry (which, line, data)
283
HIST_ENTRY *temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
284
HIST_ENTRY *old_value;
286
if (which >= history_length)
287
return ((HIST_ENTRY *)NULL);
289
old_value = the_history[which];
291
temp->line = savestring (line);
293
the_history[which] = temp;
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. */
302
remove_history (which)
305
HIST_ENTRY *return_value;
307
if (which >= history_length || !history_length)
308
return_value = (HIST_ENTRY *)NULL;
312
return_value = the_history[which];
314
for (i = which; i < history_length; i++)
315
the_history[i] = the_history[i + 1];
320
return (return_value);
323
/* Stifle the history list, remembering only MAX number of lines. */
331
if (history_length > max)
335
/* This loses because we cannot free the data. */
336
for (i = 0, j = history_length - max; i < j; i++)
338
free (the_history[i]->line);
339
free (the_history[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;
350
max_input_history = max;
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. */
362
return (-max_input_history);
365
return (max_input_history);
369
history_is_stifled ()
371
return (history_stifled);
379
/* This loses because we cannot free the data. */
380
for (i = 0; i < history_length; i++)
382
free (the_history[i]->line);
383
free (the_history[i]);
384
the_history[i] = (HIST_ENTRY *)NULL;
387
history_offset = history_length = 0;