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