1 /* history.c -- standalone history library */
3 /* Copyright (C) 1989-2005 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>
52 /* The number of slots to increase the_history by. */
53 #define DEFAULT_HISTORY_GROW_SIZE 50
55 static char *hist_inittime PARAMS((void));
57 /* **************************************************************** */
59 /* History Functions */
61 /* **************************************************************** */
63 /* An array of HIST_ENTRY. This is where we store the history. */
64 static HIST_ENTRY **the_history = (HIST_ENTRY **)NULL;
66 /* Non-zero means that we have enforced a limit on the amount of
67 history that we save. */
68 static int history_stifled;
70 /* The current number of slots allocated to the input_history. */
71 static int history_size;
73 /* If HISTORY_STIFLED is non-zero, then this is the maximum number of
74 entries to remember. */
75 int history_max_entries;
76 int max_input_history; /* backwards compatibility */
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 logical `base' of the history array. It defaults to 1. */
88 /* Return the current HISTORY_STATE of the history. */
90 history_get_history_state ()
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;
101 state->flags |= HS_STIFLED;
106 /* Set the state of the current history array to STATE. */
108 history_set_history_state (state)
109 HISTORY_STATE *state;
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)
119 /* Begin a session in which the history functions might be used. This
120 initializes interactive variables. */
124 history_offset = history_length;
127 /* Return the number of bytes that the primary history entries are using.
128 This just adds up the lengths of the_history->lines and the associated
131 history_total_bytes ()
133 register int i, result;
135 for (i = result = 0; the_history && the_history[i]; i++)
136 result += HISTENT_BYTES (the_history[i]);
141 /* Returns the magic number which says what history element we are
142 looking at now. In this implementation, it returns history_offset. */
146 return (history_offset);
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. */
152 history_set_pos (pos)
155 if (pos > history_length || pos < 0 || !the_history)
157 history_offset = pos;
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. */
167 return (the_history);
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. */
175 return ((history_offset == history_length) || the_history == 0)
177 : the_history[history_offset];
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
186 return history_offset ? the_history[--history_offset] : (HIST_ENTRY *)NULL;
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
195 return (history_offset == history_length) ? (HIST_ENTRY *)NULL : the_history[++history_offset];
198 /* Return the history entry which is logically at OFFSET in the history array.
199 OFFSET is relative to history_base. */
206 local_index = offset - history_base;
207 return (local_index >= history_length || local_index < 0 || the_history == 0)
209 : the_history[local_index];
213 alloc_history_entry (string, ts)
219 temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
221 temp->line = string ? savestring (string) : string;
222 temp->data = (char *)NULL;
223 temp->timestamp = ts;
229 history_get_time (hist)
235 if (hist == 0 || hist->timestamp == 0)
237 ts = hist->timestamp;
238 if (ts[0] != history_comment_char)
240 t = (time_t) atol (ts + 1); /* XXX - should use strtol() here */
250 t = (time_t) time ((time_t *)0);
251 #if defined (HAVE_VSNPRINTF) /* assume snprintf if vsnprintf exists */
252 snprintf (ts, sizeof (ts) - 1, "X%lu", (unsigned long) t);
254 sprintf (ts, "X%lu", (unsigned long) t);
256 ret = savestring (ts);
257 ret[0] = history_comment_char;
262 /* Place STRING at the end of the history list. The data field
270 if (history_stifled && (history_length == history_max_entries))
274 /* If the history is stifled, and history_length is zero,
275 and it equals history_max_entries, we don't save items. */
276 if (history_length == 0)
279 /* If there is something in the slot, then remove it. */
281 (void) free_history_entry (the_history[0]);
283 /* Copy the rest of the entries, moving down one slot. */
284 for (i = 0; i < history_length; i++)
285 the_history[i] = the_history[i + 1];
291 if (history_size == 0)
293 history_size = DEFAULT_HISTORY_GROW_SIZE;
294 the_history = (HIST_ENTRY **)xmalloc (history_size * sizeof (HIST_ENTRY *));
299 if (history_length == (history_size - 1))
301 history_size += DEFAULT_HISTORY_GROW_SIZE;
302 the_history = (HIST_ENTRY **)
303 xrealloc (the_history, history_size * sizeof (HIST_ENTRY *));
309 temp = alloc_history_entry (string, hist_inittime ());
311 the_history[history_length] = (HIST_ENTRY *)NULL;
312 the_history[history_length - 1] = temp;
315 /* Change the time stamp of the most recent history entry to STRING. */
317 add_history_time (string)
322 hs = the_history[history_length - 1];
323 FREE (hs->timestamp);
324 hs->timestamp = savestring (string);
327 /* Free HIST and return the data so the calling application can free it
328 if necessary and desired. */
330 free_history_entry (hist)
336 return ((histdata_t) 0);
338 FREE (hist->timestamp);
345 copy_history_entry (hist)
354 ret = alloc_history_entry (hist->line, (char *)NULL);
356 ts = hist->timestamp ? savestring (hist->timestamp) : hist->timestamp;
359 ret->data = hist->data;
364 /* Make the history entry at WHICH have LINE and DATA. This returns
365 the old entry so you can dispose of the data. In the case of an
366 invalid WHICH, a NULL pointer is returned. */
368 replace_history_entry (which, line, data)
373 HIST_ENTRY *temp, *old_value;
375 if (which < 0 || which >= history_length)
376 return ((HIST_ENTRY *)NULL);
378 temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
379 old_value = the_history[which];
381 temp->line = savestring (line);
383 temp->timestamp = savestring (old_value->timestamp);
384 the_history[which] = temp;
389 /* Replace the DATA in the specified history entries, replacing OLD with
390 NEW. WHICH says which one(s) to replace: WHICH == -1 means to replace
391 all of the history entries where entry->data == OLD; WHICH == -2 means
392 to replace the `newest' history entry where entry->data == OLD; and
393 WHICH >= 0 means to replace that particular history entry's data, as
394 long as it matches OLD. */
396 replace_history_data (which,old, new)
398 histdata_t *old, *new;
401 register int i, last;
403 if (which < -2 || which >= history_length || history_length == 0 || the_history == 0)
408 entry = the_history[which];
409 if (entry && entry->data == old)
415 for (i = 0; i < history_length; i++)
417 entry = the_history[i];
420 if (entry->data == old)
427 if (which == -2 && last >= 0)
429 entry = the_history[last];
430 entry->data = new; /* XXX - we don't check entry->old */
434 /* Remove history element WHICH from the history. The removed
435 element is returned to you so you can free the line, data,
436 and containing structure. */
438 remove_history (which)
441 HIST_ENTRY *return_value;
444 if (which < 0 || which >= history_length || history_length == 0 || the_history == 0)
445 return ((HIST_ENTRY *)NULL);
447 return_value = the_history[which];
449 for (i = which; i < history_length; i++)
450 the_history[i] = the_history[i + 1];
454 return (return_value);
457 /* Stifle the history list, remembering only MAX number of lines. */
467 if (history_length > max)
469 /* This loses because we cannot free the data. */
470 for (i = 0, j = history_length - max; i < j; i++)
471 free_history_entry (the_history[i]);
474 for (j = 0, i = history_length - max; j < max; i++, j++)
475 the_history[j] = the_history[i];
476 the_history[j] = (HIST_ENTRY *)NULL;
481 max_input_history = history_max_entries = max;
484 /* Stop stifling the history. This returns the previous maximum
485 number of history entries. The value is positive if the history
486 was stifled, negative if it wasn't. */
493 return (history_max_entries);
496 return (-history_max_entries);
500 history_is_stifled ()
502 return (history_stifled);
510 /* This loses because we cannot free the data. */
511 for (i = 0; i < history_length; i++)
513 free_history_entry (the_history[i]);
514 the_history[i] = (HIST_ENTRY *)NULL;
517 history_offset = history_length = 0;