1/* misc.c -- miscellaneous bindable readline functions. */ 2 3/* Copyright (C) 1987-2005 Free Software Foundation, Inc. 4 5 This file is part of the GNU Readline Library, a library for 6 reading lines of text with interactive input and history editing. 7 8 The GNU Readline Library is free software; you can redistribute it 9 and/or modify it under the terms of the GNU General Public License 10 as published by the Free Software Foundation; either version 2, or 11 (at your option) any later version. 12 13 The GNU Readline Library is distributed in the hope that it will be 14 useful, but WITHOUT ANY WARRANTY; without even the implied warranty 15 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU 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#define READLINE_LIBRARY 23 24#if defined (HAVE_CONFIG_H) 25# include <config.h> 26#endif 27 28#if defined (HAVE_UNISTD_H) 29# include <unistd.h> 30#endif /* HAVE_UNISTD_H */ 31 32#if defined (HAVE_STDLIB_H) 33# include <stdlib.h> 34#else 35# include "ansi_stdlib.h" 36#endif /* HAVE_STDLIB_H */ 37 38#if defined (HAVE_LOCALE_H) 39# include <locale.h> 40#endif 41 42#include <stdio.h> 43 44/* System-specific feature definitions and include files. */ 45#include "rldefs.h" 46#include "rlmbutil.h" 47 48/* Some standard library routines. */ 49#include "readline.h" 50#include "history.h" 51 52#include "rlprivate.h" 53#include "rlshell.h" 54#include "xmalloc.h" 55 56static int rl_digit_loop PARAMS((void)); 57static void _rl_history_set_point PARAMS((void)); 58 59/* Forward declarations used in this file */ 60void _rl_free_history_entry PARAMS((HIST_ENTRY *)); 61 62/* If non-zero, rl_get_previous_history and rl_get_next_history attempt 63 to preserve the value of rl_point from line to line. */ 64int _rl_history_preserve_point = 0; 65 66_rl_arg_cxt _rl_argcxt; 67 68/* Saved target point for when _rl_history_preserve_point is set. Special 69 value of -1 means that point is at the end of the line. */ 70int _rl_history_saved_point = -1; 71 72/* **************************************************************** */ 73/* */ 74/* Numeric Arguments */ 75/* */ 76/* **************************************************************** */ 77 78int 79_rl_arg_overflow () 80{ 81 if (rl_numeric_arg > 1000000) 82 { 83 _rl_argcxt = 0; 84 rl_explicit_arg = rl_numeric_arg = 0; 85 rl_ding (); 86 rl_restore_prompt (); 87 rl_clear_message (); 88 RL_UNSETSTATE(RL_STATE_NUMERICARG); 89 return 1; 90 } 91 return 0; 92} 93 94void 95_rl_arg_init () 96{ 97 rl_save_prompt (); 98 _rl_argcxt = 0; 99 RL_SETSTATE(RL_STATE_NUMERICARG); 100} 101 102int 103_rl_arg_getchar () 104{ 105 int c; 106 107 rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg); 108 RL_SETSTATE(RL_STATE_MOREINPUT); 109 c = rl_read_key (); 110 RL_UNSETSTATE(RL_STATE_MOREINPUT); 111 112 return c; 113} 114 115/* Process C as part of the current numeric argument. Return -1 if the 116 argument should be aborted, 0 if we should not read any more chars, and 117 1 if we should continue to read chars. */ 118int 119_rl_arg_dispatch (cxt, c) 120 _rl_arg_cxt cxt; 121 int c; 122{ 123 int key, r; 124 125 key = c; 126 127 /* If we see a key bound to `universal-argument' after seeing digits, 128 it ends the argument but is otherwise ignored. */ 129 if (_rl_keymap[c].type == ISFUNC && _rl_keymap[c].function == rl_universal_argument) 130 { 131 if ((cxt & NUM_SAWDIGITS) == 0) 132 { 133 rl_numeric_arg *= 4; 134 return 1; 135 } 136 else if (RL_ISSTATE (RL_STATE_CALLBACK)) 137 { 138 _rl_argcxt |= NUM_READONE; 139 return 0; /* XXX */ 140 } 141 else 142 { 143 RL_SETSTATE(RL_STATE_MOREINPUT); 144 key = rl_read_key (); 145 RL_UNSETSTATE(RL_STATE_MOREINPUT); 146 rl_restore_prompt (); 147 rl_clear_message (); 148 RL_UNSETSTATE(RL_STATE_NUMERICARG); 149 if (key < 0) 150 return -1; 151 return (_rl_dispatch (key, _rl_keymap)); 152 } 153 } 154 155 c = UNMETA (c); 156 157 if (_rl_digit_p (c)) 158 { 159 r = _rl_digit_value (c); 160 rl_numeric_arg = rl_explicit_arg ? (rl_numeric_arg * 10) + r : r; 161 rl_explicit_arg = 1; 162 _rl_argcxt |= NUM_SAWDIGITS; 163 } 164 else if (c == '-' && rl_explicit_arg == 0) 165 { 166 rl_numeric_arg = 1; 167 _rl_argcxt |= NUM_SAWMINUS; 168 rl_arg_sign = -1; 169 } 170 else 171 { 172 /* Make M-- command equivalent to M--1 command. */ 173 if ((_rl_argcxt & NUM_SAWMINUS) && rl_numeric_arg == 1 && rl_explicit_arg == 0) 174 rl_explicit_arg = 1; 175 rl_restore_prompt (); 176 rl_clear_message (); 177 RL_UNSETSTATE(RL_STATE_NUMERICARG); 178 179 r = _rl_dispatch (key, _rl_keymap); 180 if (RL_ISSTATE (RL_STATE_CALLBACK)) 181 { 182 /* At worst, this will cause an extra redisplay. Otherwise, 183 we have to wait until the next character comes in. */ 184 if (rl_done == 0) 185 (*rl_redisplay_function) (); 186 r = 0; 187 } 188 return r; 189 } 190 191 return 1; 192} 193 194/* Handle C-u style numeric args, as well as M--, and M-digits. */ 195static int 196rl_digit_loop () 197{ 198 int c, r; 199 200 while (1) 201 { 202 if (_rl_arg_overflow ()) 203 return 1; 204 205 c = _rl_arg_getchar (); 206 207 if (c < 0) 208 { 209 _rl_abort_internal (); 210 return -1; 211 } 212 213 r = _rl_arg_dispatch (_rl_argcxt, c); 214 if (r <= 0 || (RL_ISSTATE (RL_STATE_NUMERICARG) == 0)) 215 break; 216 } 217 218 return r; 219} 220 221/* Create a default argument. */ 222void 223_rl_reset_argument () 224{ 225 rl_numeric_arg = rl_arg_sign = 1; 226 rl_explicit_arg = 0; 227 _rl_argcxt = 0; 228} 229 230/* Start a numeric argument with initial value KEY */ 231int 232rl_digit_argument (ignore, key) 233 int ignore, key; 234{ 235 _rl_arg_init (); 236 if (RL_ISSTATE (RL_STATE_CALLBACK)) 237 { 238 _rl_arg_dispatch (_rl_argcxt, key); 239 rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg); 240 return 0; 241 } 242 else 243 { 244 rl_execute_next (key); 245 return (rl_digit_loop ()); 246 } 247} 248 249/* C-u, universal argument. Multiply the current argument by 4. 250 Read a key. If the key has nothing to do with arguments, then 251 dispatch on it. If the key is the abort character then abort. */ 252int 253rl_universal_argument (count, key) 254 int count, key; 255{ 256 _rl_arg_init (); 257 rl_numeric_arg *= 4; 258 259 return (RL_ISSTATE (RL_STATE_CALLBACK) ? 0 : rl_digit_loop ()); 260} 261 262int 263_rl_arg_callback (cxt) 264 _rl_arg_cxt cxt; 265{ 266 int c, r; 267 268 c = _rl_arg_getchar (); 269 270 if (_rl_argcxt & NUM_READONE) 271 { 272 _rl_argcxt &= ~NUM_READONE; 273 rl_restore_prompt (); 274 rl_clear_message (); 275 RL_UNSETSTATE(RL_STATE_NUMERICARG); 276 rl_execute_next (c); 277 return 0; 278 } 279 280 r = _rl_arg_dispatch (cxt, c); 281 return (r != 1); 282} 283 284/* What to do when you abort reading an argument. */ 285int 286rl_discard_argument () 287{ 288 rl_ding (); 289 rl_clear_message (); 290 _rl_reset_argument (); 291 292 return 0; 293} 294 295/* **************************************************************** */ 296/* */ 297/* History Utilities */ 298/* */ 299/* **************************************************************** */ 300 301/* We already have a history library, and that is what we use to control 302 the history features of readline. This is our local interface to 303 the history mechanism. */ 304 305/* While we are editing the history, this is the saved 306 version of the original line. */ 307HIST_ENTRY *_rl_saved_line_for_history = (HIST_ENTRY *)NULL; 308 309/* Set the history pointer back to the last entry in the history. */ 310void 311_rl_start_using_history () 312{ 313 using_history (); 314 if (_rl_saved_line_for_history) 315 _rl_free_history_entry (_rl_saved_line_for_history); 316 317 _rl_saved_line_for_history = (HIST_ENTRY *)NULL; 318} 319 320/* Free the contents (and containing structure) of a HIST_ENTRY. */ 321void 322_rl_free_history_entry (entry) 323 HIST_ENTRY *entry; 324{ 325 if (entry == 0) 326 return; 327 328 FREE (entry->line); 329 FREE (entry->timestamp); 330 331 free (entry); 332} 333 334/* Perhaps put back the current line if it has changed. */ 335int 336rl_maybe_replace_line () 337{ 338 HIST_ENTRY *temp; 339 340 temp = current_history (); 341 /* If the current line has changed, save the changes. */ 342 if (temp && ((UNDO_LIST *)(temp->data) != rl_undo_list)) 343 { 344 temp = replace_history_entry (where_history (), rl_line_buffer, (histdata_t)rl_undo_list); 345 free (temp->line); 346 FREE (temp->timestamp); 347 free (temp); 348 } 349 return 0; 350} 351 352/* Restore the _rl_saved_line_for_history if there is one. */ 353int 354rl_maybe_unsave_line () 355{ 356 if (_rl_saved_line_for_history) 357 { 358 /* Can't call with `1' because rl_undo_list might point to an undo 359 list from a history entry, as in rl_replace_from_history() below. */ 360 rl_replace_line (_rl_saved_line_for_history->line, 0); 361 rl_undo_list = (UNDO_LIST *)_rl_saved_line_for_history->data; 362 _rl_free_history_entry (_rl_saved_line_for_history); 363 _rl_saved_line_for_history = (HIST_ENTRY *)NULL; 364 rl_point = rl_end; /* rl_replace_line sets rl_end */ 365 } 366 else 367 rl_ding (); 368 return 0; 369} 370 371/* Save the current line in _rl_saved_line_for_history. */ 372int 373rl_maybe_save_line () 374{ 375 if (_rl_saved_line_for_history == 0) 376 { 377 _rl_saved_line_for_history = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY)); 378 _rl_saved_line_for_history->line = savestring (rl_line_buffer); 379 _rl_saved_line_for_history->timestamp = (char *)NULL; 380 _rl_saved_line_for_history->data = (char *)rl_undo_list; 381 } 382 383 return 0; 384} 385 386int 387_rl_free_saved_history_line () 388{ 389 if (_rl_saved_line_for_history) 390 { 391 _rl_free_history_entry (_rl_saved_line_for_history); 392 _rl_saved_line_for_history = (HIST_ENTRY *)NULL; 393 } 394 return 0; 395} 396 397static void 398_rl_history_set_point () 399{ 400 rl_point = (_rl_history_preserve_point && _rl_history_saved_point != -1) 401 ? _rl_history_saved_point 402 : rl_end; 403 if (rl_point > rl_end) 404 rl_point = rl_end; 405 406#if defined (VI_MODE) 407 if (rl_editing_mode == vi_mode && _rl_keymap != vi_insertion_keymap) 408 rl_point = 0; 409#endif /* VI_MODE */ 410 411 if (rl_editing_mode == emacs_mode) 412 rl_mark = (rl_point == rl_end ? 0 : rl_end); 413} 414 415void 416rl_replace_from_history (entry, flags) 417 HIST_ENTRY *entry; 418 int flags; /* currently unused */ 419{ 420 /* Can't call with `1' because rl_undo_list might point to an undo list 421 from a history entry, just like we're setting up here. */ 422 rl_replace_line (entry->line, 0); 423 rl_undo_list = (UNDO_LIST *)entry->data; 424 rl_point = rl_end; 425 rl_mark = 0; 426 427#if defined (VI_MODE) 428 if (rl_editing_mode == vi_mode) 429 { 430 rl_point = 0; 431 rl_mark = rl_end; 432 } 433#endif 434} 435 436/* **************************************************************** */ 437/* */ 438/* History Commands */ 439/* */ 440/* **************************************************************** */ 441 442/* Meta-< goes to the start of the history. */ 443int 444rl_beginning_of_history (count, key) 445 int count, key; 446{ 447 return (rl_get_previous_history (1 + where_history (), key)); 448} 449 450/* Meta-> goes to the end of the history. (The current line). */ 451int 452rl_end_of_history (count, key) 453 int count, key; 454{ 455 rl_maybe_replace_line (); 456 using_history (); 457 rl_maybe_unsave_line (); 458 return 0; 459} 460 461/* Move down to the next history line. */ 462int 463rl_get_next_history (count, key) 464 int count, key; 465{ 466 HIST_ENTRY *temp; 467 468 if (count < 0) 469 return (rl_get_previous_history (-count, key)); 470 471 if (count == 0) 472 return 0; 473 474 rl_maybe_replace_line (); 475 476 /* either not saved by rl_newline or at end of line, so set appropriately. */ 477 if (_rl_history_saved_point == -1 && (rl_point || rl_end)) 478 _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point; 479 480 temp = (HIST_ENTRY *)NULL; 481 while (count) 482 { 483 temp = next_history (); 484 if (!temp) 485 break; 486 --count; 487 } 488 489 if (temp == 0) 490 rl_maybe_unsave_line (); 491 else 492 { 493 rl_replace_from_history (temp, 0); 494 _rl_history_set_point (); 495 } 496 return 0; 497} 498 499/* Get the previous item out of our interactive history, making it the current 500 line. If there is no previous history, just ding. */ 501int 502rl_get_previous_history (count, key) 503 int count, key; 504{ 505 HIST_ENTRY *old_temp, *temp; 506 507 if (count < 0) 508 return (rl_get_next_history (-count, key)); 509 510 if (count == 0) 511 return 0; 512 513 /* either not saved by rl_newline or at end of line, so set appropriately. */ 514 if (_rl_history_saved_point == -1 && (rl_point || rl_end)) 515 _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point; 516 517 /* If we don't have a line saved, then save this one. */ 518 rl_maybe_save_line (); 519 520 /* If the current line has changed, save the changes. */ 521 rl_maybe_replace_line (); 522 523 temp = old_temp = (HIST_ENTRY *)NULL; 524 while (count) 525 { 526 temp = previous_history (); 527 if (temp == 0) 528 break; 529 530 old_temp = temp; 531 --count; 532 } 533 534 /* If there was a large argument, and we moved back to the start of the 535 history, that is not an error. So use the last value found. */ 536 if (!temp && old_temp) 537 temp = old_temp; 538 539 if (temp == 0) 540 rl_ding (); 541 else 542 { 543 rl_replace_from_history (temp, 0); 544 _rl_history_set_point (); 545 } 546 547 return 0; 548} 549 550/* **************************************************************** */ 551/* */ 552/* Editing Modes */ 553/* */ 554/* **************************************************************** */ 555/* How to toggle back and forth between editing modes. */ 556int 557rl_vi_editing_mode (count, key) 558 int count, key; 559{ 560#if defined (VI_MODE) 561 _rl_set_insert_mode (RL_IM_INSERT, 1); /* vi mode ignores insert mode */ 562 rl_editing_mode = vi_mode; 563 rl_vi_insertion_mode (1, key); 564#endif /* VI_MODE */ 565 566 return 0; 567} 568 569int 570rl_emacs_editing_mode (count, key) 571 int count, key; 572{ 573 rl_editing_mode = emacs_mode; 574 _rl_set_insert_mode (RL_IM_INSERT, 1); /* emacs mode default is insert mode */ 575 _rl_keymap = emacs_standard_keymap; 576 return 0; 577} 578 579/* Function for the rest of the library to use to set insert/overwrite mode. */ 580void 581_rl_set_insert_mode (im, force) 582 int im, force; 583{ 584#ifdef CURSOR_MODE 585 _rl_set_cursor (im, force); 586#endif 587 588 rl_insert_mode = im; 589} 590 591/* Toggle overwrite mode. A positive explicit argument selects overwrite 592 mode. A negative or zero explicit argument selects insert mode. */ 593int 594rl_overwrite_mode (count, key) 595 int count, key; 596{ 597 if (rl_explicit_arg == 0) 598 _rl_set_insert_mode (rl_insert_mode ^ 1, 0); 599 else if (count > 0) 600 _rl_set_insert_mode (RL_IM_OVERWRITE, 0); 601 else 602 _rl_set_insert_mode (RL_IM_INSERT, 0); 603 604 return 0; 605} 606