1119610Sache/* misc.c -- miscellaneous bindable readline functions. */ 2119610Sache 3157184Sache/* Copyright (C) 1987-2005 Free Software Foundation, Inc. 4119610Sache 5119610Sache This file is part of the GNU Readline Library, a library for 6119610Sache reading lines of text with interactive input and history editing. 7119610Sache 8119610Sache The GNU Readline Library is free software; you can redistribute it 9119610Sache and/or modify it under the terms of the GNU General Public License 10119610Sache as published by the Free Software Foundation; either version 2, or 11119610Sache (at your option) any later version. 12119610Sache 13119610Sache The GNU Readline Library is distributed in the hope that it will be 14119610Sache useful, but WITHOUT ANY WARRANTY; without even the implied warranty 15119610Sache of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16119610Sache GNU General Public License for more details. 17119610Sache 18119610Sache The GNU General Public License is often shipped with GNU software, and 19119610Sache is generally kept in a file called COPYING or LICENSE. If you do not 20119610Sache have a copy of the license, write to the Free Software Foundation, 21119610Sache 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ 22119610Sache#define READLINE_LIBRARY 23119610Sache 24119610Sache#if defined (HAVE_CONFIG_H) 25119610Sache# include <config.h> 26119610Sache#endif 27119610Sache 28119610Sache#if defined (HAVE_UNISTD_H) 29119610Sache# include <unistd.h> 30119610Sache#endif /* HAVE_UNISTD_H */ 31119610Sache 32119610Sache#if defined (HAVE_STDLIB_H) 33119610Sache# include <stdlib.h> 34119610Sache#else 35119610Sache# include "ansi_stdlib.h" 36119610Sache#endif /* HAVE_STDLIB_H */ 37119610Sache 38119610Sache#if defined (HAVE_LOCALE_H) 39119610Sache# include <locale.h> 40119610Sache#endif 41119610Sache 42119610Sache#include <stdio.h> 43119610Sache 44119610Sache/* System-specific feature definitions and include files. */ 45119610Sache#include "rldefs.h" 46119610Sache#include "rlmbutil.h" 47119610Sache 48119610Sache/* Some standard library routines. */ 49119610Sache#include "readline.h" 50119610Sache#include "history.h" 51119610Sache 52119610Sache#include "rlprivate.h" 53119610Sache#include "rlshell.h" 54119610Sache#include "xmalloc.h" 55119610Sache 56119610Sachestatic int rl_digit_loop PARAMS((void)); 57119610Sachestatic void _rl_history_set_point PARAMS((void)); 58119610Sache 59119610Sache/* Forward declarations used in this file */ 60119610Sachevoid _rl_free_history_entry PARAMS((HIST_ENTRY *)); 61119610Sache 62119610Sache/* If non-zero, rl_get_previous_history and rl_get_next_history attempt 63119610Sache to preserve the value of rl_point from line to line. */ 64119610Sacheint _rl_history_preserve_point = 0; 65119610Sache 66157184Sache_rl_arg_cxt _rl_argcxt; 67157184Sache 68119610Sache/* Saved target point for when _rl_history_preserve_point is set. Special 69119610Sache value of -1 means that point is at the end of the line. */ 70119610Sacheint _rl_history_saved_point = -1; 71119610Sache 72119610Sache/* **************************************************************** */ 73119610Sache/* */ 74119610Sache/* Numeric Arguments */ 75119610Sache/* */ 76119610Sache/* **************************************************************** */ 77119610Sache 78157184Sacheint 79157184Sache_rl_arg_overflow () 80119610Sache{ 81157184Sache if (rl_numeric_arg > 1000000) 82157184Sache { 83157184Sache _rl_argcxt = 0; 84157184Sache rl_explicit_arg = rl_numeric_arg = 0; 85157184Sache rl_ding (); 86157184Sache rl_restore_prompt (); 87157184Sache rl_clear_message (); 88157184Sache RL_UNSETSTATE(RL_STATE_NUMERICARG); 89157184Sache return 1; 90157184Sache } 91157184Sache return 0; 92157184Sache} 93119610Sache 94157184Sachevoid 95157184Sache_rl_arg_init () 96157184Sache{ 97119610Sache rl_save_prompt (); 98157184Sache _rl_argcxt = 0; 99119610Sache RL_SETSTATE(RL_STATE_NUMERICARG); 100157184Sache} 101119610Sache 102157184Sacheint 103157184Sache_rl_arg_getchar () 104157184Sache{ 105157184Sache int c; 106119610Sache 107157184Sache rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg); 108157184Sache RL_SETSTATE(RL_STATE_MOREINPUT); 109157184Sache c = rl_read_key (); 110157184Sache RL_UNSETSTATE(RL_STATE_MOREINPUT); 111119610Sache 112157184Sache return c; 113157184Sache} 114119610Sache 115157184Sache/* Process C as part of the current numeric argument. Return -1 if the 116157184Sache argument should be aborted, 0 if we should not read any more chars, and 117157184Sache 1 if we should continue to read chars. */ 118157184Sacheint 119157184Sache_rl_arg_dispatch (cxt, c) 120157184Sache _rl_arg_cxt cxt; 121157184Sache int c; 122157184Sache{ 123157184Sache int key, r; 124157184Sache 125157184Sache key = c; 126157184Sache 127157184Sache /* If we see a key bound to `universal-argument' after seeing digits, 128157184Sache it ends the argument but is otherwise ignored. */ 129157184Sache if (_rl_keymap[c].type == ISFUNC && _rl_keymap[c].function == rl_universal_argument) 130157184Sache { 131157184Sache if ((cxt & NUM_SAWDIGITS) == 0) 132119610Sache { 133157184Sache rl_numeric_arg *= 4; 134157184Sache return 1; 135119610Sache } 136157184Sache else if (RL_ISSTATE (RL_STATE_CALLBACK)) 137157184Sache { 138157184Sache _rl_argcxt |= NUM_READONE; 139157184Sache return 0; /* XXX */ 140157184Sache } 141119610Sache else 142119610Sache { 143157184Sache RL_SETSTATE(RL_STATE_MOREINPUT); 144157184Sache key = rl_read_key (); 145157184Sache RL_UNSETSTATE(RL_STATE_MOREINPUT); 146119610Sache rl_restore_prompt (); 147119610Sache rl_clear_message (); 148119610Sache RL_UNSETSTATE(RL_STATE_NUMERICARG); 149173403Sache if (key < 0) 150173403Sache return -1; 151119610Sache return (_rl_dispatch (key, _rl_keymap)); 152119610Sache } 153119610Sache } 154119610Sache 155157184Sache c = UNMETA (c); 156157184Sache 157157184Sache if (_rl_digit_p (c)) 158157184Sache { 159157184Sache r = _rl_digit_value (c); 160157184Sache rl_numeric_arg = rl_explicit_arg ? (rl_numeric_arg * 10) + r : r; 161157184Sache rl_explicit_arg = 1; 162157184Sache _rl_argcxt |= NUM_SAWDIGITS; 163157184Sache } 164157184Sache else if (c == '-' && rl_explicit_arg == 0) 165157184Sache { 166157184Sache rl_numeric_arg = 1; 167157184Sache _rl_argcxt |= NUM_SAWMINUS; 168157184Sache rl_arg_sign = -1; 169157184Sache } 170157184Sache else 171157184Sache { 172157184Sache /* Make M-- command equivalent to M--1 command. */ 173157184Sache if ((_rl_argcxt & NUM_SAWMINUS) && rl_numeric_arg == 1 && rl_explicit_arg == 0) 174157184Sache rl_explicit_arg = 1; 175157184Sache rl_restore_prompt (); 176157184Sache rl_clear_message (); 177157184Sache RL_UNSETSTATE(RL_STATE_NUMERICARG); 178157184Sache 179157184Sache r = _rl_dispatch (key, _rl_keymap); 180157184Sache if (RL_ISSTATE (RL_STATE_CALLBACK)) 181157184Sache { 182157184Sache /* At worst, this will cause an extra redisplay. Otherwise, 183157184Sache we have to wait until the next character comes in. */ 184157184Sache if (rl_done == 0) 185157184Sache (*rl_redisplay_function) (); 186157184Sache r = 0; 187157184Sache } 188157184Sache return r; 189157184Sache } 190157184Sache 191157184Sache return 1; 192119610Sache} 193119610Sache 194157184Sache/* Handle C-u style numeric args, as well as M--, and M-digits. */ 195157184Sachestatic int 196157184Sacherl_digit_loop () 197119610Sache{ 198157184Sache int c, r; 199119610Sache 200157184Sache while (1) 201157184Sache { 202157184Sache if (_rl_arg_overflow ()) 203157184Sache return 1; 204157184Sache 205157184Sache c = _rl_arg_getchar (); 206157184Sache 207157184Sache if (c < 0) 208157184Sache { 209157184Sache _rl_abort_internal (); 210157184Sache return -1; 211157184Sache } 212157184Sache 213157184Sache r = _rl_arg_dispatch (_rl_argcxt, c); 214157184Sache if (r <= 0 || (RL_ISSTATE (RL_STATE_NUMERICARG) == 0)) 215157184Sache break; 216157184Sache } 217165670Sache 218165670Sache return r; 219119610Sache} 220119610Sache 221119610Sache/* Create a default argument. */ 222157184Sachevoid 223157184Sache_rl_reset_argument () 224119610Sache{ 225119610Sache rl_numeric_arg = rl_arg_sign = 1; 226119610Sache rl_explicit_arg = 0; 227157184Sache _rl_argcxt = 0; 228119610Sache} 229119610Sache 230157184Sache/* Start a numeric argument with initial value KEY */ 231157184Sacheint 232157184Sacherl_digit_argument (ignore, key) 233157184Sache int ignore, key; 234157184Sache{ 235157184Sache _rl_arg_init (); 236157184Sache if (RL_ISSTATE (RL_STATE_CALLBACK)) 237157184Sache { 238157184Sache _rl_arg_dispatch (_rl_argcxt, key); 239157184Sache rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg); 240157184Sache return 0; 241157184Sache } 242157184Sache else 243157184Sache { 244157184Sache rl_execute_next (key); 245157184Sache return (rl_digit_loop ()); 246157184Sache } 247157184Sache} 248157184Sache 249119610Sache/* C-u, universal argument. Multiply the current argument by 4. 250119610Sache Read a key. If the key has nothing to do with arguments, then 251119610Sache dispatch on it. If the key is the abort character then abort. */ 252119610Sacheint 253119610Sacherl_universal_argument (count, key) 254119610Sache int count, key; 255119610Sache{ 256157184Sache _rl_arg_init (); 257119610Sache rl_numeric_arg *= 4; 258157184Sache 259157184Sache return (RL_ISSTATE (RL_STATE_CALLBACK) ? 0 : rl_digit_loop ()); 260119610Sache} 261119610Sache 262157184Sacheint 263157184Sache_rl_arg_callback (cxt) 264157184Sache _rl_arg_cxt cxt; 265157184Sache{ 266157184Sache int c, r; 267157184Sache 268157184Sache c = _rl_arg_getchar (); 269157184Sache 270157184Sache if (_rl_argcxt & NUM_READONE) 271157184Sache { 272157184Sache _rl_argcxt &= ~NUM_READONE; 273157184Sache rl_restore_prompt (); 274157184Sache rl_clear_message (); 275157184Sache RL_UNSETSTATE(RL_STATE_NUMERICARG); 276157184Sache rl_execute_next (c); 277157184Sache return 0; 278157184Sache } 279157184Sache 280157184Sache r = _rl_arg_dispatch (cxt, c); 281157184Sache return (r != 1); 282157184Sache} 283157184Sache 284157184Sache/* What to do when you abort reading an argument. */ 285157184Sacheint 286157184Sacherl_discard_argument () 287157184Sache{ 288157184Sache rl_ding (); 289157184Sache rl_clear_message (); 290157184Sache _rl_reset_argument (); 291157184Sache 292157184Sache return 0; 293157184Sache} 294157184Sache 295119610Sache/* **************************************************************** */ 296119610Sache/* */ 297119610Sache/* History Utilities */ 298119610Sache/* */ 299119610Sache/* **************************************************************** */ 300119610Sache 301119610Sache/* We already have a history library, and that is what we use to control 302119610Sache the history features of readline. This is our local interface to 303119610Sache the history mechanism. */ 304119610Sache 305119610Sache/* While we are editing the history, this is the saved 306119610Sache version of the original line. */ 307119610SacheHIST_ENTRY *_rl_saved_line_for_history = (HIST_ENTRY *)NULL; 308119610Sache 309119610Sache/* Set the history pointer back to the last entry in the history. */ 310119610Sachevoid 311119610Sache_rl_start_using_history () 312119610Sache{ 313119610Sache using_history (); 314119610Sache if (_rl_saved_line_for_history) 315119610Sache _rl_free_history_entry (_rl_saved_line_for_history); 316119610Sache 317119610Sache _rl_saved_line_for_history = (HIST_ENTRY *)NULL; 318119610Sache} 319119610Sache 320119610Sache/* Free the contents (and containing structure) of a HIST_ENTRY. */ 321119610Sachevoid 322119610Sache_rl_free_history_entry (entry) 323119610Sache HIST_ENTRY *entry; 324119610Sache{ 325119610Sache if (entry == 0) 326119610Sache return; 327157184Sache 328157184Sache FREE (entry->line); 329157184Sache FREE (entry->timestamp); 330157184Sache 331119610Sache free (entry); 332119610Sache} 333119610Sache 334119610Sache/* Perhaps put back the current line if it has changed. */ 335119610Sacheint 336119610Sacherl_maybe_replace_line () 337119610Sache{ 338119610Sache HIST_ENTRY *temp; 339119610Sache 340119610Sache temp = current_history (); 341119610Sache /* If the current line has changed, save the changes. */ 342119610Sache if (temp && ((UNDO_LIST *)(temp->data) != rl_undo_list)) 343119610Sache { 344119610Sache temp = replace_history_entry (where_history (), rl_line_buffer, (histdata_t)rl_undo_list); 345119610Sache free (temp->line); 346157184Sache FREE (temp->timestamp); 347119610Sache free (temp); 348119610Sache } 349119610Sache return 0; 350119610Sache} 351119610Sache 352119610Sache/* Restore the _rl_saved_line_for_history if there is one. */ 353119610Sacheint 354119610Sacherl_maybe_unsave_line () 355119610Sache{ 356119610Sache if (_rl_saved_line_for_history) 357119610Sache { 358136644Sache /* Can't call with `1' because rl_undo_list might point to an undo 359136644Sache list from a history entry, as in rl_replace_from_history() below. */ 360119610Sache rl_replace_line (_rl_saved_line_for_history->line, 0); 361119610Sache rl_undo_list = (UNDO_LIST *)_rl_saved_line_for_history->data; 362119610Sache _rl_free_history_entry (_rl_saved_line_for_history); 363119610Sache _rl_saved_line_for_history = (HIST_ENTRY *)NULL; 364119610Sache rl_point = rl_end; /* rl_replace_line sets rl_end */ 365119610Sache } 366119610Sache else 367119610Sache rl_ding (); 368119610Sache return 0; 369119610Sache} 370119610Sache 371119610Sache/* Save the current line in _rl_saved_line_for_history. */ 372119610Sacheint 373119610Sacherl_maybe_save_line () 374119610Sache{ 375119610Sache if (_rl_saved_line_for_history == 0) 376119610Sache { 377119610Sache _rl_saved_line_for_history = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY)); 378119610Sache _rl_saved_line_for_history->line = savestring (rl_line_buffer); 379157184Sache _rl_saved_line_for_history->timestamp = (char *)NULL; 380119610Sache _rl_saved_line_for_history->data = (char *)rl_undo_list; 381119610Sache } 382136644Sache 383119610Sache return 0; 384119610Sache} 385119610Sache 386119610Sacheint 387119610Sache_rl_free_saved_history_line () 388119610Sache{ 389119610Sache if (_rl_saved_line_for_history) 390119610Sache { 391119610Sache _rl_free_history_entry (_rl_saved_line_for_history); 392119610Sache _rl_saved_line_for_history = (HIST_ENTRY *)NULL; 393119610Sache } 394119610Sache return 0; 395119610Sache} 396119610Sache 397119610Sachestatic void 398119610Sache_rl_history_set_point () 399119610Sache{ 400119610Sache rl_point = (_rl_history_preserve_point && _rl_history_saved_point != -1) 401119610Sache ? _rl_history_saved_point 402119610Sache : rl_end; 403119610Sache if (rl_point > rl_end) 404119610Sache rl_point = rl_end; 405119610Sache 406119610Sache#if defined (VI_MODE) 407136644Sache if (rl_editing_mode == vi_mode && _rl_keymap != vi_insertion_keymap) 408119610Sache rl_point = 0; 409119610Sache#endif /* VI_MODE */ 410119610Sache 411119610Sache if (rl_editing_mode == emacs_mode) 412119610Sache rl_mark = (rl_point == rl_end ? 0 : rl_end); 413119610Sache} 414119610Sache 415119610Sachevoid 416119610Sacherl_replace_from_history (entry, flags) 417119610Sache HIST_ENTRY *entry; 418119610Sache int flags; /* currently unused */ 419119610Sache{ 420136644Sache /* Can't call with `1' because rl_undo_list might point to an undo list 421136644Sache from a history entry, just like we're setting up here. */ 422119610Sache rl_replace_line (entry->line, 0); 423119610Sache rl_undo_list = (UNDO_LIST *)entry->data; 424119610Sache rl_point = rl_end; 425119610Sache rl_mark = 0; 426119610Sache 427119610Sache#if defined (VI_MODE) 428119610Sache if (rl_editing_mode == vi_mode) 429119610Sache { 430119610Sache rl_point = 0; 431119610Sache rl_mark = rl_end; 432119610Sache } 433119610Sache#endif 434119610Sache} 435119610Sache 436119610Sache/* **************************************************************** */ 437119610Sache/* */ 438119610Sache/* History Commands */ 439119610Sache/* */ 440119610Sache/* **************************************************************** */ 441119610Sache 442119610Sache/* Meta-< goes to the start of the history. */ 443119610Sacheint 444119610Sacherl_beginning_of_history (count, key) 445119610Sache int count, key; 446119610Sache{ 447119610Sache return (rl_get_previous_history (1 + where_history (), key)); 448119610Sache} 449119610Sache 450119610Sache/* Meta-> goes to the end of the history. (The current line). */ 451119610Sacheint 452119610Sacherl_end_of_history (count, key) 453119610Sache int count, key; 454119610Sache{ 455119610Sache rl_maybe_replace_line (); 456119610Sache using_history (); 457119610Sache rl_maybe_unsave_line (); 458119610Sache return 0; 459119610Sache} 460119610Sache 461119610Sache/* Move down to the next history line. */ 462119610Sacheint 463119610Sacherl_get_next_history (count, key) 464119610Sache int count, key; 465119610Sache{ 466119610Sache HIST_ENTRY *temp; 467119610Sache 468119610Sache if (count < 0) 469119610Sache return (rl_get_previous_history (-count, key)); 470119610Sache 471119610Sache if (count == 0) 472119610Sache return 0; 473119610Sache 474119610Sache rl_maybe_replace_line (); 475119610Sache 476119610Sache /* either not saved by rl_newline or at end of line, so set appropriately. */ 477119610Sache if (_rl_history_saved_point == -1 && (rl_point || rl_end)) 478119610Sache _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point; 479119610Sache 480119610Sache temp = (HIST_ENTRY *)NULL; 481119610Sache while (count) 482119610Sache { 483119610Sache temp = next_history (); 484119610Sache if (!temp) 485119610Sache break; 486119610Sache --count; 487119610Sache } 488119610Sache 489119610Sache if (temp == 0) 490119610Sache rl_maybe_unsave_line (); 491119610Sache else 492119610Sache { 493119610Sache rl_replace_from_history (temp, 0); 494119610Sache _rl_history_set_point (); 495119610Sache } 496119610Sache return 0; 497119610Sache} 498119610Sache 499119610Sache/* Get the previous item out of our interactive history, making it the current 500119610Sache line. If there is no previous history, just ding. */ 501119610Sacheint 502119610Sacherl_get_previous_history (count, key) 503119610Sache int count, key; 504119610Sache{ 505119610Sache HIST_ENTRY *old_temp, *temp; 506119610Sache 507119610Sache if (count < 0) 508119610Sache return (rl_get_next_history (-count, key)); 509119610Sache 510119610Sache if (count == 0) 511119610Sache return 0; 512119610Sache 513119610Sache /* either not saved by rl_newline or at end of line, so set appropriately. */ 514119610Sache if (_rl_history_saved_point == -1 && (rl_point || rl_end)) 515119610Sache _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point; 516119610Sache 517119610Sache /* If we don't have a line saved, then save this one. */ 518119610Sache rl_maybe_save_line (); 519119610Sache 520119610Sache /* If the current line has changed, save the changes. */ 521119610Sache rl_maybe_replace_line (); 522119610Sache 523119610Sache temp = old_temp = (HIST_ENTRY *)NULL; 524119610Sache while (count) 525119610Sache { 526119610Sache temp = previous_history (); 527119610Sache if (temp == 0) 528119610Sache break; 529119610Sache 530119610Sache old_temp = temp; 531119610Sache --count; 532119610Sache } 533119610Sache 534119610Sache /* If there was a large argument, and we moved back to the start of the 535119610Sache history, that is not an error. So use the last value found. */ 536119610Sache if (!temp && old_temp) 537119610Sache temp = old_temp; 538119610Sache 539119610Sache if (temp == 0) 540119610Sache rl_ding (); 541119610Sache else 542119610Sache { 543119610Sache rl_replace_from_history (temp, 0); 544119610Sache _rl_history_set_point (); 545119610Sache } 546136644Sache 547119610Sache return 0; 548119610Sache} 549119610Sache 550119610Sache/* **************************************************************** */ 551119610Sache/* */ 552119610Sache/* Editing Modes */ 553119610Sache/* */ 554119610Sache/* **************************************************************** */ 555119610Sache/* How to toggle back and forth between editing modes. */ 556119610Sacheint 557119610Sacherl_vi_editing_mode (count, key) 558119610Sache int count, key; 559119610Sache{ 560119610Sache#if defined (VI_MODE) 561119610Sache _rl_set_insert_mode (RL_IM_INSERT, 1); /* vi mode ignores insert mode */ 562119610Sache rl_editing_mode = vi_mode; 563119610Sache rl_vi_insertion_mode (1, key); 564119610Sache#endif /* VI_MODE */ 565119610Sache 566119610Sache return 0; 567119610Sache} 568119610Sache 569119610Sacheint 570119610Sacherl_emacs_editing_mode (count, key) 571119610Sache int count, key; 572119610Sache{ 573119610Sache rl_editing_mode = emacs_mode; 574119610Sache _rl_set_insert_mode (RL_IM_INSERT, 1); /* emacs mode default is insert mode */ 575119610Sache _rl_keymap = emacs_standard_keymap; 576119610Sache return 0; 577119610Sache} 578119610Sache 579119610Sache/* Function for the rest of the library to use to set insert/overwrite mode. */ 580119610Sachevoid 581119610Sache_rl_set_insert_mode (im, force) 582119610Sache int im, force; 583119610Sache{ 584119610Sache#ifdef CURSOR_MODE 585119610Sache _rl_set_cursor (im, force); 586119610Sache#endif 587119610Sache 588119610Sache rl_insert_mode = im; 589119610Sache} 590119610Sache 591119610Sache/* Toggle overwrite mode. A positive explicit argument selects overwrite 592119610Sache mode. A negative or zero explicit argument selects insert mode. */ 593119610Sacheint 594119610Sacherl_overwrite_mode (count, key) 595119610Sache int count, key; 596119610Sache{ 597119610Sache if (rl_explicit_arg == 0) 598119610Sache _rl_set_insert_mode (rl_insert_mode ^ 1, 0); 599119610Sache else if (count > 0) 600119610Sache _rl_set_insert_mode (RL_IM_OVERWRITE, 0); 601119610Sache else 602119610Sache _rl_set_insert_mode (RL_IM_INSERT, 0); 603119610Sache 604119610Sache return 0; 605119610Sache} 606