1136644Sache/* history.c -- standalone history library */ 221308Sache 3157184Sache/* Copyright (C) 1989-2005 Free Software Foundation, Inc. 421308Sache 521308Sache This file contains the GNU History Library (the Library), a set of 621308Sache routines for managing the text of previously typed lines. 721308Sache 821308Sache The Library is free software; you can redistribute it and/or modify 921308Sache it under the terms of the GNU General Public License as published by 1058310Sache the Free Software Foundation; either version 2, or (at your option) 1121308Sache any later version. 1221308Sache 1321308Sache The Library is distributed in the hope that it will be useful, but 1421308Sache WITHOUT ANY WARRANTY; without even the implied warranty of 1521308Sache MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1621308Sache General Public License for more details. 1721308Sache 1821308Sache The GNU General Public License is often shipped with GNU software, and 1921308Sache is generally kept in a file called COPYING or LICENSE. If you do not 2021308Sache have a copy of the license, write to the Free Software Foundation, 2158310Sache 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ 2221308Sache 2321308Sache/* The goal is to make the implementation transparent, so that you 2421308Sache don't have to know what data types are used, just what functions 2521308Sache you can call. I think I have done that. */ 2621308Sache#define READLINE_LIBRARY 2721308Sache 2821308Sache#if defined (HAVE_CONFIG_H) 2921308Sache# include <config.h> 3021308Sache#endif 3121308Sache 3221308Sache#include <stdio.h> 3321308Sache 3421308Sache#if defined (HAVE_STDLIB_H) 3521308Sache# include <stdlib.h> 3621308Sache#else 3721308Sache# include "ansi_stdlib.h" 3821308Sache#endif /* HAVE_STDLIB_H */ 3921308Sache 4021308Sache#if defined (HAVE_UNISTD_H) 4135486Sache# ifdef _MINIX 4235486Sache# include <sys/types.h> 4335486Sache# endif 4421308Sache# include <unistd.h> 4521308Sache#endif 4621308Sache 4721308Sache#include "history.h" 4821308Sache#include "histlib.h" 4921308Sache 5058310Sache#include "xmalloc.h" 5121308Sache 5221308Sache/* The number of slots to increase the_history by. */ 5321308Sache#define DEFAULT_HISTORY_GROW_SIZE 50 5421308Sache 55136644Sachestatic char *hist_inittime PARAMS((void)); 56136644Sache 5721308Sache/* **************************************************************** */ 5821308Sache/* */ 5921308Sache/* History Functions */ 6021308Sache/* */ 6121308Sache/* **************************************************************** */ 6221308Sache 6321308Sache/* An array of HIST_ENTRY. This is where we store the history. */ 6421308Sachestatic HIST_ENTRY **the_history = (HIST_ENTRY **)NULL; 6521308Sache 6621308Sache/* Non-zero means that we have enforced a limit on the amount of 6721308Sache history that we save. */ 6821308Sachestatic int history_stifled; 6921308Sache 70119610Sache/* The current number of slots allocated to the input_history. */ 71119610Sachestatic int history_size; 72119610Sache 7321308Sache/* If HISTORY_STIFLED is non-zero, then this is the maximum number of 7421308Sache entries to remember. */ 7575406Sacheint history_max_entries; 7675406Sacheint max_input_history; /* backwards compatibility */ 7721308Sache 7821308Sache/* The current location of the interactive history pointer. Just makes 7921308Sache life easier for outside callers. */ 8021308Sacheint history_offset; 8121308Sache 8221308Sache/* The number of strings currently stored in the history list. */ 8321308Sacheint history_length; 8421308Sache 8521308Sache/* The logical `base' of the history array. It defaults to 1. */ 8621308Sacheint history_base = 1; 8721308Sache 8821308Sache/* Return the current HISTORY_STATE of the history. */ 8921308SacheHISTORY_STATE * 9021308Sachehistory_get_history_state () 9121308Sache{ 9221308Sache HISTORY_STATE *state; 9321308Sache 9421308Sache state = (HISTORY_STATE *)xmalloc (sizeof (HISTORY_STATE)); 9521308Sache state->entries = the_history; 9621308Sache state->offset = history_offset; 9721308Sache state->length = history_length; 9821308Sache state->size = history_size; 9921308Sache state->flags = 0; 10021308Sache if (history_stifled) 10121308Sache state->flags |= HS_STIFLED; 10221308Sache 10321308Sache return (state); 10421308Sache} 10521308Sache 10621308Sache/* Set the state of the current history array to STATE. */ 10721308Sachevoid 10821308Sachehistory_set_history_state (state) 10921308Sache HISTORY_STATE *state; 11021308Sache{ 11121308Sache the_history = state->entries; 11221308Sache history_offset = state->offset; 11321308Sache history_length = state->length; 11421308Sache history_size = state->size; 11521308Sache if (state->flags & HS_STIFLED) 11621308Sache history_stifled = 1; 11721308Sache} 11821308Sache 11921308Sache/* Begin a session in which the history functions might be used. This 12021308Sache initializes interactive variables. */ 12121308Sachevoid 12221308Sacheusing_history () 12321308Sache{ 12421308Sache history_offset = history_length; 12521308Sache} 12621308Sache 12721308Sache/* Return the number of bytes that the primary history entries are using. 128136644Sache This just adds up the lengths of the_history->lines and the associated 129136644Sache timestamps. */ 13021308Sacheint 13121308Sachehistory_total_bytes () 13221308Sache{ 13321308Sache register int i, result; 13421308Sache 13575406Sache for (i = result = 0; the_history && the_history[i]; i++) 136136644Sache result += HISTENT_BYTES (the_history[i]); 13721308Sache 13821308Sache return (result); 13921308Sache} 14021308Sache 14121308Sache/* Returns the magic number which says what history element we are 14221308Sache looking at now. In this implementation, it returns history_offset. */ 14321308Sacheint 14421308Sachewhere_history () 14521308Sache{ 14621308Sache return (history_offset); 14721308Sache} 14821308Sache 14921308Sache/* Make the current history item be the one at POS, an absolute index. 15021308Sache Returns zero if POS is out of range, else non-zero. */ 15121308Sacheint 15221308Sachehistory_set_pos (pos) 15321308Sache int pos; 15421308Sache{ 15521308Sache if (pos > history_length || pos < 0 || !the_history) 15621308Sache return (0); 15721308Sache history_offset = pos; 15821308Sache return (1); 15921308Sache} 16021308Sache 16121308Sache/* Return the current history array. The caller has to be carefull, since this 16221308Sache is the actual array of data, and could be bashed or made corrupt easily. 16321308Sache The array is terminated with a NULL pointer. */ 16421308SacheHIST_ENTRY ** 16521308Sachehistory_list () 16621308Sache{ 16721308Sache return (the_history); 16821308Sache} 16921308Sache 17021308Sache/* Return the history entry at the current position, as determined by 17121308Sache history_offset. If there is no entry there, return a NULL pointer. */ 17221308SacheHIST_ENTRY * 17321308Sachecurrent_history () 17421308Sache{ 17521308Sache return ((history_offset == history_length) || the_history == 0) 17621308Sache ? (HIST_ENTRY *)NULL 17721308Sache : the_history[history_offset]; 17821308Sache} 17921308Sache 18021308Sache/* Back up history_offset to the previous history entry, and return 18121308Sache a pointer to that entry. If there is no previous entry then return 18221308Sache a NULL pointer. */ 18321308SacheHIST_ENTRY * 18421308Sacheprevious_history () 18521308Sache{ 18621308Sache return history_offset ? the_history[--history_offset] : (HIST_ENTRY *)NULL; 18721308Sache} 18821308Sache 18921308Sache/* Move history_offset forward to the next history entry, and return 19021308Sache a pointer to that entry. If there is no next entry then return a 19121308Sache NULL pointer. */ 19221308SacheHIST_ENTRY * 19321308Sachenext_history () 19421308Sache{ 19521308Sache return (history_offset == history_length) ? (HIST_ENTRY *)NULL : the_history[++history_offset]; 19621308Sache} 19721308Sache 19821308Sache/* Return the history entry which is logically at OFFSET in the history array. 19921308Sache OFFSET is relative to history_base. */ 20021308SacheHIST_ENTRY * 20121308Sachehistory_get (offset) 20221308Sache int offset; 20321308Sache{ 20421308Sache int local_index; 20521308Sache 20621308Sache local_index = offset - history_base; 207157184Sache return (local_index >= history_length || local_index < 0 || the_history == 0) 20821308Sache ? (HIST_ENTRY *)NULL 20921308Sache : the_history[local_index]; 21021308Sache} 21121308Sache 212165670SacheHIST_ENTRY * 213165670Sachealloc_history_entry (string, ts) 214165670Sache char *string; 215165670Sache char *ts; 216165670Sache{ 217165670Sache HIST_ENTRY *temp; 218165670Sache 219165670Sache temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY)); 220165670Sache 221165670Sache temp->line = string ? savestring (string) : string; 222165670Sache temp->data = (char *)NULL; 223165670Sache temp->timestamp = ts; 224165670Sache 225165670Sache return temp; 226165670Sache} 227165670Sache 228136644Sachetime_t 229136644Sachehistory_get_time (hist) 230136644Sache HIST_ENTRY *hist; 231136644Sache{ 232136644Sache char *ts; 233136644Sache time_t t; 234136644Sache 235136644Sache if (hist == 0 || hist->timestamp == 0) 236136644Sache return 0; 237136644Sache ts = hist->timestamp; 238136644Sache if (ts[0] != history_comment_char) 239136644Sache return 0; 240136644Sache t = (time_t) atol (ts + 1); /* XXX - should use strtol() here */ 241136644Sache return t; 242136644Sache} 243136644Sache 244136644Sachestatic char * 245136644Sachehist_inittime () 246136644Sache{ 247136644Sache time_t t; 248136644Sache char ts[64], *ret; 249136644Sache 250136644Sache t = (time_t) time ((time_t *)0); 251136644Sache#if defined (HAVE_VSNPRINTF) /* assume snprintf if vsnprintf exists */ 252136644Sache snprintf (ts, sizeof (ts) - 1, "X%lu", (unsigned long) t); 253136644Sache#else 254136644Sache sprintf (ts, "X%lu", (unsigned long) t); 255136644Sache#endif 256136644Sache ret = savestring (ts); 257136644Sache ret[0] = history_comment_char; 258136644Sache 259136644Sache return ret; 260136644Sache} 261136644Sache 26221308Sache/* Place STRING at the end of the history list. The data field 26321308Sache is set to NULL. */ 26421308Sachevoid 26521308Sacheadd_history (string) 26675406Sache const char *string; 26721308Sache{ 26821308Sache HIST_ENTRY *temp; 26921308Sache 27075406Sache if (history_stifled && (history_length == history_max_entries)) 27121308Sache { 27221308Sache register int i; 27321308Sache 27421308Sache /* If the history is stifled, and history_length is zero, 27575406Sache and it equals history_max_entries, we don't save items. */ 27621308Sache if (history_length == 0) 27721308Sache return; 27821308Sache 27921308Sache /* If there is something in the slot, then remove it. */ 28021308Sache if (the_history[0]) 281136644Sache (void) free_history_entry (the_history[0]); 28221308Sache 28321308Sache /* Copy the rest of the entries, moving down one slot. */ 28421308Sache for (i = 0; i < history_length; i++) 28521308Sache the_history[i] = the_history[i + 1]; 28621308Sache 28721308Sache history_base++; 28821308Sache } 28921308Sache else 29021308Sache { 29121308Sache if (history_size == 0) 29221308Sache { 29321308Sache history_size = DEFAULT_HISTORY_GROW_SIZE; 29421308Sache the_history = (HIST_ENTRY **)xmalloc (history_size * sizeof (HIST_ENTRY *)); 29521308Sache history_length = 1; 29621308Sache } 29721308Sache else 29821308Sache { 29921308Sache if (history_length == (history_size - 1)) 30021308Sache { 30121308Sache history_size += DEFAULT_HISTORY_GROW_SIZE; 30221308Sache the_history = (HIST_ENTRY **) 30321308Sache xrealloc (the_history, history_size * sizeof (HIST_ENTRY *)); 30421308Sache } 30521308Sache history_length++; 30621308Sache } 30721308Sache } 30821308Sache 309165670Sache temp = alloc_history_entry (string, hist_inittime ()); 31021308Sache 31121308Sache the_history[history_length] = (HIST_ENTRY *)NULL; 31221308Sache the_history[history_length - 1] = temp; 31321308Sache} 31421308Sache 315136644Sache/* Change the time stamp of the most recent history entry to STRING. */ 316136644Sachevoid 317136644Sacheadd_history_time (string) 318136644Sache const char *string; 319136644Sache{ 320136644Sache HIST_ENTRY *hs; 321136644Sache 322136644Sache hs = the_history[history_length - 1]; 323136644Sache FREE (hs->timestamp); 324136644Sache hs->timestamp = savestring (string); 325136644Sache} 326136644Sache 327136644Sache/* Free HIST and return the data so the calling application can free it 328136644Sache if necessary and desired. */ 329136644Sachehistdata_t 330136644Sachefree_history_entry (hist) 331136644Sache HIST_ENTRY *hist; 332136644Sache{ 333136644Sache histdata_t x; 334136644Sache 335136644Sache if (hist == 0) 336136644Sache return ((histdata_t) 0); 337136644Sache FREE (hist->line); 338136644Sache FREE (hist->timestamp); 339136644Sache x = hist->data; 340136644Sache free (hist); 341136644Sache return (x); 342136644Sache} 343165670Sache 344165670SacheHIST_ENTRY * 345165670Sachecopy_history_entry (hist) 346165670Sache HIST_ENTRY *hist; 347165670Sache{ 348165670Sache HIST_ENTRY *ret; 349165670Sache char *ts; 350165670Sache 351165670Sache if (hist == 0) 352165670Sache return hist; 353165670Sache 354165670Sache ret = alloc_history_entry (hist->line, (char *)NULL); 355165670Sache 356165670Sache ts = hist->timestamp ? savestring (hist->timestamp) : hist->timestamp; 357165670Sache ret->timestamp = ts; 358165670Sache 359165670Sache ret->data = hist->data; 360165670Sache 361165670Sache return ret; 362165670Sache} 363136644Sache 36421308Sache/* Make the history entry at WHICH have LINE and DATA. This returns 36521308Sache the old entry so you can dispose of the data. In the case of an 36621308Sache invalid WHICH, a NULL pointer is returned. */ 36721308SacheHIST_ENTRY * 36821308Sachereplace_history_entry (which, line, data) 36921308Sache int which; 37075406Sache const char *line; 37147558Sache histdata_t data; 37221308Sache{ 37375406Sache HIST_ENTRY *temp, *old_value; 37421308Sache 375157184Sache if (which < 0 || which >= history_length) 37621308Sache return ((HIST_ENTRY *)NULL); 37721308Sache 37875406Sache temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY)); 37921308Sache old_value = the_history[which]; 38021308Sache 38121308Sache temp->line = savestring (line); 38221308Sache temp->data = data; 383136644Sache temp->timestamp = savestring (old_value->timestamp); 38421308Sache the_history[which] = temp; 38521308Sache 38621308Sache return (old_value); 38721308Sache} 38821308Sache 389165670Sache/* Replace the DATA in the specified history entries, replacing OLD with 390165670Sache NEW. WHICH says which one(s) to replace: WHICH == -1 means to replace 391165670Sache all of the history entries where entry->data == OLD; WHICH == -2 means 392165670Sache to replace the `newest' history entry where entry->data == OLD; and 393165670Sache WHICH >= 0 means to replace that particular history entry's data, as 394165670Sache long as it matches OLD. */ 395165670Sachevoid 396165670Sachereplace_history_data (which,old, new) 397165670Sache int which; 398165670Sache histdata_t *old, *new; 399165670Sache{ 400165670Sache HIST_ENTRY *entry; 401165670Sache register int i, last; 402165670Sache 403165670Sache if (which < -2 || which >= history_length || history_length == 0 || the_history == 0) 404165670Sache return; 405165670Sache 406165670Sache if (which >= 0) 407165670Sache { 408165670Sache entry = the_history[which]; 409165670Sache if (entry && entry->data == old) 410165670Sache entry->data = new; 411165670Sache return; 412165670Sache } 413165670Sache 414165670Sache last = -1; 415165670Sache for (i = 0; i < history_length; i++) 416165670Sache { 417165670Sache entry = the_history[i]; 418165670Sache if (entry == 0) 419165670Sache continue; 420165670Sache if (entry->data == old) 421165670Sache { 422165670Sache last = i; 423165670Sache if (which == -1) 424165670Sache entry->data = new; 425165670Sache } 426165670Sache } 427165670Sache if (which == -2 && last >= 0) 428165670Sache { 429165670Sache entry = the_history[last]; 430165670Sache entry->data = new; /* XXX - we don't check entry->old */ 431165670Sache } 432165670Sache} 433165670Sache 43421308Sache/* Remove history element WHICH from the history. The removed 43521308Sache element is returned to you so you can free the line, data, 43621308Sache and containing structure. */ 43721308SacheHIST_ENTRY * 43821308Sacheremove_history (which) 43921308Sache int which; 44021308Sache{ 44121308Sache HIST_ENTRY *return_value; 44275406Sache register int i; 44321308Sache 444157184Sache if (which < 0 || which >= history_length || history_length == 0 || the_history == 0) 445157184Sache return ((HIST_ENTRY *)NULL); 44621308Sache 447157184Sache return_value = the_history[which]; 44821308Sache 449157184Sache for (i = which; i < history_length; i++) 450157184Sache the_history[i] = the_history[i + 1]; 45121308Sache 452157184Sache history_length--; 453157184Sache 45421308Sache return (return_value); 45521308Sache} 45621308Sache 45721308Sache/* Stifle the history list, remembering only MAX number of lines. */ 45821308Sachevoid 45921308Sachestifle_history (max) 46021308Sache int max; 46121308Sache{ 46275406Sache register int i, j; 46375406Sache 46421308Sache if (max < 0) 46521308Sache max = 0; 46621308Sache 46721308Sache if (history_length > max) 46821308Sache { 46921308Sache /* This loses because we cannot free the data. */ 47021308Sache for (i = 0, j = history_length - max; i < j; i++) 471136644Sache free_history_entry (the_history[i]); 47221308Sache 47321308Sache history_base = i; 47421308Sache for (j = 0, i = history_length - max; j < max; i++, j++) 47521308Sache the_history[j] = the_history[i]; 47621308Sache the_history[j] = (HIST_ENTRY *)NULL; 47721308Sache history_length = j; 47821308Sache } 47921308Sache 48021308Sache history_stifled = 1; 48175406Sache max_input_history = history_max_entries = max; 48221308Sache} 48321308Sache 484119610Sache/* Stop stifling the history. This returns the previous maximum 485119610Sache number of history entries. The value is positive if the history 486119610Sache was stifled, negative if it wasn't. */ 48721308Sacheint 48821308Sacheunstifle_history () 48921308Sache{ 49021308Sache if (history_stifled) 49121308Sache { 49221308Sache history_stifled = 0; 493119610Sache return (history_max_entries); 49421308Sache } 495119610Sache else 496119610Sache return (-history_max_entries); 49721308Sache} 49821308Sache 49921308Sacheint 50021308Sachehistory_is_stifled () 50121308Sache{ 50221308Sache return (history_stifled); 50321308Sache} 50421308Sache 50521308Sachevoid 50621308Sacheclear_history () 50721308Sache{ 50821308Sache register int i; 50921308Sache 51021308Sache /* This loses because we cannot free the data. */ 51121308Sache for (i = 0; i < history_length; i++) 51221308Sache { 513136644Sache free_history_entry (the_history[i]); 51421308Sache the_history[i] = (HIST_ENTRY *)NULL; 51521308Sache } 51621308Sache 51721308Sache history_offset = history_length = 0; 51821308Sache} 519