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