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