1 /* history.c -- standalone history library */
2 
3 /* Copyright (C) 1989-2005 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
10    the Free Software Foundation; either version 2, or (at your option)
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,
21    51 Franklin Street, Fifth Floor, Boston, MA  02110-1335  USA. */
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 
28 #if defined (HAVE_CONFIG_H)
29 #  include "config_readline.h"
30 #endif
31 
32 #include <stdio.h>
33 
34 #if defined (HAVE_STDLIB_H)
35 #  include <stdlib.h>
36 #else
37 #  include "ansi_stdlib.h"
38 #endif /* HAVE_STDLIB_H */
39 
40 #if defined (HAVE_UNISTD_H)
41 #  ifdef _MINIX
42 #    include <sys/types.h>
43 #  endif
44 #  include <unistd.h>
45 #endif
46 
47 #include "history.h"
48 #include "histlib.h"
49 
50 #include "xmalloc.h"
51 
52 /* The number of slots to increase the_history by. */
53 #define DEFAULT_HISTORY_GROW_SIZE 50
54 
55 static char *hist_inittime PARAMS((void));
56 
57 /* **************************************************************** */
58 /*								    */
59 /*			History Functions			    */
60 /*								    */
61 /* **************************************************************** */
62 
63 /* An array of HIST_ENTRY.  This is where we store the history. */
64 static 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. */
68 static int history_stifled;
69 
70 /* The current number of slots allocated to the input_history. */
71 static int history_size;
72 
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 */
77 
78 /* The current location of the interactive history pointer.  Just makes
79    life easier for outside callers. */
80 int history_offset;
81 
82 /* The number of strings currently stored in the history list. */
83 int history_length;
84 
85 /* The logical `base' of the history array.  It defaults to 1. */
86 int history_base = 1;
87 
88 /* Return the current HISTORY_STATE of the history. */
89 HISTORY_STATE *
history_get_history_state()90 history_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. */
107 void
history_set_history_state(state)108 history_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. */
121 void
using_history()122 using_history ()
123 {
124   history_offset = history_length;
125 }
126 
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. */
130 int
history_total_bytes()131 history_total_bytes ()
132 {
133   register int i, result;
134 
135   for (i = result = 0; the_history && the_history[i]; i++)
136     result += HISTENT_BYTES (the_history[i]);
137 
138   return (result);
139 }
140 
141 /* Returns the magic number which says what history element we are
142    looking at now.  In this implementation, it returns history_offset. */
143 int
where_history()144 where_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. */
151 int
history_set_pos(pos)152 history_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. */
164 HIST_ENTRY **
history_list()165 history_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. */
172 HIST_ENTRY *
current_history()173 current_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. */
183 HIST_ENTRY *
previous_history()184 previous_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. */
192 HIST_ENTRY *
next_history()193 next_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. */
200 HIST_ENTRY *
history_get(offset)201 history_get (offset)
202      int offset;
203 {
204   int local_index;
205 
206   local_index = offset - history_base;
207   return (local_index >= history_length || local_index < 0 || the_history == 0)
208 		? (HIST_ENTRY *)NULL
209 		: the_history[local_index];
210 }
211 
212 HIST_ENTRY *
alloc_history_entry(string,ts)213 alloc_history_entry (string, ts)
214      const char *string;
215      char *ts;
216 {
217   HIST_ENTRY *temp;
218 
219   temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
220 
221   temp->line = string ? savestring ((char*) string) : (char*) string;
222   temp->data = (char *)NULL;
223   temp->timestamp = ts;
224 
225   return temp;
226 }
227 
228 time_t
history_get_time(hist)229 history_get_time (hist)
230      HIST_ENTRY *hist;
231 {
232   char *ts;
233   time_t t;
234 
235   if (hist == 0 || hist->timestamp == 0)
236     return 0;
237   ts = hist->timestamp;
238   if (ts[0] != history_comment_char)
239     return 0;
240   t = (time_t) atol (ts + 1);		/* XXX - should use strtol() here */
241   return t;
242 }
243 
244 static char *
hist_inittime()245 hist_inittime ()
246 {
247   time_t t;
248   char ts[64], *ret;
249 
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);
253 #else
254   sprintf (ts, "X%lu", (unsigned long) t);
255 #endif
256   ret = savestring (ts);
257   ret[0] = history_comment_char;
258 
259   return ret;
260 }
261 
262 /* Place STRING at the end of the history list.  The data field
263    is  set to NULL. */
264 void
add_history(string)265 add_history (string)
266      const char *string;
267 {
268   HIST_ENTRY *temp;
269 
270   if (history_stifled && (history_length == history_max_entries))
271     {
272       register int i;
273 
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)
277 	return;
278 
279       /* If there is something in the slot, then remove it. */
280       if (the_history[0])
281 	(void) free_history_entry (the_history[0]);
282 
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];
286 
287       history_base++;
288     }
289   else
290     {
291       if (history_size == 0)
292 	{
293 	  history_size = DEFAULT_HISTORY_GROW_SIZE;
294 	  the_history = (HIST_ENTRY **)xmalloc (history_size * sizeof (HIST_ENTRY *));
295 	  history_length = 1;
296 	}
297       else
298 	{
299 	  if (history_length == (history_size - 1))
300 	    {
301 	      history_size += DEFAULT_HISTORY_GROW_SIZE;
302 	      the_history = (HIST_ENTRY **)
303 		xrealloc (the_history, history_size * sizeof (HIST_ENTRY *));
304 	    }
305 	  history_length++;
306 	}
307     }
308 
309   temp = alloc_history_entry ((char*) string, hist_inittime ());
310 
311   the_history[history_length] = (HIST_ENTRY *)NULL;
312   the_history[history_length - 1] = temp;
313 }
314 
315 /* Change the time stamp of the most recent history entry to STRING. */
316 void
add_history_time(string)317 add_history_time (string)
318      const char *string;
319 {
320   HIST_ENTRY *hs;
321 
322   hs = the_history[history_length - 1];
323   FREE (hs->timestamp);
324   hs->timestamp = savestring (string);
325 }
326 
327 /* Free HIST and return the data so the calling application can free it
328    if necessary and desired. */
329 histdata_t
free_history_entry(hist)330 free_history_entry (hist)
331      HIST_ENTRY *hist;
332 {
333   histdata_t x;
334 
335   if (hist == 0)
336     return ((histdata_t) 0);
337   FREE (hist->line);
338   FREE (hist->timestamp);
339   x = hist->data;
340   free (hist);
341   return (x);
342 }
343 
344 HIST_ENTRY *
copy_history_entry(hist)345 copy_history_entry (hist)
346      HIST_ENTRY *hist;
347 {
348   HIST_ENTRY *ret;
349   char *ts;
350 
351   if (hist == 0)
352     return hist;
353 
354   ret = alloc_history_entry (hist->line, (char *)NULL);
355 
356   ts = hist->timestamp ? savestring (hist->timestamp) : hist->timestamp;
357   ret->timestamp = ts;
358 
359   ret->data = hist->data;
360 
361   return ret;
362 }
363 
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. */
367 HIST_ENTRY *
replace_history_entry(which,line,data)368 replace_history_entry (which, line, data)
369      int which;
370      const char *line;
371      histdata_t data;
372 {
373   HIST_ENTRY *temp, *old_value;
374 
375   if (which < 0 || which >= history_length)
376     return ((HIST_ENTRY *)NULL);
377 
378   temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
379   old_value = the_history[which];
380 
381   temp->line = savestring (line);
382   temp->data = data;
383   temp->timestamp = savestring (old_value->timestamp);
384   the_history[which] = temp;
385 
386   return (old_value);
387 }
388 
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. */
395 void
replace_history_data(which,old,new)396 replace_history_data (which,old, new)
397      int which;
398      histdata_t *old, *new;
399 {
400   HIST_ENTRY *entry;
401   register int i, last;
402 
403   if (which < -2 || which >= history_length || history_length == 0 || the_history == 0)
404     return;
405 
406   if (which >= 0)
407     {
408       entry = the_history[which];
409       if (entry && entry->data == old)
410 	entry->data = new;
411       return;
412     }
413 
414   last = -1;
415   for (i = 0; i < history_length; i++)
416     {
417       entry = the_history[i];
418       if (entry == 0)
419 	continue;
420       if (entry->data == old)
421 	{
422 	  last = i;
423 	  if (which == -1)
424 	    entry->data = new;
425 	}
426     }
427   if (which == -2 && last >= 0)
428     {
429       entry = the_history[last];
430       entry->data = new;	/* XXX - we don't check entry->old */
431     }
432 }
433 
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. */
437 HIST_ENTRY *
remove_history(which)438 remove_history (which)
439      int which;
440 {
441   HIST_ENTRY *return_value;
442   register int i;
443 
444   if (which < 0 || which >= history_length || history_length ==  0 || the_history == 0)
445     return ((HIST_ENTRY *)NULL);
446 
447   return_value = the_history[which];
448 
449   for (i = which; i < history_length; i++)
450     the_history[i] = the_history[i + 1];
451 
452   history_length--;
453 
454   return (return_value);
455 }
456 
457 /* Stifle the history list, remembering only MAX number of lines. */
458 void
stifle_history(max)459 stifle_history (max)
460      int max;
461 {
462   register int i, j;
463 
464   if (max < 0)
465     max = 0;
466 
467   if (history_length > max)
468     {
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]);
472 
473       history_base = 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;
477       history_length = j;
478     }
479 
480   history_stifled = 1;
481   max_input_history = history_max_entries = max;
482 }
483 
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. */
487 int
unstifle_history()488 unstifle_history ()
489 {
490   if (history_stifled)
491     {
492       history_stifled = 0;
493       return (history_max_entries);
494     }
495   else
496     return (-history_max_entries);
497 }
498 
499 int
history_is_stifled()500 history_is_stifled ()
501 {
502   return (history_stifled);
503 }
504 
505 void
clear_history()506 clear_history ()
507 {
508   register int i;
509 
510   /* This loses because we cannot free the data. */
511   for (i = 0; i < history_length; i++)
512     {
513       free_history_entry (the_history[i]);
514       the_history[i] = (HIST_ENTRY *)NULL;
515     }
516 
517   history_offset = history_length = 0;
518 }
519