xref: /openbsd-src/gnu/lib/libreadline/history.c (revision 47911bd667ac77dc523b8a13ef40b012dbffa741)
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
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    59 Temple Place, Suite 330, Boston, MA 02111 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.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 #if defined (HAVE_STRING_H)
48 #  include <string.h>
49 #else
50 #  include <strings.h>
51 #endif /* !HAVE_STRING_H */
52 
53 #include "history.h"
54 #include "histlib.h"
55 
56 #include "xmalloc.h"
57 
58 /* The number of slots to increase the_history by. */
59 #define DEFAULT_HISTORY_GROW_SIZE 50
60 
61 /* **************************************************************** */
62 /*								    */
63 /*			History Functions			    */
64 /*								    */
65 /* **************************************************************** */
66 
67 /* An array of HIST_ENTRY.  This is where we store the history. */
68 static 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. */
72 static int history_stifled;
73 
74 /* If HISTORY_STIFLED is non-zero, then this is the maximum number of
75    entries to remember. */
76 int max_input_history;
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 current number of slots allocated to the input_history. */
86 static int history_size;
87 
88 /* The logical `base' of the history array.  It defaults to 1. */
89 int history_base = 1;
90 
91 /* Return the current HISTORY_STATE of the history. */
92 HISTORY_STATE *
93 history_get_history_state ()
94 {
95   HISTORY_STATE *state;
96 
97   state = (HISTORY_STATE *)xmalloc (sizeof (HISTORY_STATE));
98   state->entries = the_history;
99   state->offset = history_offset;
100   state->length = history_length;
101   state->size = history_size;
102   state->flags = 0;
103   if (history_stifled)
104     state->flags |= HS_STIFLED;
105 
106   return (state);
107 }
108 
109 /* Set the state of the current history array to STATE. */
110 void
111 history_set_history_state (state)
112      HISTORY_STATE *state;
113 {
114   the_history = state->entries;
115   history_offset = state->offset;
116   history_length = state->length;
117   history_size = state->size;
118   if (state->flags & HS_STIFLED)
119     history_stifled = 1;
120 }
121 
122 /* Begin a session in which the history functions might be used.  This
123    initializes interactive variables. */
124 void
125 using_history ()
126 {
127   history_offset = history_length;
128 }
129 
130 /* Return the number of bytes that the primary history entries are using.
131    This just adds up the lengths of the_history->lines. */
132 int
133 history_total_bytes ()
134 {
135   register int i, result;
136 
137   result = 0;
138 
139   for (i = 0; the_history && the_history[i]; i++)
140     result += strlen (the_history[i]->line);
141 
142   return (result);
143 }
144 
145 /* Returns the magic number which says what history element we are
146    looking at now.  In this implementation, it returns history_offset. */
147 int
148 where_history ()
149 {
150   return (history_offset);
151 }
152 
153 /* Make the current history item be the one at POS, an absolute index.
154    Returns zero if POS is out of range, else non-zero. */
155 int
156 history_set_pos (pos)
157      int pos;
158 {
159   if (pos > history_length || pos < 0 || !the_history)
160     return (0);
161   history_offset = pos;
162   return (1);
163 }
164 
165 /* Return the current history array.  The caller has to be carefull, since this
166    is the actual array of data, and could be bashed or made corrupt easily.
167    The array is terminated with a NULL pointer. */
168 HIST_ENTRY **
169 history_list ()
170 {
171   return (the_history);
172 }
173 
174 /* Return the history entry at the current position, as determined by
175    history_offset.  If there is no entry there, return a NULL pointer. */
176 HIST_ENTRY *
177 current_history ()
178 {
179   return ((history_offset == history_length) || the_history == 0)
180 		? (HIST_ENTRY *)NULL
181 		: the_history[history_offset];
182 }
183 
184 /* Back up history_offset to the previous history entry, and return
185    a pointer to that entry.  If there is no previous entry then return
186    a NULL pointer. */
187 HIST_ENTRY *
188 previous_history ()
189 {
190   return history_offset ? the_history[--history_offset] : (HIST_ENTRY *)NULL;
191 }
192 
193 /* Move history_offset forward to the next history entry, and return
194    a pointer to that entry.  If there is no next entry then return a
195    NULL pointer. */
196 HIST_ENTRY *
197 next_history ()
198 {
199   return (history_offset == history_length) ? (HIST_ENTRY *)NULL : the_history[++history_offset];
200 }
201 
202 /* Return the history entry which is logically at OFFSET in the history array.
203    OFFSET is relative to history_base. */
204 HIST_ENTRY *
205 history_get (offset)
206      int offset;
207 {
208   int local_index;
209 
210   local_index = offset - history_base;
211   return (local_index >= history_length || local_index < 0 || !the_history)
212 		? (HIST_ENTRY *)NULL
213 		: the_history[local_index];
214 }
215 
216 /* Place STRING at the end of the history list.  The data field
217    is  set to NULL. */
218 void
219 add_history (string)
220      char *string;
221 {
222   HIST_ENTRY *temp;
223 
224   if (history_stifled && (history_length == max_input_history))
225     {
226       register int i;
227 
228       /* If the history is stifled, and history_length is zero,
229 	 and it equals max_input_history, we don't save items. */
230       if (history_length == 0)
231 	return;
232 
233       /* If there is something in the slot, then remove it. */
234       if (the_history[0])
235 	{
236 	  free (the_history[0]->line);
237 	  free (the_history[0]);
238 	}
239 
240       /* Copy the rest of the entries, moving down one slot. */
241       for (i = 0; i < history_length; i++)
242 	the_history[i] = the_history[i + 1];
243 
244       history_base++;
245     }
246   else
247     {
248       if (history_size == 0)
249 	{
250 	  history_size = DEFAULT_HISTORY_GROW_SIZE;
251 	  the_history = (HIST_ENTRY **)xmalloc (history_size * sizeof (HIST_ENTRY *));
252 	  history_length = 1;
253 	}
254       else
255 	{
256 	  if (history_length == (history_size - 1))
257 	    {
258 	      history_size += DEFAULT_HISTORY_GROW_SIZE;
259 	      the_history = (HIST_ENTRY **)
260 		xrealloc (the_history, history_size * sizeof (HIST_ENTRY *));
261 	    }
262 	  history_length++;
263 	}
264     }
265 
266   temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
267   temp->line = savestring (string);
268   temp->data = (char *)NULL;
269 
270   the_history[history_length] = (HIST_ENTRY *)NULL;
271   the_history[history_length - 1] = temp;
272 }
273 
274 /* Make the history entry at WHICH have LINE and DATA.  This returns
275    the old entry so you can dispose of the data.  In the case of an
276    invalid WHICH, a NULL pointer is returned. */
277 HIST_ENTRY *
278 replace_history_entry (which, line, data)
279      int which;
280      char *line;
281      histdata_t data;
282 {
283   HIST_ENTRY *temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
284   HIST_ENTRY *old_value;
285 
286   if (which >= history_length)
287     return ((HIST_ENTRY *)NULL);
288 
289   old_value = the_history[which];
290 
291   temp->line = savestring (line);
292   temp->data = data;
293   the_history[which] = temp;
294 
295   return (old_value);
296 }
297 
298 /* Remove history element WHICH from the history.  The removed
299    element is returned to you so you can free the line, data,
300    and containing structure. */
301 HIST_ENTRY *
302 remove_history (which)
303      int which;
304 {
305   HIST_ENTRY *return_value;
306 
307   if (which >= history_length || !history_length)
308     return_value = (HIST_ENTRY *)NULL;
309   else
310     {
311       register int i;
312       return_value = the_history[which];
313 
314       for (i = which; i < history_length; i++)
315 	the_history[i] = the_history[i + 1];
316 
317       history_length--;
318     }
319 
320   return (return_value);
321 }
322 
323 /* Stifle the history list, remembering only MAX number of lines. */
324 void
325 stifle_history (max)
326      int max;
327 {
328   if (max < 0)
329     max = 0;
330 
331   if (history_length > max)
332     {
333       register int i, j;
334 
335       /* This loses because we cannot free the data. */
336       for (i = 0, j = history_length - max; i < j; i++)
337 	{
338 	  free (the_history[i]->line);
339 	  free (the_history[i]);
340 	}
341 
342       history_base = i;
343       for (j = 0, i = history_length - max; j < max; i++, j++)
344 	the_history[j] = the_history[i];
345       the_history[j] = (HIST_ENTRY *)NULL;
346       history_length = j;
347     }
348 
349   history_stifled = 1;
350   max_input_history = max;
351 }
352 
353 /* Stop stifling the history.  This returns the previous amount the
354    history was stifled by.  The value is positive if the history was
355    stifled,  negative if it wasn't. */
356 int
357 unstifle_history ()
358 {
359   if (history_stifled)
360     {
361       history_stifled = 0;
362       return (-max_input_history);
363     }
364 
365   return (max_input_history);
366 }
367 
368 int
369 history_is_stifled ()
370 {
371   return (history_stifled);
372 }
373 
374 void
375 clear_history ()
376 {
377   register int i;
378 
379   /* This loses because we cannot free the data. */
380   for (i = 0; i < history_length; i++)
381     {
382       free (the_history[i]->line);
383       free (the_history[i]);
384       the_history[i] = (HIST_ENTRY *)NULL;
385     }
386 
387   history_offset = history_length = 0;
388 }
389