Add some files that seem to have slipped during the conversion from
[dragonfly.git] / contrib / readline-5.0 / history.c
blobd99b76e8744eedfe2a8adee77674bd560868b589
1 /* history.c -- standalone history library */
3 /* Copyright (C) 1989-2003 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)
11 any later version.
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)
29 # include <config.h>
30 #endif
32 #include <stdio.h>
34 #if defined (HAVE_STDLIB_H)
35 # include <stdlib.h>
36 #else
37 # include "ansi_stdlib.h"
38 #endif /* HAVE_STDLIB_H */
40 #if defined (HAVE_UNISTD_H)
41 # ifdef _MINIX
42 # include <sys/types.h>
43 # endif
44 # include <unistd.h>
45 #endif
47 #include "history.h"
48 #include "histlib.h"
50 #include "xmalloc.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 /* **************************************************************** */
58 /* */
59 /* History Functions */
60 /* */
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. */
80 int history_offset;
82 /* The number of strings currently stored in the history list. */
83 int history_length;
85 /* The logical `base' of the history array. It defaults to 1. */
86 int history_base = 1;
88 /* Return the current HISTORY_STATE of the history. */
89 HISTORY_STATE *
90 history_get_history_state ()
92 HISTORY_STATE *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;
99 state->flags = 0;
100 if (history_stifled)
101 state->flags |= HS_STIFLED;
103 return (state);
106 /* Set the state of the current history array to STATE. */
107 void
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)
116 history_stifled = 1;
119 /* Begin a session in which the history functions might be used. This
120 initializes interactive variables. */
121 void
122 using_history ()
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
129 timestamps. */
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]);
138 return (result);
141 /* Returns the magic number which says what history element we are
142 looking at now. In this implementation, it returns history_offset. */
144 where_history ()
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)
153 int pos;
155 if (pos > history_length || pos < 0 || !the_history)
156 return (0);
157 history_offset = pos;
158 return (1);
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. */
164 HIST_ENTRY **
165 history_list ()
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. */
172 HIST_ENTRY *
173 current_history ()
175 return ((history_offset == history_length) || the_history == 0)
176 ? (HIST_ENTRY *)NULL
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
182 a NULL pointer. */
183 HIST_ENTRY *
184 previous_history ()
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
191 NULL pointer. */
192 HIST_ENTRY *
193 next_history ()
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. */
200 HIST_ENTRY *
201 history_get (offset)
202 int offset;
204 int local_index;
206 local_index = offset - history_base;
207 return (local_index >= history_length || local_index < 0 || !the_history)
208 ? (HIST_ENTRY *)NULL
209 : the_history[local_index];
212 time_t
213 history_get_time (hist)
214 HIST_ENTRY *hist;
216 char *ts;
217 time_t t;
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;
228 static char *
229 hist_inittime ()
231 time_t t;
232 char ts[64], *ret;
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;
243 return ret;
246 /* Place STRING at the end of the history list. The data field
247 is set to NULL. */
248 void
249 add_history (string)
250 const char *string;
252 HIST_ENTRY *temp;
254 if (history_stifled && (history_length == history_max_entries))
256 register int i;
258 /* If the history is stifled, and history_length is zero,
259 and it equals history_max_entries, we don't save items. */
260 if (history_length == 0)
261 return;
263 /* If there is something in the slot, then remove it. */
264 if (the_history[0])
265 (void) free_history_entry (the_history[0]);
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];
271 history_base++;
273 else
275 if (history_size == 0)
277 history_size = DEFAULT_HISTORY_GROW_SIZE;
278 the_history = (HIST_ENTRY **)xmalloc (history_size * sizeof (HIST_ENTRY *));
279 history_length = 1;
281 else
283 if (history_length == (history_size - 1))
285 history_size += DEFAULT_HISTORY_GROW_SIZE;
286 the_history = (HIST_ENTRY **)
287 xrealloc (the_history, history_size * sizeof (HIST_ENTRY *));
289 history_length++;
293 temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
294 temp->line = savestring (string);
295 temp->data = (char *)NULL;
297 temp->timestamp = hist_inittime ();
299 the_history[history_length] = (HIST_ENTRY *)NULL;
300 the_history[history_length - 1] = temp;
303 /* Change the time stamp of the most recent history entry to STRING. */
304 void
305 add_history_time (string)
306 const char *string;
308 HIST_ENTRY *hs;
310 hs = the_history[history_length - 1];
311 FREE (hs->timestamp);
312 hs->timestamp = savestring (string);
315 /* Free HIST and return the data so the calling application can free it
316 if necessary and desired. */
317 histdata_t
318 free_history_entry (hist)
319 HIST_ENTRY *hist;
321 histdata_t x;
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);
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. */
335 HIST_ENTRY *
336 replace_history_entry (which, line, data)
337 int which;
338 const char *line;
339 histdata_t data;
341 HIST_ENTRY *temp, *old_value;
343 if (which >= history_length)
344 return ((HIST_ENTRY *)NULL);
346 temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
347 old_value = the_history[which];
349 temp->line = savestring (line);
350 temp->data = data;
351 temp->timestamp = savestring (old_value->timestamp);
352 the_history[which] = temp;
354 return (old_value);
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. */
360 HIST_ENTRY *
361 remove_history (which)
362 int which;
364 HIST_ENTRY *return_value;
365 register int i;
367 if (which >= history_length || !history_length)
368 return_value = (HIST_ENTRY *)NULL;
369 else
371 return_value = the_history[which];
373 for (i = which; i < history_length; i++)
374 the_history[i] = the_history[i + 1];
376 history_length--;
379 return (return_value);
382 /* Stifle the history list, remembering only MAX number of lines. */
383 void
384 stifle_history (max)
385 int max;
387 register int i, j;
389 if (max < 0)
390 max = 0;
392 if (history_length > max)
394 /* This loses because we cannot free the data. */
395 for (i = 0, j = history_length - max; i < j; i++)
396 free_history_entry (the_history[i]);
398 history_base = i;
399 for (j = 0, i = history_length - max; j < max; i++, j++)
400 the_history[j] = the_history[i];
401 the_history[j] = (HIST_ENTRY *)NULL;
402 history_length = j;
405 history_stifled = 1;
406 max_input_history = history_max_entries = max;
409 /* Stop stifling the history. This returns the previous maximum
410 number of history entries. The value is positive if the history
411 was stifled, negative if it wasn't. */
413 unstifle_history ()
415 if (history_stifled)
417 history_stifled = 0;
418 return (history_max_entries);
420 else
421 return (-history_max_entries);
425 history_is_stifled ()
427 return (history_stifled);
430 void
431 clear_history ()
433 register int i;
435 /* This loses because we cannot free the data. */
436 for (i = 0; i < history_length; i++)
438 free_history_entry (the_history[i]);
439 the_history[i] = (HIST_ENTRY *)NULL;
442 history_offset = history_length = 0;