1 /* search.c - code for non-incremental searching in emacs and vi modes. */ 2 3 /* Copyright (C) 1992-2009 Free Software Foundation, Inc. 4 5 This file is part of the GNU Readline Library (Readline), a library 6 for reading lines of text with interactive input and history editing. 7 8 Readline 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 3 of the License, or 11 (at your option) any later version. 12 13 Readline is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with Readline. If not, see <http://www.gnu.org/licenses/>. 20 */ 21 22 #define READLINE_LIBRARY 23 24 #if defined (HAVE_CONFIG_H) 25 # include <config.h> 26 #endif 27 28 #include <sys/types.h> 29 #include <stdio.h> 30 31 #if defined (HAVE_UNISTD_H) 32 # include <unistd.h> 33 #endif 34 35 #if defined (HAVE_STDLIB_H) 36 # include <stdlib.h> 37 #else 38 # include "ansi_stdlib.h" 39 #endif 40 41 #include "rldefs.h" 42 #include "rlmbutil.h" 43 44 #include "readline.h" 45 #include "history.h" 46 47 #include "rlprivate.h" 48 #include "xmalloc.h" 49 50 #ifdef abs 51 # undef abs 52 #endif 53 #define abs(x) (((x) >= 0) ? (x) : -(x)) 54 55 _rl_search_cxt *_rl_nscxt = 0; 56 57 extern HIST_ENTRY *_rl_saved_line_for_history; 58 59 /* Functions imported from the rest of the library. */ 60 extern int _rl_free_history_entry PARAMS((HIST_ENTRY *)); 61 62 static char *noninc_search_string = (char *) NULL; 63 static int noninc_history_pos; 64 65 static char *prev_line_found = (char *) NULL; 66 67 static int rl_history_search_len; 68 static int rl_history_search_pos; 69 static char *history_search_string; 70 static int history_string_size; 71 72 static void make_history_line_current PARAMS((HIST_ENTRY *)); 73 static int noninc_search_from_pos PARAMS((char *, int, int)); 74 static int noninc_dosearch PARAMS((char *, int)); 75 static int noninc_search PARAMS((int, int)); 76 static int rl_history_search_internal PARAMS((int, int)); 77 static void rl_history_search_reinit PARAMS((void)); 78 79 static _rl_search_cxt *_rl_nsearch_init PARAMS((int, int)); 80 static int _rl_nsearch_cleanup PARAMS((_rl_search_cxt *, int)); 81 static void _rl_nsearch_abort PARAMS((_rl_search_cxt *)); 82 static int _rl_nsearch_dispatch PARAMS((_rl_search_cxt *, int)); 83 84 /* Make the data from the history entry ENTRY be the contents of the 85 current line. This doesn't do anything with rl_point; the caller 86 must set it. */ 87 static void 88 make_history_line_current (entry) 89 HIST_ENTRY *entry; 90 { 91 _rl_replace_text (entry->line, 0, rl_end); 92 _rl_fix_point (1); 93 #if defined (VI_MODE) 94 if (rl_editing_mode == vi_mode) 95 /* POSIX.2 says that the `U' command doesn't affect the copy of any 96 command lines to the edit line. We're going to implement that by 97 making the undo list start after the matching line is copied to the 98 current editing buffer. */ 99 rl_free_undo_list (); 100 #endif 101 102 if (_rl_saved_line_for_history) 103 _rl_free_history_entry (_rl_saved_line_for_history); 104 _rl_saved_line_for_history = (HIST_ENTRY *)NULL; 105 } 106 107 /* Search the history list for STRING starting at absolute history position 108 POS. If STRING begins with `^', the search must match STRING at the 109 beginning of a history line, otherwise a full substring match is performed 110 for STRING. DIR < 0 means to search backwards through the history list, 111 DIR >= 0 means to search forward. */ 112 static int 113 noninc_search_from_pos (string, pos, dir) 114 char *string; 115 int pos, dir; 116 { 117 int ret, old; 118 119 if (pos < 0) 120 return -1; 121 122 old = where_history (); 123 if (history_set_pos (pos) == 0) 124 return -1; 125 126 RL_SETSTATE(RL_STATE_SEARCH); 127 if (*string == '^') 128 ret = history_search_prefix (string + 1, dir); 129 else 130 ret = history_search (string, dir); 131 RL_UNSETSTATE(RL_STATE_SEARCH); 132 133 if (ret != -1) 134 ret = where_history (); 135 136 history_set_pos (old); 137 return (ret); 138 } 139 140 /* Search for a line in the history containing STRING. If DIR is < 0, the 141 search is backwards through previous entries, else through subsequent 142 entries. Returns 1 if the search was successful, 0 otherwise. */ 143 static int 144 noninc_dosearch (string, dir) 145 char *string; 146 int dir; 147 { 148 int oldpos, pos; 149 HIST_ENTRY *entry; 150 151 if (string == 0 || *string == '\0' || noninc_history_pos < 0) 152 { 153 rl_ding (); 154 return 0; 155 } 156 157 pos = noninc_search_from_pos (string, noninc_history_pos + dir, dir); 158 if (pos == -1) 159 { 160 /* Search failed, current history position unchanged. */ 161 rl_maybe_unsave_line (); 162 rl_clear_message (); 163 rl_point = 0; 164 rl_ding (); 165 return 0; 166 } 167 168 noninc_history_pos = pos; 169 170 oldpos = where_history (); 171 history_set_pos (noninc_history_pos); 172 entry = current_history (); 173 #if defined (VI_MODE) 174 if (rl_editing_mode != vi_mode) 175 #endif 176 history_set_pos (oldpos); 177 178 make_history_line_current (entry); 179 180 rl_point = 0; 181 rl_mark = rl_end; 182 183 rl_clear_message (); 184 return 1; 185 } 186 187 static _rl_search_cxt * 188 _rl_nsearch_init (dir, pchar) 189 int dir, pchar; 190 { 191 _rl_search_cxt *cxt; 192 char *p; 193 194 cxt = _rl_scxt_alloc (RL_SEARCH_NSEARCH, 0); 195 if (dir < 0) 196 cxt->sflags |= SF_REVERSE; /* not strictly needed */ 197 198 cxt->direction = dir; 199 cxt->history_pos = cxt->save_line; 200 201 rl_maybe_save_line (); 202 203 /* Clear the undo list, since reading the search string should create its 204 own undo list, and the whole list will end up being freed when we 205 finish reading the search string. */ 206 rl_undo_list = 0; 207 208 /* Use the line buffer to read the search string. */ 209 rl_line_buffer[0] = 0; 210 rl_end = rl_point = 0; 211 212 p = _rl_make_prompt_for_search (pchar ? pchar : ':'); 213 rl_message ("%s", p, 0); 214 xfree (p); 215 216 RL_SETSTATE(RL_STATE_NSEARCH); 217 218 _rl_nscxt = cxt; 219 220 return cxt; 221 } 222 223 static int 224 _rl_nsearch_cleanup (cxt, r) 225 _rl_search_cxt *cxt; 226 int r; 227 { 228 _rl_scxt_dispose (cxt, 0); 229 _rl_nscxt = 0; 230 231 RL_UNSETSTATE(RL_STATE_NSEARCH); 232 233 return (r != 1); 234 } 235 236 static void 237 _rl_nsearch_abort (cxt) 238 _rl_search_cxt *cxt; 239 { 240 rl_maybe_unsave_line (); 241 rl_clear_message (); 242 rl_point = cxt->save_point; 243 rl_mark = cxt->save_mark; 244 rl_restore_prompt (); 245 246 RL_UNSETSTATE (RL_STATE_NSEARCH); 247 } 248 249 /* Process just-read character C according to search context CXT. Return -1 250 if the caller should abort the search, 0 if we should break out of the 251 loop, and 1 if we should continue to read characters. */ 252 static int 253 _rl_nsearch_dispatch (cxt, c) 254 _rl_search_cxt *cxt; 255 int c; 256 { 257 switch (c) 258 { 259 case CTRL('W'): 260 rl_unix_word_rubout (1, c); 261 break; 262 263 case CTRL('U'): 264 rl_unix_line_discard (1, c); 265 break; 266 267 case RETURN: 268 case NEWLINE: 269 return 0; 270 271 case CTRL('H'): 272 case RUBOUT: 273 if (rl_point == 0) 274 { 275 _rl_nsearch_abort (cxt); 276 return -1; 277 } 278 _rl_rubout_char (1, c); 279 break; 280 281 case CTRL('C'): 282 case CTRL('G'): 283 rl_ding (); 284 _rl_nsearch_abort (cxt); 285 return -1; 286 287 default: 288 #if defined (HANDLE_MULTIBYTE) 289 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 290 rl_insert_text (cxt->mb); 291 else 292 #endif 293 _rl_insert_char (1, c); 294 break; 295 } 296 297 (*rl_redisplay_function) (); 298 return 1; 299 } 300 301 /* Perform one search according to CXT, using NONINC_SEARCH_STRING. Return 302 -1 if the search should be aborted, any other value means to clean up 303 using _rl_nsearch_cleanup (). Returns 1 if the search was successful, 304 0 otherwise. */ 305 static int 306 _rl_nsearch_dosearch (cxt) 307 _rl_search_cxt *cxt; 308 { 309 rl_mark = cxt->save_mark; 310 311 /* If rl_point == 0, we want to re-use the previous search string and 312 start from the saved history position. If there's no previous search 313 string, punt. */ 314 if (rl_point == 0) 315 { 316 if (noninc_search_string == 0) 317 { 318 rl_ding (); 319 rl_restore_prompt (); 320 RL_UNSETSTATE (RL_STATE_NSEARCH); 321 return -1; 322 } 323 } 324 else 325 { 326 /* We want to start the search from the current history position. */ 327 noninc_history_pos = cxt->save_line; 328 FREE (noninc_search_string); 329 noninc_search_string = savestring (rl_line_buffer); 330 331 /* If we don't want the subsequent undo list generated by the search 332 matching a history line to include the contents of the search string, 333 we need to clear rl_line_buffer here. For now, we just clear the 334 undo list generated by reading the search string. (If the search 335 fails, the old undo list will be restored by rl_maybe_unsave_line.) */ 336 rl_free_undo_list (); 337 } 338 339 rl_restore_prompt (); 340 return (noninc_dosearch (noninc_search_string, cxt->direction)); 341 } 342 343 /* Search non-interactively through the history list. DIR < 0 means to 344 search backwards through the history of previous commands; otherwise 345 the search is for commands subsequent to the current position in the 346 history list. PCHAR is the character to use for prompting when reading 347 the search string; if not specified (0), it defaults to `:'. */ 348 static int 349 noninc_search (dir, pchar) 350 int dir; 351 int pchar; 352 { 353 _rl_search_cxt *cxt; 354 int c, r; 355 356 cxt = _rl_nsearch_init (dir, pchar); 357 358 if (RL_ISSTATE (RL_STATE_CALLBACK)) 359 return (0); 360 361 /* Read the search string. */ 362 r = 0; 363 while (1) 364 { 365 c = _rl_search_getchar (cxt); 366 367 if (c == 0) 368 break; 369 370 r = _rl_nsearch_dispatch (cxt, c); 371 if (r < 0) 372 return 1; 373 else if (r == 0) 374 break; 375 } 376 377 r = _rl_nsearch_dosearch (cxt); 378 return ((r >= 0) ? _rl_nsearch_cleanup (cxt, r) : (r != 1)); 379 } 380 381 /* Search forward through the history list for a string. If the vi-mode 382 code calls this, KEY will be `?'. */ 383 int 384 rl_noninc_forward_search (count, key) 385 int count, key; 386 { 387 return noninc_search (1, (key == '?') ? '?' : 0); 388 } 389 390 /* Reverse search the history list for a string. If the vi-mode code 391 calls this, KEY will be `/'. */ 392 int 393 rl_noninc_reverse_search (count, key) 394 int count, key; 395 { 396 return noninc_search (-1, (key == '/') ? '/' : 0); 397 } 398 399 /* Search forward through the history list for the last string searched 400 for. If there is no saved search string, abort. */ 401 int 402 rl_noninc_forward_search_again (count, key) 403 int count, key; 404 { 405 int r; 406 407 if (!noninc_search_string) 408 { 409 rl_ding (); 410 return (-1); 411 } 412 r = noninc_dosearch (noninc_search_string, 1); 413 return (r != 1); 414 } 415 416 /* Reverse search in the history list for the last string searched 417 for. If there is no saved search string, abort. */ 418 int 419 rl_noninc_reverse_search_again (count, key) 420 int count, key; 421 { 422 int r; 423 424 if (!noninc_search_string) 425 { 426 rl_ding (); 427 return (-1); 428 } 429 r = noninc_dosearch (noninc_search_string, -1); 430 return (r != 1); 431 } 432 433 #if defined (READLINE_CALLBACKS) 434 int 435 _rl_nsearch_callback (cxt) 436 _rl_search_cxt *cxt; 437 { 438 int c, r; 439 440 c = _rl_search_getchar (cxt); 441 r = _rl_nsearch_dispatch (cxt, c); 442 if (r != 0) 443 return 1; 444 445 r = _rl_nsearch_dosearch (cxt); 446 return ((r >= 0) ? _rl_nsearch_cleanup (cxt, r) : (r != 1)); 447 } 448 #endif 449 450 static int 451 rl_history_search_internal (count, dir) 452 int count, dir; 453 { 454 HIST_ENTRY *temp; 455 int ret, oldpos; 456 457 rl_maybe_save_line (); 458 temp = (HIST_ENTRY *)NULL; 459 460 /* Search COUNT times through the history for a line whose prefix 461 matches history_search_string. When this loop finishes, TEMP, 462 if non-null, is the history line to copy into the line buffer. */ 463 while (count) 464 { 465 ret = noninc_search_from_pos (history_search_string, rl_history_search_pos + dir, dir); 466 if (ret == -1) 467 break; 468 469 /* Get the history entry we found. */ 470 rl_history_search_pos = ret; 471 oldpos = where_history (); 472 history_set_pos (rl_history_search_pos); 473 temp = current_history (); 474 history_set_pos (oldpos); 475 476 /* Don't find multiple instances of the same line. */ 477 if (prev_line_found && STREQ (prev_line_found, temp->line)) 478 continue; 479 prev_line_found = temp->line; 480 count--; 481 } 482 483 /* If we didn't find anything at all, return. */ 484 if (temp == 0) 485 { 486 rl_maybe_unsave_line (); 487 rl_ding (); 488 /* If you don't want the saved history line (last match) to show up 489 in the line buffer after the search fails, change the #if 0 to 490 #if 1 */ 491 #if 0 492 if (rl_point > rl_history_search_len) 493 { 494 rl_point = rl_end = rl_history_search_len; 495 rl_line_buffer[rl_end] = '\0'; 496 rl_mark = 0; 497 } 498 #else 499 rl_point = rl_history_search_len; /* rl_maybe_unsave_line changes it */ 500 rl_mark = rl_end; 501 #endif 502 return 1; 503 } 504 505 /* Copy the line we found into the current line buffer. */ 506 make_history_line_current (temp); 507 508 rl_point = rl_history_search_len; 509 rl_mark = rl_end; 510 511 return 0; 512 } 513 514 static void 515 rl_history_search_reinit () 516 { 517 rl_history_search_pos = where_history (); 518 rl_history_search_len = rl_point; 519 prev_line_found = (char *)NULL; 520 if (rl_point) 521 { 522 if (rl_history_search_len >= history_string_size - 2) 523 { 524 history_string_size = rl_history_search_len + 2; 525 history_search_string = (char *)xrealloc (history_search_string, history_string_size); 526 } 527 history_search_string[0] = '^'; 528 strncpy (history_search_string + 1, rl_line_buffer, rl_point); 529 history_search_string[rl_point + 1] = '\0'; 530 } 531 _rl_free_saved_history_line (); 532 } 533 534 /* Search forward in the history for the string of characters 535 from the start of the line to rl_point. This is a non-incremental 536 search. */ 537 int 538 rl_history_search_forward (count, ignore) 539 int count, ignore; 540 { 541 if (count == 0) 542 return (0); 543 544 if (rl_last_func != rl_history_search_forward && 545 rl_last_func != rl_history_search_backward) 546 rl_history_search_reinit (); 547 548 if (rl_history_search_len == 0) 549 return (rl_get_next_history (count, ignore)); 550 return (rl_history_search_internal (abs (count), (count > 0) ? 1 : -1)); 551 } 552 553 /* Search backward through the history for the string of characters 554 from the start of the line to rl_point. This is a non-incremental 555 search. */ 556 int 557 rl_history_search_backward (count, ignore) 558 int count, ignore; 559 { 560 if (count == 0) 561 return (0); 562 563 if (rl_last_func != rl_history_search_forward && 564 rl_last_func != rl_history_search_backward) 565 rl_history_search_reinit (); 566 567 if (rl_history_search_len == 0) 568 return (rl_get_previous_history (count, ignore)); 569 return (rl_history_search_internal (abs (count), (count > 0) ? -1 : 1)); 570 } 571