]> git.ipfire.org Git - thirdparty/bash.git/blame - lib/readline/history.c
Imported from ../bash-2.05.tar.gz.
[thirdparty/bash.git] / lib / readline / history.c
CommitLineData
726f6388
JA
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
bb70624e 10 the Free Software Foundation; either version 2, or (at your option)
726f6388
JA
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,
bb70624e 21 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
726f6388
JA
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
ccc6cda3
JA
28#if defined (HAVE_CONFIG_H)
29# include <config.h>
30#endif
31
726f6388 32#include <stdio.h>
ccc6cda3 33
726f6388
JA
34#if defined (HAVE_STDLIB_H)
35# include <stdlib.h>
36#else
37# include "ansi_stdlib.h"
38#endif /* HAVE_STDLIB_H */
ccc6cda3 39
726f6388 40#if defined (HAVE_UNISTD_H)
cce855bc
JA
41# ifdef _MINIX
42# include <sys/types.h>
43# endif
726f6388
JA
44# include <unistd.h>
45#endif
ccc6cda3 46
726f6388
JA
47#if defined (HAVE_STRING_H)
48# include <string.h>
49#else
50# include <strings.h>
51#endif /* !HAVE_STRING_H */
726f6388 52
726f6388 53#include "history.h"
ccc6cda3 54#include "histlib.h"
726f6388 55
bb70624e 56#include "xmalloc.h"
726f6388 57
ccc6cda3
JA
58/* The number of slots to increase the_history by. */
59#define DEFAULT_HISTORY_GROW_SIZE 50
726f6388
JA
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. */
ccc6cda3 72static int history_stifled;
726f6388
JA
73
74/* If HISTORY_STIFLED is non-zero, then this is the maximum number of
75 entries to remember. */
28ef6c31
JA
76int history_max_entries;
77int max_input_history; /* backwards compatibility */
726f6388
JA
78
79/* The current location of the interactive history pointer. Just makes
80 life easier for outside callers. */
ccc6cda3 81int history_offset;
726f6388 82
ccc6cda3
JA
83/* The number of strings currently stored in the history list. */
84int history_length;
726f6388
JA
85
86/* The current number of slots allocated to the input_history. */
ccc6cda3 87static int history_size;
726f6388
JA
88
89/* The logical `base' of the history array. It defaults to 1. */
90int history_base = 1;
91
92/* Return the current HISTORY_STATE of the history. */
93HISTORY_STATE *
94history_get_history_state ()
95{
96 HISTORY_STATE *state;
97
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;
103 state->flags = 0;
104 if (history_stifled)
105 state->flags |= HS_STIFLED;
106
107 return (state);
108}
109
110/* Set the state of the current history array to STATE. */
111void
112history_set_history_state (state)
113 HISTORY_STATE *state;
114{
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)
120 history_stifled = 1;
121}
122
123/* Begin a session in which the history functions might be used. This
124 initializes interactive variables. */
125void
126using_history ()
127{
128 history_offset = history_length;
129}
130
131/* Return the number of bytes that the primary history entries are using.
132 This just adds up the lengths of the_history->lines. */
133int
134history_total_bytes ()
135{
136 register int i, result;
137
28ef6c31 138 for (i = result = 0; the_history && the_history[i]; i++)
726f6388
JA
139 result += strlen (the_history[i]->line);
140
141 return (result);
142}
143
ccc6cda3
JA
144/* Returns the magic number which says what history element we are
145 looking at now. In this implementation, it returns history_offset. */
146int
147where_history ()
148{
149 return (history_offset);
150}
151
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. */
154int
155history_set_pos (pos)
156 int pos;
157{
158 if (pos > history_length || pos < 0 || !the_history)
159 return (0);
160 history_offset = pos;
161 return (1);
162}
163
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. */
167HIST_ENTRY **
168history_list ()
169{
170 return (the_history);
171}
172
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. */
175HIST_ENTRY *
176current_history ()
177{
178 return ((history_offset == history_length) || the_history == 0)
179 ? (HIST_ENTRY *)NULL
180 : the_history[history_offset];
181}
182
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
185 a NULL pointer. */
186HIST_ENTRY *
187previous_history ()
188{
189 return history_offset ? the_history[--history_offset] : (HIST_ENTRY *)NULL;
190}
191
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
194 NULL pointer. */
195HIST_ENTRY *
196next_history ()
197{
198 return (history_offset == history_length) ? (HIST_ENTRY *)NULL : the_history[++history_offset];
199}
200
201/* Return the history entry which is logically at OFFSET in the history array.
202 OFFSET is relative to history_base. */
203HIST_ENTRY *
204history_get (offset)
205 int offset;
206{
207 int local_index;
208
209 local_index = offset - history_base;
210 return (local_index >= history_length || local_index < 0 || !the_history)
211 ? (HIST_ENTRY *)NULL
212 : the_history[local_index];
213}
214
726f6388
JA
215/* Place STRING at the end of the history list. The data field
216 is set to NULL. */
217void
218add_history (string)
28ef6c31 219 const char *string;
726f6388
JA
220{
221 HIST_ENTRY *temp;
222
28ef6c31 223 if (history_stifled && (history_length == history_max_entries))
726f6388
JA
224 {
225 register int i;
226
227 /* If the history is stifled, and history_length is zero,
28ef6c31 228 and it equals history_max_entries, we don't save items. */
726f6388
JA
229 if (history_length == 0)
230 return;
231
232 /* If there is something in the slot, then remove it. */
233 if (the_history[0])
234 {
235 free (the_history[0]->line);
236 free (the_history[0]);
237 }
238
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];
242
243 history_base++;
726f6388
JA
244 }
245 else
246 {
ccc6cda3 247 if (history_size == 0)
726f6388
JA
248 {
249 history_size = DEFAULT_HISTORY_GROW_SIZE;
250 the_history = (HIST_ENTRY **)xmalloc (history_size * sizeof (HIST_ENTRY *));
251 history_length = 1;
726f6388
JA
252 }
253 else
254 {
255 if (history_length == (history_size - 1))
256 {
257 history_size += DEFAULT_HISTORY_GROW_SIZE;
258 the_history = (HIST_ENTRY **)
259 xrealloc (the_history, history_size * sizeof (HIST_ENTRY *));
260 }
261 history_length++;
262 }
263 }
264
265 temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
266 temp->line = savestring (string);
267 temp->data = (char *)NULL;
268
269 the_history[history_length] = (HIST_ENTRY *)NULL;
270 the_history[history_length - 1] = temp;
271}
272
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. */
276HIST_ENTRY *
277replace_history_entry (which, line, data)
278 int which;
28ef6c31 279 const char *line;
b72432fd 280 histdata_t data;
726f6388 281{
28ef6c31 282 HIST_ENTRY *temp, *old_value;
726f6388
JA
283
284 if (which >= history_length)
285 return ((HIST_ENTRY *)NULL);
286
28ef6c31 287 temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
726f6388
JA
288 old_value = the_history[which];
289
290 temp->line = savestring (line);
291 temp->data = data;
292 the_history[which] = temp;
293
294 return (old_value);
295}
296
726f6388
JA
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. */
300HIST_ENTRY *
301remove_history (which)
302 int which;
303{
304 HIST_ENTRY *return_value;
28ef6c31 305 register int i;
726f6388
JA
306
307 if (which >= history_length || !history_length)
308 return_value = (HIST_ENTRY *)NULL;
309 else
310 {
726f6388
JA
311 return_value = the_history[which];
312
313 for (i = which; i < history_length; i++)
314 the_history[i] = the_history[i + 1];
315
316 history_length--;
317 }
318
319 return (return_value);
320}
321
322/* Stifle the history list, remembering only MAX number of lines. */
323void
324stifle_history (max)
325 int max;
326{
28ef6c31
JA
327 register int i, j;
328
726f6388
JA
329 if (max < 0)
330 max = 0;
331
332 if (history_length > max)
333 {
726f6388 334 /* This loses because we cannot free the data. */
ccc6cda3 335 for (i = 0, j = history_length - max; i < j; i++)
726f6388
JA
336 {
337 free (the_history[i]->line);
338 free (the_history[i]);
339 }
340
341 history_base = 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;
345 history_length = j;
346 }
347
348 history_stifled = 1;
28ef6c31 349 max_input_history = history_max_entries = max;
726f6388
JA
350}
351
ccc6cda3
JA
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. */
726f6388
JA
355int
356unstifle_history ()
357{
726f6388
JA
358 if (history_stifled)
359 {
726f6388 360 history_stifled = 0;
28ef6c31 361 return (-history_max_entries);
726f6388
JA
362 }
363
28ef6c31 364 return (history_max_entries);
726f6388
JA
365}
366
367int
368history_is_stifled ()
369{
370 return (history_stifled);
371}
372
ccc6cda3
JA
373void
374clear_history ()
726f6388
JA
375{
376 register int i;
726f6388 377
ccc6cda3
JA
378 /* This loses because we cannot free the data. */
379 for (i = 0; i < history_length; i++)
726f6388 380 {
ccc6cda3
JA
381 free (the_history[i]->line);
382 free (the_history[i]);
383 the_history[i] = (HIST_ENTRY *)NULL;
726f6388
JA
384 }
385
ccc6cda3 386 history_offset = history_length = 0;
726f6388 387}