11acd27e7Smillert /* History.c -- standalone history library */
21acd27e7Smillert
31acd27e7Smillert /* Copyright (C) 1989, 1992 Free Software Foundation, Inc.
41acd27e7Smillert
51acd27e7Smillert This file contains the GNU History Library (the Library), a set of
61acd27e7Smillert routines for managing the text of previously typed lines.
71acd27e7Smillert
81acd27e7Smillert The Library is free software; you can redistribute it and/or modify
91acd27e7Smillert it under the terms of the GNU General Public License as published by
101acd27e7Smillert the Free Software Foundation; either version 2, or (at your option)
111acd27e7Smillert any later version.
121acd27e7Smillert
131acd27e7Smillert The Library is distributed in the hope that it will be useful, but
141acd27e7Smillert WITHOUT ANY WARRANTY; without even the implied warranty of
151acd27e7Smillert MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
161acd27e7Smillert General Public License for more details.
171acd27e7Smillert
181acd27e7Smillert The GNU General Public License is often shipped with GNU software, and
191acd27e7Smillert is generally kept in a file called COPYING or LICENSE. If you do not
201acd27e7Smillert have a copy of the license, write to the Free Software Foundation,
211acd27e7Smillert 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
221acd27e7Smillert
231acd27e7Smillert /* The goal is to make the implementation transparent, so that you
241acd27e7Smillert don't have to know what data types are used, just what functions
251acd27e7Smillert you can call. I think I have done that. */
261acd27e7Smillert #define READLINE_LIBRARY
271acd27e7Smillert
281acd27e7Smillert #if defined (HAVE_CONFIG_H)
291acd27e7Smillert # include <config.h>
301acd27e7Smillert #endif
311acd27e7Smillert
321acd27e7Smillert #include <stdio.h>
331acd27e7Smillert
341acd27e7Smillert #if defined (HAVE_STDLIB_H)
351acd27e7Smillert # include <stdlib.h>
361acd27e7Smillert #else
371acd27e7Smillert # include "ansi_stdlib.h"
381acd27e7Smillert #endif /* HAVE_STDLIB_H */
391acd27e7Smillert
401acd27e7Smillert #if defined (HAVE_UNISTD_H)
411acd27e7Smillert # ifdef _MINIX
421acd27e7Smillert # include <sys/types.h>
431acd27e7Smillert # endif
441acd27e7Smillert # include <unistd.h>
451acd27e7Smillert #endif
461acd27e7Smillert
471acd27e7Smillert #include "history.h"
481acd27e7Smillert #include "histlib.h"
491acd27e7Smillert
501acd27e7Smillert #include "xmalloc.h"
511acd27e7Smillert
521acd27e7Smillert /* The number of slots to increase the_history by. */
531acd27e7Smillert #define DEFAULT_HISTORY_GROW_SIZE 50
541acd27e7Smillert
551acd27e7Smillert /* **************************************************************** */
561acd27e7Smillert /* */
571acd27e7Smillert /* History Functions */
581acd27e7Smillert /* */
591acd27e7Smillert /* **************************************************************** */
601acd27e7Smillert
611acd27e7Smillert /* An array of HIST_ENTRY. This is where we store the history. */
621acd27e7Smillert static HIST_ENTRY **the_history = (HIST_ENTRY **)NULL;
631acd27e7Smillert
641acd27e7Smillert /* Non-zero means that we have enforced a limit on the amount of
651acd27e7Smillert history that we save. */
661acd27e7Smillert static int history_stifled;
671acd27e7Smillert
68*15b117eaSkettenis /* The current number of slots allocated to the input_history. */
69*15b117eaSkettenis static int history_size;
70*15b117eaSkettenis
711acd27e7Smillert /* If HISTORY_STIFLED is non-zero, then this is the maximum number of
721acd27e7Smillert entries to remember. */
73*15b117eaSkettenis int history_max_entries;
74*15b117eaSkettenis int max_input_history; /* backwards compatibility */
751acd27e7Smillert
761acd27e7Smillert /* The current location of the interactive history pointer. Just makes
771acd27e7Smillert life easier for outside callers. */
781acd27e7Smillert int history_offset;
791acd27e7Smillert
801acd27e7Smillert /* The number of strings currently stored in the history list. */
811acd27e7Smillert int history_length;
821acd27e7Smillert
831acd27e7Smillert /* The logical `base' of the history array. It defaults to 1. */
841acd27e7Smillert int history_base = 1;
851acd27e7Smillert
861acd27e7Smillert /* Return the current HISTORY_STATE of the history. */
871acd27e7Smillert HISTORY_STATE *
history_get_history_state()881acd27e7Smillert history_get_history_state ()
891acd27e7Smillert {
901acd27e7Smillert HISTORY_STATE *state;
911acd27e7Smillert
921acd27e7Smillert state = (HISTORY_STATE *)xmalloc (sizeof (HISTORY_STATE));
931acd27e7Smillert state->entries = the_history;
941acd27e7Smillert state->offset = history_offset;
951acd27e7Smillert state->length = history_length;
961acd27e7Smillert state->size = history_size;
971acd27e7Smillert state->flags = 0;
981acd27e7Smillert if (history_stifled)
991acd27e7Smillert state->flags |= HS_STIFLED;
1001acd27e7Smillert
1011acd27e7Smillert return (state);
1021acd27e7Smillert }
1031acd27e7Smillert
1041acd27e7Smillert /* Set the state of the current history array to STATE. */
1051acd27e7Smillert void
history_set_history_state(state)1061acd27e7Smillert history_set_history_state (state)
1071acd27e7Smillert HISTORY_STATE *state;
1081acd27e7Smillert {
1091acd27e7Smillert the_history = state->entries;
1101acd27e7Smillert history_offset = state->offset;
1111acd27e7Smillert history_length = state->length;
1121acd27e7Smillert history_size = state->size;
1131acd27e7Smillert if (state->flags & HS_STIFLED)
1141acd27e7Smillert history_stifled = 1;
1151acd27e7Smillert }
1161acd27e7Smillert
1171acd27e7Smillert /* Begin a session in which the history functions might be used. This
1181acd27e7Smillert initializes interactive variables. */
1191acd27e7Smillert void
using_history()1201acd27e7Smillert using_history ()
1211acd27e7Smillert {
1221acd27e7Smillert history_offset = history_length;
1231acd27e7Smillert }
1241acd27e7Smillert
1251acd27e7Smillert /* Return the number of bytes that the primary history entries are using.
1261acd27e7Smillert This just adds up the lengths of the_history->lines. */
1271acd27e7Smillert int
history_total_bytes()1281acd27e7Smillert history_total_bytes ()
1291acd27e7Smillert {
1301acd27e7Smillert register int i, result;
1311acd27e7Smillert
132*15b117eaSkettenis for (i = result = 0; the_history && the_history[i]; i++)
1331acd27e7Smillert result += strlen (the_history[i]->line);
1341acd27e7Smillert
1351acd27e7Smillert return (result);
1361acd27e7Smillert }
1371acd27e7Smillert
1381acd27e7Smillert /* Returns the magic number which says what history element we are
1391acd27e7Smillert looking at now. In this implementation, it returns history_offset. */
1401acd27e7Smillert int
where_history()1411acd27e7Smillert where_history ()
1421acd27e7Smillert {
1431acd27e7Smillert return (history_offset);
1441acd27e7Smillert }
1451acd27e7Smillert
1461acd27e7Smillert /* Make the current history item be the one at POS, an absolute index.
1471acd27e7Smillert Returns zero if POS is out of range, else non-zero. */
1481acd27e7Smillert int
history_set_pos(pos)1491acd27e7Smillert history_set_pos (pos)
1501acd27e7Smillert int pos;
1511acd27e7Smillert {
1521acd27e7Smillert if (pos > history_length || pos < 0 || !the_history)
1531acd27e7Smillert return (0);
1541acd27e7Smillert history_offset = pos;
1551acd27e7Smillert return (1);
1561acd27e7Smillert }
1571acd27e7Smillert
1581acd27e7Smillert /* Return the current history array. The caller has to be carefull, since this
1591acd27e7Smillert is the actual array of data, and could be bashed or made corrupt easily.
1601acd27e7Smillert The array is terminated with a NULL pointer. */
1611acd27e7Smillert HIST_ENTRY **
history_list()1621acd27e7Smillert history_list ()
1631acd27e7Smillert {
1641acd27e7Smillert return (the_history);
1651acd27e7Smillert }
1661acd27e7Smillert
1671acd27e7Smillert /* Return the history entry at the current position, as determined by
1681acd27e7Smillert history_offset. If there is no entry there, return a NULL pointer. */
1691acd27e7Smillert HIST_ENTRY *
current_history()1701acd27e7Smillert current_history ()
1711acd27e7Smillert {
1721acd27e7Smillert return ((history_offset == history_length) || the_history == 0)
1731acd27e7Smillert ? (HIST_ENTRY *)NULL
1741acd27e7Smillert : the_history[history_offset];
1751acd27e7Smillert }
1761acd27e7Smillert
1771acd27e7Smillert /* Back up history_offset to the previous history entry, and return
1781acd27e7Smillert a pointer to that entry. If there is no previous entry then return
1791acd27e7Smillert a NULL pointer. */
1801acd27e7Smillert HIST_ENTRY *
previous_history()1811acd27e7Smillert previous_history ()
1821acd27e7Smillert {
1831acd27e7Smillert return history_offset ? the_history[--history_offset] : (HIST_ENTRY *)NULL;
1841acd27e7Smillert }
1851acd27e7Smillert
1861acd27e7Smillert /* Move history_offset forward to the next history entry, and return
1871acd27e7Smillert a pointer to that entry. If there is no next entry then return a
1881acd27e7Smillert NULL pointer. */
1891acd27e7Smillert HIST_ENTRY *
next_history()1901acd27e7Smillert next_history ()
1911acd27e7Smillert {
1921acd27e7Smillert return (history_offset == history_length) ? (HIST_ENTRY *)NULL : the_history[++history_offset];
1931acd27e7Smillert }
1941acd27e7Smillert
1951acd27e7Smillert /* Return the history entry which is logically at OFFSET in the history array.
1961acd27e7Smillert OFFSET is relative to history_base. */
1971acd27e7Smillert HIST_ENTRY *
history_get(offset)1981acd27e7Smillert history_get (offset)
1991acd27e7Smillert int offset;
2001acd27e7Smillert {
2011acd27e7Smillert int local_index;
2021acd27e7Smillert
2031acd27e7Smillert local_index = offset - history_base;
2041acd27e7Smillert return (local_index >= history_length || local_index < 0 || !the_history)
2051acd27e7Smillert ? (HIST_ENTRY *)NULL
2061acd27e7Smillert : the_history[local_index];
2071acd27e7Smillert }
2081acd27e7Smillert
2091acd27e7Smillert /* Place STRING at the end of the history list. The data field
2101acd27e7Smillert is set to NULL. */
2111acd27e7Smillert void
add_history(string)2121acd27e7Smillert add_history (string)
213*15b117eaSkettenis const char *string;
2141acd27e7Smillert {
2151acd27e7Smillert HIST_ENTRY *temp;
2161acd27e7Smillert
217*15b117eaSkettenis if (history_stifled && (history_length == history_max_entries))
2181acd27e7Smillert {
2191acd27e7Smillert register int i;
2201acd27e7Smillert
2211acd27e7Smillert /* If the history is stifled, and history_length is zero,
222*15b117eaSkettenis and it equals history_max_entries, we don't save items. */
2231acd27e7Smillert if (history_length == 0)
2241acd27e7Smillert return;
2251acd27e7Smillert
2261acd27e7Smillert /* If there is something in the slot, then remove it. */
2271acd27e7Smillert if (the_history[0])
2281acd27e7Smillert {
2291acd27e7Smillert free (the_history[0]->line);
2301acd27e7Smillert free (the_history[0]);
2311acd27e7Smillert }
2321acd27e7Smillert
2331acd27e7Smillert /* Copy the rest of the entries, moving down one slot. */
2341acd27e7Smillert for (i = 0; i < history_length; i++)
2351acd27e7Smillert the_history[i] = the_history[i + 1];
2361acd27e7Smillert
2371acd27e7Smillert history_base++;
2381acd27e7Smillert }
2391acd27e7Smillert else
2401acd27e7Smillert {
2411acd27e7Smillert if (history_size == 0)
2421acd27e7Smillert {
2431acd27e7Smillert history_size = DEFAULT_HISTORY_GROW_SIZE;
2441acd27e7Smillert the_history = (HIST_ENTRY **)xmalloc (history_size * sizeof (HIST_ENTRY *));
2451acd27e7Smillert history_length = 1;
2461acd27e7Smillert }
2471acd27e7Smillert else
2481acd27e7Smillert {
2491acd27e7Smillert if (history_length == (history_size - 1))
2501acd27e7Smillert {
2511acd27e7Smillert history_size += DEFAULT_HISTORY_GROW_SIZE;
2521acd27e7Smillert the_history = (HIST_ENTRY **)
2531acd27e7Smillert xrealloc (the_history, history_size * sizeof (HIST_ENTRY *));
2541acd27e7Smillert }
2551acd27e7Smillert history_length++;
2561acd27e7Smillert }
2571acd27e7Smillert }
2581acd27e7Smillert
2591acd27e7Smillert temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
2601acd27e7Smillert temp->line = savestring (string);
2611acd27e7Smillert temp->data = (char *)NULL;
2621acd27e7Smillert
2631acd27e7Smillert the_history[history_length] = (HIST_ENTRY *)NULL;
2641acd27e7Smillert the_history[history_length - 1] = temp;
2651acd27e7Smillert }
2661acd27e7Smillert
2671acd27e7Smillert /* Make the history entry at WHICH have LINE and DATA. This returns
2681acd27e7Smillert the old entry so you can dispose of the data. In the case of an
2691acd27e7Smillert invalid WHICH, a NULL pointer is returned. */
2701acd27e7Smillert HIST_ENTRY *
replace_history_entry(which,line,data)2711acd27e7Smillert replace_history_entry (which, line, data)
2721acd27e7Smillert int which;
273*15b117eaSkettenis const char *line;
2741acd27e7Smillert histdata_t data;
2751acd27e7Smillert {
276*15b117eaSkettenis HIST_ENTRY *temp, *old_value;
2771acd27e7Smillert
2781acd27e7Smillert if (which >= history_length)
2791acd27e7Smillert return ((HIST_ENTRY *)NULL);
2801acd27e7Smillert
281*15b117eaSkettenis temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
2821acd27e7Smillert old_value = the_history[which];
2831acd27e7Smillert
2841acd27e7Smillert temp->line = savestring (line);
2851acd27e7Smillert temp->data = data;
2861acd27e7Smillert the_history[which] = temp;
2871acd27e7Smillert
2881acd27e7Smillert return (old_value);
2891acd27e7Smillert }
2901acd27e7Smillert
2911acd27e7Smillert /* Remove history element WHICH from the history. The removed
2921acd27e7Smillert element is returned to you so you can free the line, data,
2931acd27e7Smillert and containing structure. */
2941acd27e7Smillert HIST_ENTRY *
remove_history(which)2951acd27e7Smillert remove_history (which)
2961acd27e7Smillert int which;
2971acd27e7Smillert {
2981acd27e7Smillert HIST_ENTRY *return_value;
299*15b117eaSkettenis register int i;
3001acd27e7Smillert
3011acd27e7Smillert if (which >= history_length || !history_length)
3021acd27e7Smillert return_value = (HIST_ENTRY *)NULL;
3031acd27e7Smillert else
3041acd27e7Smillert {
3051acd27e7Smillert return_value = the_history[which];
3061acd27e7Smillert
3071acd27e7Smillert for (i = which; i < history_length; i++)
3081acd27e7Smillert the_history[i] = the_history[i + 1];
3091acd27e7Smillert
3101acd27e7Smillert history_length--;
3111acd27e7Smillert }
3121acd27e7Smillert
3131acd27e7Smillert return (return_value);
3141acd27e7Smillert }
3151acd27e7Smillert
3161acd27e7Smillert /* Stifle the history list, remembering only MAX number of lines. */
3171acd27e7Smillert void
stifle_history(max)3181acd27e7Smillert stifle_history (max)
3191acd27e7Smillert int max;
3201acd27e7Smillert {
321*15b117eaSkettenis register int i, j;
322*15b117eaSkettenis
3231acd27e7Smillert if (max < 0)
3241acd27e7Smillert max = 0;
3251acd27e7Smillert
3261acd27e7Smillert if (history_length > max)
3271acd27e7Smillert {
3281acd27e7Smillert /* This loses because we cannot free the data. */
3291acd27e7Smillert for (i = 0, j = history_length - max; i < j; i++)
3301acd27e7Smillert {
3311acd27e7Smillert free (the_history[i]->line);
3321acd27e7Smillert free (the_history[i]);
3331acd27e7Smillert }
3341acd27e7Smillert
3351acd27e7Smillert history_base = i;
3361acd27e7Smillert for (j = 0, i = history_length - max; j < max; i++, j++)
3371acd27e7Smillert the_history[j] = the_history[i];
3381acd27e7Smillert the_history[j] = (HIST_ENTRY *)NULL;
3391acd27e7Smillert history_length = j;
3401acd27e7Smillert }
3411acd27e7Smillert
3421acd27e7Smillert history_stifled = 1;
343*15b117eaSkettenis max_input_history = history_max_entries = max;
3441acd27e7Smillert }
3451acd27e7Smillert
346*15b117eaSkettenis /* Stop stifling the history. This returns the previous maximum
347*15b117eaSkettenis number of history entries. The value is positive if the history
348*15b117eaSkettenis was stifled, negative if it wasn't. */
3491acd27e7Smillert int
unstifle_history()3501acd27e7Smillert unstifle_history ()
3511acd27e7Smillert {
3521acd27e7Smillert if (history_stifled)
3531acd27e7Smillert {
3541acd27e7Smillert history_stifled = 0;
355*15b117eaSkettenis return (history_max_entries);
3561acd27e7Smillert }
357*15b117eaSkettenis else
358*15b117eaSkettenis return (-history_max_entries);
3591acd27e7Smillert }
3601acd27e7Smillert
3611acd27e7Smillert int
history_is_stifled()3621acd27e7Smillert history_is_stifled ()
3631acd27e7Smillert {
3641acd27e7Smillert return (history_stifled);
3651acd27e7Smillert }
3661acd27e7Smillert
3671acd27e7Smillert void
clear_history()3681acd27e7Smillert clear_history ()
3691acd27e7Smillert {
3701acd27e7Smillert register int i;
3711acd27e7Smillert
3721acd27e7Smillert /* This loses because we cannot free the data. */
3731acd27e7Smillert for (i = 0; i < history_length; i++)
3741acd27e7Smillert {
3751acd27e7Smillert free (the_history[i]->line);
3761acd27e7Smillert free (the_history[i]);
3771acd27e7Smillert the_history[i] = (HIST_ENTRY *)NULL;
3781acd27e7Smillert }
3791acd27e7Smillert
3801acd27e7Smillert history_offset = history_length = 0;
3811acd27e7Smillert }
382