]> git.ipfire.org Git - thirdparty/bash.git/blame - lib/readline/history.c
Imported from ../bash-3.1.tar.gz.
[thirdparty/bash.git] / lib / readline / history.c
CommitLineData
b80f6443 1/* history.c -- standalone history library */
726f6388 2
95732b49 3/* Copyright (C) 1989-2005 Free Software Foundation, Inc.
726f6388
JA
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 47#include "history.h"
ccc6cda3 48#include "histlib.h"
726f6388 49
bb70624e 50#include "xmalloc.h"
726f6388 51
ccc6cda3
JA
52/* The number of slots to increase the_history by. */
53#define DEFAULT_HISTORY_GROW_SIZE 50
726f6388 54
b80f6443
JA
55static char *hist_inittime PARAMS((void));
56
726f6388
JA
57/* **************************************************************** */
58/* */
59/* History Functions */
60/* */
61/* **************************************************************** */
62
63/* An array of HIST_ENTRY. This is where we store the history. */
64static HIST_ENTRY **the_history = (HIST_ENTRY **)NULL;
65
66/* Non-zero means that we have enforced a limit on the amount of
67 history that we save. */
ccc6cda3 68static int history_stifled;
726f6388 69
f73dda09
JA
70/* The current number of slots allocated to the input_history. */
71static int history_size;
72
726f6388
JA
73/* If HISTORY_STIFLED is non-zero, then this is the maximum number of
74 entries to remember. */
28ef6c31
JA
75int history_max_entries;
76int max_input_history; /* backwards compatibility */
726f6388
JA
77
78/* The current location of the interactive history pointer. Just makes
79 life easier for outside callers. */
ccc6cda3 80int history_offset;
726f6388 81
ccc6cda3
JA
82/* The number of strings currently stored in the history list. */
83int history_length;
726f6388 84
726f6388
JA
85/* The logical `base' of the history array. It defaults to 1. */
86int history_base = 1;
87
88/* Return the current HISTORY_STATE of the history. */
89HISTORY_STATE *
90history_get_history_state ()
91{
92 HISTORY_STATE *state;
93
94 state = (HISTORY_STATE *)xmalloc (sizeof (HISTORY_STATE));
95 state->entries = the_history;
96 state->offset = history_offset;
97 state->length = history_length;
98 state->size = history_size;
99 state->flags = 0;
100 if (history_stifled)
101 state->flags |= HS_STIFLED;
102
103 return (state);
104}
105
106/* Set the state of the current history array to STATE. */
107void
108history_set_history_state (state)
109 HISTORY_STATE *state;
110{
111 the_history = state->entries;
112 history_offset = state->offset;
113 history_length = state->length;
114 history_size = state->size;
115 if (state->flags & HS_STIFLED)
116 history_stifled = 1;
117}
118
119/* Begin a session in which the history functions might be used. This
120 initializes interactive variables. */
121void
122using_history ()
123{
124 history_offset = history_length;
125}
126
127/* Return the number of bytes that the primary history entries are using.
b80f6443
JA
128 This just adds up the lengths of the_history->lines and the associated
129 timestamps. */
726f6388
JA
130int
131history_total_bytes ()
132{
133 register int i, result;
134
28ef6c31 135 for (i = result = 0; the_history && the_history[i]; i++)
b80f6443 136 result += HISTENT_BYTES (the_history[i]);
726f6388
JA
137
138 return (result);
139}
140
ccc6cda3
JA
141/* Returns the magic number which says what history element we are
142 looking at now. In this implementation, it returns history_offset. */
143int
144where_history ()
145{
146 return (history_offset);
147}
148
149/* Make the current history item be the one at POS, an absolute index.
150 Returns zero if POS is out of range, else non-zero. */
151int
152history_set_pos (pos)
153 int pos;
154{
155 if (pos > history_length || pos < 0 || !the_history)
156 return (0);
157 history_offset = pos;
158 return (1);
159}
160
161/* Return the current history array. The caller has to be carefull, since this
162 is the actual array of data, and could be bashed or made corrupt easily.
163 The array is terminated with a NULL pointer. */
164HIST_ENTRY **
165history_list ()
166{
167 return (the_history);
168}
169
170/* Return the history entry at the current position, as determined by
171 history_offset. If there is no entry there, return a NULL pointer. */
172HIST_ENTRY *
173current_history ()
174{
175 return ((history_offset == history_length) || the_history == 0)
176 ? (HIST_ENTRY *)NULL
177 : the_history[history_offset];
178}
179
180/* Back up history_offset to the previous history entry, and return
181 a pointer to that entry. If there is no previous entry then return
182 a NULL pointer. */
183HIST_ENTRY *
184previous_history ()
185{
186 return history_offset ? the_history[--history_offset] : (HIST_ENTRY *)NULL;
187}
188
189/* Move history_offset forward to the next history entry, and return
190 a pointer to that entry. If there is no next entry then return a
191 NULL pointer. */
192HIST_ENTRY *
193next_history ()
194{
195 return (history_offset == history_length) ? (HIST_ENTRY *)NULL : the_history[++history_offset];
196}
197
198/* Return the history entry which is logically at OFFSET in the history array.
199 OFFSET is relative to history_base. */
200HIST_ENTRY *
201history_get (offset)
202 int offset;
203{
204 int local_index;
205
206 local_index = offset - history_base;
95732b49 207 return (local_index >= history_length || local_index < 0 || the_history == 0)
ccc6cda3
JA
208 ? (HIST_ENTRY *)NULL
209 : the_history[local_index];
210}
211
b80f6443
JA
212time_t
213history_get_time (hist)
214 HIST_ENTRY *hist;
215{
216 char *ts;
217 time_t t;
218
219 if (hist == 0 || hist->timestamp == 0)
220 return 0;
221 ts = hist->timestamp;
222 if (ts[0] != history_comment_char)
223 return 0;
224 t = (time_t) atol (ts + 1); /* XXX - should use strtol() here */
225 return t;
226}
227
228static char *
229hist_inittime ()
230{
231 time_t t;
232 char ts[64], *ret;
233
234 t = (time_t) time ((time_t *)0);
235#if defined (HAVE_VSNPRINTF) /* assume snprintf if vsnprintf exists */
236 snprintf (ts, sizeof (ts) - 1, "X%lu", (unsigned long) t);
237#else
238 sprintf (ts, "X%lu", (unsigned long) t);
239#endif
240 ret = savestring (ts);
241 ret[0] = history_comment_char;
242
243 return ret;
244}
245
726f6388
JA
246/* Place STRING at the end of the history list. The data field
247 is set to NULL. */
248void
249add_history (string)
28ef6c31 250 const char *string;
726f6388
JA
251{
252 HIST_ENTRY *temp;
253
28ef6c31 254 if (history_stifled && (history_length == history_max_entries))
726f6388
JA
255 {
256 register int i;
257
258 /* If the history is stifled, and history_length is zero,
28ef6c31 259 and it equals history_max_entries, we don't save items. */
726f6388
JA
260 if (history_length == 0)
261 return;
262
263 /* If there is something in the slot, then remove it. */
264 if (the_history[0])
b80f6443 265 (void) free_history_entry (the_history[0]);
726f6388
JA
266
267 /* Copy the rest of the entries, moving down one slot. */
268 for (i = 0; i < history_length; i++)
269 the_history[i] = the_history[i + 1];
270
271 history_base++;
726f6388
JA
272 }
273 else
274 {
ccc6cda3 275 if (history_size == 0)
726f6388
JA
276 {
277 history_size = DEFAULT_HISTORY_GROW_SIZE;
278 the_history = (HIST_ENTRY **)xmalloc (history_size * sizeof (HIST_ENTRY *));
279 history_length = 1;
726f6388
JA
280 }
281 else
282 {
283 if (history_length == (history_size - 1))
284 {
285 history_size += DEFAULT_HISTORY_GROW_SIZE;
286 the_history = (HIST_ENTRY **)
287 xrealloc (the_history, history_size * sizeof (HIST_ENTRY *));
288 }
289 history_length++;
290 }
291 }
292
293 temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
294 temp->line = savestring (string);
295 temp->data = (char *)NULL;
296
b80f6443
JA
297 temp->timestamp = hist_inittime ();
298
726f6388
JA
299 the_history[history_length] = (HIST_ENTRY *)NULL;
300 the_history[history_length - 1] = temp;
301}
302
b80f6443
JA
303/* Change the time stamp of the most recent history entry to STRING. */
304void
305add_history_time (string)
306 const char *string;
307{
308 HIST_ENTRY *hs;
309
310 hs = the_history[history_length - 1];
311 FREE (hs->timestamp);
312 hs->timestamp = savestring (string);
313}
314
315/* Free HIST and return the data so the calling application can free it
316 if necessary and desired. */
317histdata_t
318free_history_entry (hist)
319 HIST_ENTRY *hist;
320{
321 histdata_t x;
322
323 if (hist == 0)
324 return ((histdata_t) 0);
325 FREE (hist->line);
326 FREE (hist->timestamp);
327 x = hist->data;
328 free (hist);
329 return (x);
330}
331
726f6388
JA
332/* Make the history entry at WHICH have LINE and DATA. This returns
333 the old entry so you can dispose of the data. In the case of an
334 invalid WHICH, a NULL pointer is returned. */
335HIST_ENTRY *
336replace_history_entry (which, line, data)
337 int which;
28ef6c31 338 const char *line;
b72432fd 339 histdata_t data;
726f6388 340{
28ef6c31 341 HIST_ENTRY *temp, *old_value;
726f6388 342
95732b49 343 if (which < 0 || which >= history_length)
726f6388
JA
344 return ((HIST_ENTRY *)NULL);
345
28ef6c31 346 temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
726f6388
JA
347 old_value = the_history[which];
348
349 temp->line = savestring (line);
350 temp->data = data;
b80f6443 351 temp->timestamp = savestring (old_value->timestamp);
726f6388
JA
352 the_history[which] = temp;
353
354 return (old_value);
355}
356
726f6388
JA
357/* Remove history element WHICH from the history. The removed
358 element is returned to you so you can free the line, data,
359 and containing structure. */
360HIST_ENTRY *
361remove_history (which)
362 int which;
363{
364 HIST_ENTRY *return_value;
28ef6c31 365 register int i;
726f6388 366
95732b49
JA
367 if (which < 0 || which >= history_length || history_length == 0 || the_history == 0)
368 return ((HIST_ENTRY *)NULL);
726f6388 369
95732b49 370 return_value = the_history[which];
726f6388 371
95732b49
JA
372 for (i = which; i < history_length; i++)
373 the_history[i] = the_history[i + 1];
374
375 history_length--;
726f6388
JA
376
377 return (return_value);
378}
379
380/* Stifle the history list, remembering only MAX number of lines. */
381void
382stifle_history (max)
383 int max;
384{
28ef6c31
JA
385 register int i, j;
386
726f6388
JA
387 if (max < 0)
388 max = 0;
389
390 if (history_length > max)
391 {
726f6388 392 /* This loses because we cannot free the data. */
ccc6cda3 393 for (i = 0, j = history_length - max; i < j; i++)
b80f6443 394 free_history_entry (the_history[i]);
726f6388
JA
395
396 history_base = i;
397 for (j = 0, i = history_length - max; j < max; i++, j++)
398 the_history[j] = the_history[i];
399 the_history[j] = (HIST_ENTRY *)NULL;
400 history_length = j;
401 }
402
403 history_stifled = 1;
28ef6c31 404 max_input_history = history_max_entries = max;
726f6388
JA
405}
406
7117c2d2
JA
407/* Stop stifling the history. This returns the previous maximum
408 number of history entries. The value is positive if the history
409 was stifled, negative if it wasn't. */
726f6388
JA
410int
411unstifle_history ()
412{
726f6388
JA
413 if (history_stifled)
414 {
726f6388 415 history_stifled = 0;
7117c2d2 416 return (history_max_entries);
726f6388 417 }
7117c2d2
JA
418 else
419 return (-history_max_entries);
726f6388
JA
420}
421
422int
423history_is_stifled ()
424{
425 return (history_stifled);
426}
427
ccc6cda3
JA
428void
429clear_history ()
726f6388
JA
430{
431 register int i;
726f6388 432
ccc6cda3
JA
433 /* This loses because we cannot free the data. */
434 for (i = 0; i < history_length; i++)
726f6388 435 {
b80f6443 436 free_history_entry (the_history[i]);
ccc6cda3 437 the_history[i] = (HIST_ENTRY *)NULL;
726f6388
JA
438 }
439
ccc6cda3 440 history_offset = history_length = 0;
726f6388 441}