misc.c revision 165670
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); 149119610Sache return (_rl_dispatch (key, _rl_keymap)); 150119610Sache } 151119610Sache } 152119610Sache 153157184Sache c = UNMETA (c); 154157184Sache 155157184Sache if (_rl_digit_p (c)) 156157184Sache { 157157184Sache r = _rl_digit_value (c); 158157184Sache rl_numeric_arg = rl_explicit_arg ? (rl_numeric_arg * 10) + r : r; 159157184Sache rl_explicit_arg = 1; 160157184Sache _rl_argcxt |= NUM_SAWDIGITS; 161157184Sache } 162157184Sache else if (c == '-' && rl_explicit_arg == 0) 163157184Sache { 164157184Sache rl_numeric_arg = 1; 165157184Sache _rl_argcxt |= NUM_SAWMINUS; 166157184Sache rl_arg_sign = -1; 167157184Sache } 168157184Sache else 169157184Sache { 170157184Sache /* Make M-- command equivalent to M--1 command. */ 171157184Sache if ((_rl_argcxt & NUM_SAWMINUS) && rl_numeric_arg == 1 && rl_explicit_arg == 0) 172157184Sache rl_explicit_arg = 1; 173157184Sache rl_restore_prompt (); 174157184Sache rl_clear_message (); 175157184Sache RL_UNSETSTATE(RL_STATE_NUMERICARG); 176157184Sache 177157184Sache r = _rl_dispatch (key, _rl_keymap); 178157184Sache if (RL_ISSTATE (RL_STATE_CALLBACK)) 179157184Sache { 180157184Sache /* At worst, this will cause an extra redisplay. Otherwise, 181157184Sache we have to wait until the next character comes in. */ 182157184Sache if (rl_done == 0) 183157184Sache (*rl_redisplay_function) (); 184157184Sache r = 0; 185157184Sache } 186157184Sache return r; 187157184Sache } 188157184Sache 189157184Sache return 1; 190119610Sache} 191119610Sache 192157184Sache/* Handle C-u style numeric args, as well as M--, and M-digits. */ 193157184Sachestatic int 194157184Sacherl_digit_loop () 195119610Sache{ 196157184Sache int c, r; 197119610Sache 198157184Sache while (1) 199157184Sache { 200157184Sache if (_rl_arg_overflow ()) 201157184Sache return 1; 202157184Sache 203157184Sache c = _rl_arg_getchar (); 204157184Sache 205157184Sache if (c < 0) 206157184Sache { 207157184Sache _rl_abort_internal (); 208157184Sache return -1; 209157184Sache } 210157184Sache 211157184Sache r = _rl_arg_dispatch (_rl_argcxt, c); 212157184Sache if (r <= 0 || (RL_ISSTATE (RL_STATE_NUMERICARG) == 0)) 213157184Sache break; 214157184Sache } 215165670Sache 216165670Sache return r; 217119610Sache} 218119610Sache 219119610Sache/* Create a default argument. */ 220157184Sachevoid 221157184Sache_rl_reset_argument () 222119610Sache{ 223119610Sache rl_numeric_arg = rl_arg_sign = 1; 224119610Sache rl_explicit_arg = 0; 225157184Sache _rl_argcxt = 0; 226119610Sache} 227119610Sache 228157184Sache/* Start a numeric argument with initial value KEY */ 229157184Sacheint 230157184Sacherl_digit_argument (ignore, key) 231157184Sache int ignore, key; 232157184Sache{ 233157184Sache _rl_arg_init (); 234157184Sache if (RL_ISSTATE (RL_STATE_CALLBACK)) 235157184Sache { 236157184Sache _rl_arg_dispatch (_rl_argcxt, key); 237157184Sache rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg); 238157184Sache return 0; 239157184Sache } 240157184Sache else 241157184Sache { 242157184Sache rl_execute_next (key); 243157184Sache return (rl_digit_loop ()); 244157184Sache } 245157184Sache} 246157184Sache 247119610Sache/* C-u, universal argument. Multiply the current argument by 4. 248119610Sache Read a key. If the key has nothing to do with arguments, then 249119610Sache dispatch on it. If the key is the abort character then abort. */ 250119610Sacheint 251119610Sacherl_universal_argument (count, key) 252119610Sache int count, key; 253119610Sache{ 254157184Sache _rl_arg_init (); 255119610Sache rl_numeric_arg *= 4; 256157184Sache 257157184Sache return (RL_ISSTATE (RL_STATE_CALLBACK) ? 0 : rl_digit_loop ()); 258119610Sache} 259119610Sache 260157184Sacheint 261157184Sache_rl_arg_callback (cxt) 262157184Sache _rl_arg_cxt cxt; 263157184Sache{ 264157184Sache int c, r; 265157184Sache 266157184Sache c = _rl_arg_getchar (); 267157184Sache 268157184Sache if (_rl_argcxt & NUM_READONE) 269157184Sache { 270157184Sache _rl_argcxt &= ~NUM_READONE; 271157184Sache rl_restore_prompt (); 272157184Sache rl_clear_message (); 273157184Sache RL_UNSETSTATE(RL_STATE_NUMERICARG); 274157184Sache rl_execute_next (c); 275157184Sache return 0; 276157184Sache } 277157184Sache 278157184Sache r = _rl_arg_dispatch (cxt, c); 279157184Sache return (r != 1); 280157184Sache} 281157184Sache 282157184Sache/* What to do when you abort reading an argument. */ 283157184Sacheint 284157184Sacherl_discard_argument () 285157184Sache{ 286157184Sache rl_ding (); 287157184Sache rl_clear_message (); 288157184Sache _rl_reset_argument (); 289157184Sache 290157184Sache return 0; 291157184Sache} 292157184Sache 293119610Sache/* **************************************************************** */ 294119610Sache/* */ 295119610Sache/* History Utilities */ 296119610Sache/* */ 297119610Sache/* **************************************************************** */ 298119610Sache 299119610Sache/* We already have a history library, and that is what we use to control 300119610Sache the history features of readline. This is our local interface to 301119610Sache the history mechanism. */ 302119610Sache 303119610Sache/* While we are editing the history, this is the saved 304119610Sache version of the original line. */ 305119610SacheHIST_ENTRY *_rl_saved_line_for_history = (HIST_ENTRY *)NULL; 306119610Sache 307119610Sache/* Set the history pointer back to the last entry in the history. */ 308119610Sachevoid 309119610Sache_rl_start_using_history () 310119610Sache{ 311119610Sache using_history (); 312119610Sache if (_rl_saved_line_for_history) 313119610Sache _rl_free_history_entry (_rl_saved_line_for_history); 314119610Sache 315119610Sache _rl_saved_line_for_history = (HIST_ENTRY *)NULL; 316119610Sache} 317119610Sache 318119610Sache/* Free the contents (and containing structure) of a HIST_ENTRY. */ 319119610Sachevoid 320119610Sache_rl_free_history_entry (entry) 321119610Sache HIST_ENTRY *entry; 322119610Sache{ 323119610Sache if (entry == 0) 324119610Sache return; 325157184Sache 326157184Sache FREE (entry->line); 327157184Sache FREE (entry->timestamp); 328157184Sache 329119610Sache free (entry); 330119610Sache} 331119610Sache 332119610Sache/* Perhaps put back the current line if it has changed. */ 333119610Sacheint 334119610Sacherl_maybe_replace_line () 335119610Sache{ 336119610Sache HIST_ENTRY *temp; 337119610Sache 338119610Sache temp = current_history (); 339119610Sache /* If the current line has changed, save the changes. */ 340119610Sache if (temp && ((UNDO_LIST *)(temp->data) != rl_undo_list)) 341119610Sache { 342119610Sache temp = replace_history_entry (where_history (), rl_line_buffer, (histdata_t)rl_undo_list); 343119610Sache free (temp->line); 344157184Sache FREE (temp->timestamp); 345119610Sache free (temp); 346119610Sache } 347119610Sache return 0; 348119610Sache} 349119610Sache 350119610Sache/* Restore the _rl_saved_line_for_history if there is one. */ 351119610Sacheint 352119610Sacherl_maybe_unsave_line () 353119610Sache{ 354119610Sache if (_rl_saved_line_for_history) 355119610Sache { 356136644Sache /* Can't call with `1' because rl_undo_list might point to an undo 357136644Sache list from a history entry, as in rl_replace_from_history() below. */ 358119610Sache rl_replace_line (_rl_saved_line_for_history->line, 0); 359119610Sache rl_undo_list = (UNDO_LIST *)_rl_saved_line_for_history->data; 360119610Sache _rl_free_history_entry (_rl_saved_line_for_history); 361119610Sache _rl_saved_line_for_history = (HIST_ENTRY *)NULL; 362119610Sache rl_point = rl_end; /* rl_replace_line sets rl_end */ 363119610Sache } 364119610Sache else 365119610Sache rl_ding (); 366119610Sache return 0; 367119610Sache} 368119610Sache 369119610Sache/* Save the current line in _rl_saved_line_for_history. */ 370119610Sacheint 371119610Sacherl_maybe_save_line () 372119610Sache{ 373119610Sache if (_rl_saved_line_for_history == 0) 374119610Sache { 375119610Sache _rl_saved_line_for_history = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY)); 376119610Sache _rl_saved_line_for_history->line = savestring (rl_line_buffer); 377157184Sache _rl_saved_line_for_history->timestamp = (char *)NULL; 378119610Sache _rl_saved_line_for_history->data = (char *)rl_undo_list; 379119610Sache } 380136644Sache 381119610Sache return 0; 382119610Sache} 383119610Sache 384119610Sacheint 385119610Sache_rl_free_saved_history_line () 386119610Sache{ 387119610Sache if (_rl_saved_line_for_history) 388119610Sache { 389119610Sache _rl_free_history_entry (_rl_saved_line_for_history); 390119610Sache _rl_saved_line_for_history = (HIST_ENTRY *)NULL; 391119610Sache } 392119610Sache return 0; 393119610Sache} 394119610Sache 395119610Sachestatic void 396119610Sache_rl_history_set_point () 397119610Sache{ 398119610Sache rl_point = (_rl_history_preserve_point && _rl_history_saved_point != -1) 399119610Sache ? _rl_history_saved_point 400119610Sache : rl_end; 401119610Sache if (rl_point > rl_end) 402119610Sache rl_point = rl_end; 403119610Sache 404119610Sache#if defined (VI_MODE) 405136644Sache if (rl_editing_mode == vi_mode && _rl_keymap != vi_insertion_keymap) 406119610Sache rl_point = 0; 407119610Sache#endif /* VI_MODE */ 408119610Sache 409119610Sache if (rl_editing_mode == emacs_mode) 410119610Sache rl_mark = (rl_point == rl_end ? 0 : rl_end); 411119610Sache} 412119610Sache 413119610Sachevoid 414119610Sacherl_replace_from_history (entry, flags) 415119610Sache HIST_ENTRY *entry; 416119610Sache int flags; /* currently unused */ 417119610Sache{ 418136644Sache /* Can't call with `1' because rl_undo_list might point to an undo list 419136644Sache from a history entry, just like we're setting up here. */ 420119610Sache rl_replace_line (entry->line, 0); 421119610Sache rl_undo_list = (UNDO_LIST *)entry->data; 422119610Sache rl_point = rl_end; 423119610Sache rl_mark = 0; 424119610Sache 425119610Sache#if defined (VI_MODE) 426119610Sache if (rl_editing_mode == vi_mode) 427119610Sache { 428119610Sache rl_point = 0; 429119610Sache rl_mark = rl_end; 430119610Sache } 431119610Sache#endif 432119610Sache} 433119610Sache 434119610Sache/* **************************************************************** */ 435119610Sache/* */ 436119610Sache/* History Commands */ 437119610Sache/* */ 438119610Sache/* **************************************************************** */ 439119610Sache 440119610Sache/* Meta-< goes to the start of the history. */ 441119610Sacheint 442119610Sacherl_beginning_of_history (count, key) 443119610Sache int count, key; 444119610Sache{ 445119610Sache return (rl_get_previous_history (1 + where_history (), key)); 446119610Sache} 447119610Sache 448119610Sache/* Meta-> goes to the end of the history. (The current line). */ 449119610Sacheint 450119610Sacherl_end_of_history (count, key) 451119610Sache int count, key; 452119610Sache{ 453119610Sache rl_maybe_replace_line (); 454119610Sache using_history (); 455119610Sache rl_maybe_unsave_line (); 456119610Sache return 0; 457119610Sache} 458119610Sache 459119610Sache/* Move down to the next history line. */ 460119610Sacheint 461119610Sacherl_get_next_history (count, key) 462119610Sache int count, key; 463119610Sache{ 464119610Sache HIST_ENTRY *temp; 465119610Sache 466119610Sache if (count < 0) 467119610Sache return (rl_get_previous_history (-count, key)); 468119610Sache 469119610Sache if (count == 0) 470119610Sache return 0; 471119610Sache 472119610Sache rl_maybe_replace_line (); 473119610Sache 474119610Sache /* either not saved by rl_newline or at end of line, so set appropriately. */ 475119610Sache if (_rl_history_saved_point == -1 && (rl_point || rl_end)) 476119610Sache _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point; 477119610Sache 478119610Sache temp = (HIST_ENTRY *)NULL; 479119610Sache while (count) 480119610Sache { 481119610Sache temp = next_history (); 482119610Sache if (!temp) 483119610Sache break; 484119610Sache --count; 485119610Sache } 486119610Sache 487119610Sache if (temp == 0) 488119610Sache rl_maybe_unsave_line (); 489119610Sache else 490119610Sache { 491119610Sache rl_replace_from_history (temp, 0); 492119610Sache _rl_history_set_point (); 493119610Sache } 494119610Sache return 0; 495119610Sache} 496119610Sache 497119610Sache/* Get the previous item out of our interactive history, making it the current 498119610Sache line. If there is no previous history, just ding. */ 499119610Sacheint 500119610Sacherl_get_previous_history (count, key) 501119610Sache int count, key; 502119610Sache{ 503119610Sache HIST_ENTRY *old_temp, *temp; 504119610Sache 505119610Sache if (count < 0) 506119610Sache return (rl_get_next_history (-count, key)); 507119610Sache 508119610Sache if (count == 0) 509119610Sache return 0; 510119610Sache 511119610Sache /* either not saved by rl_newline or at end of line, so set appropriately. */ 512119610Sache if (_rl_history_saved_point == -1 && (rl_point || rl_end)) 513119610Sache _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point; 514119610Sache 515119610Sache /* If we don't have a line saved, then save this one. */ 516119610Sache rl_maybe_save_line (); 517119610Sache 518119610Sache /* If the current line has changed, save the changes. */ 519119610Sache rl_maybe_replace_line (); 520119610Sache 521119610Sache temp = old_temp = (HIST_ENTRY *)NULL; 522119610Sache while (count) 523119610Sache { 524119610Sache temp = previous_history (); 525119610Sache if (temp == 0) 526119610Sache break; 527119610Sache 528119610Sache old_temp = temp; 529119610Sache --count; 530119610Sache } 531119610Sache 532119610Sache /* If there was a large argument, and we moved back to the start of the 533119610Sache history, that is not an error. So use the last value found. */ 534119610Sache if (!temp && old_temp) 535119610Sache temp = old_temp; 536119610Sache 537119610Sache if (temp == 0) 538119610Sache rl_ding (); 539119610Sache else 540119610Sache { 541119610Sache rl_replace_from_history (temp, 0); 542119610Sache _rl_history_set_point (); 543119610Sache } 544136644Sache 545119610Sache return 0; 546119610Sache} 547119610Sache 548119610Sache/* **************************************************************** */ 549119610Sache/* */ 550119610Sache/* Editing Modes */ 551119610Sache/* */ 552119610Sache/* **************************************************************** */ 553119610Sache/* How to toggle back and forth between editing modes. */ 554119610Sacheint 555119610Sacherl_vi_editing_mode (count, key) 556119610Sache int count, key; 557119610Sache{ 558119610Sache#if defined (VI_MODE) 559119610Sache _rl_set_insert_mode (RL_IM_INSERT, 1); /* vi mode ignores insert mode */ 560119610Sache rl_editing_mode = vi_mode; 561119610Sache rl_vi_insertion_mode (1, key); 562119610Sache#endif /* VI_MODE */ 563119610Sache 564119610Sache return 0; 565119610Sache} 566119610Sache 567119610Sacheint 568119610Sacherl_emacs_editing_mode (count, key) 569119610Sache int count, key; 570119610Sache{ 571119610Sache rl_editing_mode = emacs_mode; 572119610Sache _rl_set_insert_mode (RL_IM_INSERT, 1); /* emacs mode default is insert mode */ 573119610Sache _rl_keymap = emacs_standard_keymap; 574119610Sache return 0; 575119610Sache} 576119610Sache 577119610Sache/* Function for the rest of the library to use to set insert/overwrite mode. */ 578119610Sachevoid 579119610Sache_rl_set_insert_mode (im, force) 580119610Sache int im, force; 581119610Sache{ 582119610Sache#ifdef CURSOR_MODE 583119610Sache _rl_set_cursor (im, force); 584119610Sache#endif 585119610Sache 586119610Sache rl_insert_mode = im; 587119610Sache} 588119610Sache 589119610Sache/* Toggle overwrite mode. A positive explicit argument selects overwrite 590119610Sache mode. A negative or zero explicit argument selects insert mode. */ 591119610Sacheint 592119610Sacherl_overwrite_mode (count, key) 593119610Sache int count, key; 594119610Sache{ 595119610Sache if (rl_explicit_arg == 0) 596119610Sache _rl_set_insert_mode (rl_insert_mode ^ 1, 0); 597119610Sache else if (count > 0) 598119610Sache _rl_set_insert_mode (RL_IM_OVERWRITE, 0); 599119610Sache else 600119610Sache _rl_set_insert_mode (RL_IM_INSERT, 0); 601119610Sache 602119610Sache return 0; 603119610Sache} 604