00001 /* misc.c -- miscellaneous bindable readline functions. */ 00002 00003 /* Copyright (C) 1987-2004 Free Software Foundation, Inc. 00004 00005 This file is part of the GNU Readline Library, a library for 00006 reading lines of text with interactive input and history editing. 00007 00008 The GNU Readline Library is free software; you can redistribute it 00009 and/or modify it under the terms of the GNU General Public License 00010 as published by the Free Software Foundation; either version 2, or 00011 (at your option) any later version. 00012 00013 The GNU Readline Library is distributed in the hope that it will be 00014 useful, but WITHOUT ANY WARRANTY; without even the implied warranty 00015 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 GNU General Public License for more details. 00017 00018 The GNU General Public License is often shipped with GNU software, and 00019 is generally kept in a file called COPYING or LICENSE. If you do not 00020 have a copy of the license, write to the Free Software Foundation, 00021 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ 00022 #define READLINE_LIBRARY 00023 00024 #include "config_readline.h" 00025 00026 #if defined (HAVE_UNISTD_H) 00027 # include <unistd.h> 00028 #endif /* HAVE_UNISTD_H */ 00029 00030 #if defined (HAVE_STDLIB_H) 00031 # include <stdlib.h> 00032 #else 00033 # include "ansi_stdlib.h" 00034 #endif /* HAVE_STDLIB_H */ 00035 00036 #if defined (HAVE_LOCALE_H) 00037 # include <locale.h> 00038 #endif 00039 00040 #include <stdio.h> 00041 00042 /* System-specific feature definitions and include files. */ 00043 #include "rldefs.h" 00044 #include "rlmbutil.h" 00045 00046 /* Some standard library routines. */ 00047 #include "readline.h" 00048 #include "history.h" 00049 00050 #include "rlprivate.h" 00051 #include "rlshell.h" 00052 #include "xmalloc.h" 00053 00054 static int rl_digit_loop PARAMS((void)); 00055 static void _rl_history_set_point PARAMS((void)); 00056 00057 /* Forward declarations used in this file */ 00058 void _rl_free_history_entry PARAMS((HIST_ENTRY *)); 00059 00060 /* If non-zero, rl_get_previous_history and rl_get_next_history attempt 00061 to preserve the value of rl_point from line to line. */ 00062 int _rl_history_preserve_point = 0; 00063 00064 /* Saved target point for when _rl_history_preserve_point is set. Special 00065 value of -1 means that point is at the end of the line. */ 00066 int _rl_history_saved_point = -1; 00067 00068 /* **************************************************************** */ 00069 /* */ 00070 /* Numeric Arguments */ 00071 /* */ 00072 /* **************************************************************** */ 00073 00074 /* Handle C-u style numeric args, as well as M--, and M-digits. */ 00075 static int 00076 rl_digit_loop () 00077 { 00078 int key, c, sawminus, sawdigits; 00079 00080 rl_save_prompt (); 00081 00082 RL_SETSTATE(RL_STATE_NUMERICARG); 00083 sawminus = sawdigits = 0; 00084 while (1) 00085 { 00086 if (rl_numeric_arg > 1000000) 00087 { 00088 sawdigits = rl_explicit_arg = rl_numeric_arg = 0; 00089 rl_ding (); 00090 rl_restore_prompt (); 00091 rl_clear_message (); 00092 RL_UNSETSTATE(RL_STATE_NUMERICARG); 00093 return 1; 00094 } 00095 rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg); 00096 RL_SETSTATE(RL_STATE_MOREINPUT); 00097 key = c = rl_read_key (); 00098 RL_UNSETSTATE(RL_STATE_MOREINPUT); 00099 00100 if (c < 0) 00101 { 00102 _rl_abort_internal (); 00103 return -1; 00104 } 00105 00106 /* If we see a key bound to `universal-argument' after seeing digits, 00107 it ends the argument but is otherwise ignored. */ 00108 if (_rl_keymap[c].type == ISFUNC && 00109 _rl_keymap[c].function == rl_universal_argument) 00110 { 00111 if (sawdigits == 0) 00112 { 00113 rl_numeric_arg *= 4; 00114 continue; 00115 } 00116 else 00117 { 00118 RL_SETSTATE(RL_STATE_MOREINPUT); 00119 key = rl_read_key (); 00120 RL_UNSETSTATE(RL_STATE_MOREINPUT); 00121 rl_restore_prompt (); 00122 rl_clear_message (); 00123 RL_UNSETSTATE(RL_STATE_NUMERICARG); 00124 return (_rl_dispatch (key, _rl_keymap)); 00125 } 00126 } 00127 00128 c = UNMETA (c); 00129 00130 if (_rl_digit_p (c)) 00131 { 00132 rl_numeric_arg = rl_explicit_arg ? (rl_numeric_arg * 10) + c - '0' : c - '0'; 00133 sawdigits = rl_explicit_arg = 1; 00134 } 00135 else if (c == '-' && rl_explicit_arg == 0) 00136 { 00137 rl_numeric_arg = sawminus = 1; 00138 rl_arg_sign = -1; 00139 } 00140 else 00141 { 00142 /* Make M-- command equivalent to M--1 command. */ 00143 if (sawminus && rl_numeric_arg == 1 && rl_explicit_arg == 0) 00144 rl_explicit_arg = 1; 00145 rl_restore_prompt (); 00146 rl_clear_message (); 00147 RL_UNSETSTATE(RL_STATE_NUMERICARG); 00148 return (_rl_dispatch (key, _rl_keymap)); 00149 } 00150 } 00151 00152 /*NOTREACHED*/ 00153 } 00154 00155 /* Add the current digit to the argument in progress. */ 00156 int 00157 rl_digit_argument (ignore, key) 00158 int ignore, key; 00159 { 00160 rl_execute_next (key); 00161 return (rl_digit_loop ()); 00162 } 00163 00164 /* What to do when you abort reading an argument. */ 00165 int 00166 rl_discard_argument () 00167 { 00168 rl_ding (); 00169 rl_clear_message (); 00170 _rl_init_argument (); 00171 return 0; 00172 } 00173 00174 /* Create a default argument. */ 00175 int 00176 _rl_init_argument () 00177 { 00178 rl_numeric_arg = rl_arg_sign = 1; 00179 rl_explicit_arg = 0; 00180 return 0; 00181 } 00182 00183 /* C-u, universal argument. Multiply the current argument by 4. 00184 Read a key. If the key has nothing to do with arguments, then 00185 dispatch on it. If the key is the abort character then abort. */ 00186 int 00187 rl_universal_argument (count, key) 00188 int count, key; 00189 { 00190 rl_numeric_arg *= 4; 00191 return (rl_digit_loop ()); 00192 } 00193 00194 /* **************************************************************** */ 00195 /* */ 00196 /* History Utilities */ 00197 /* */ 00198 /* **************************************************************** */ 00199 00200 /* We already have a history library, and that is what we use to control 00201 the history features of readline. This is our local interface to 00202 the history mechanism. */ 00203 00204 /* While we are editing the history, this is the saved 00205 version of the original line. */ 00206 HIST_ENTRY *_rl_saved_line_for_history = (HIST_ENTRY *)NULL; 00207 00208 /* Set the history pointer back to the last entry in the history. */ 00209 void 00210 _rl_start_using_history () 00211 { 00212 using_history (); 00213 if (_rl_saved_line_for_history) 00214 _rl_free_history_entry (_rl_saved_line_for_history); 00215 00216 _rl_saved_line_for_history = (HIST_ENTRY *)NULL; 00217 } 00218 00219 /* Free the contents (and containing structure) of a HIST_ENTRY. */ 00220 void 00221 _rl_free_history_entry (entry) 00222 HIST_ENTRY *entry; 00223 { 00224 if (entry == 0) 00225 return; 00226 if (entry->line) 00227 free (entry->line); 00228 free (entry); 00229 } 00230 00231 /* Perhaps put back the current line if it has changed. */ 00232 int 00233 rl_maybe_replace_line () 00234 { 00235 HIST_ENTRY *temp; 00236 00237 temp = current_history (); 00238 /* If the current line has changed, save the changes. */ 00239 if (temp && ((UNDO_LIST *)(temp->data) != rl_undo_list)) 00240 { 00241 temp = replace_history_entry (where_history (), rl_line_buffer, (histdata_t)rl_undo_list); 00242 free (temp->line); 00243 free (temp); 00244 } 00245 return 0; 00246 } 00247 00248 /* Restore the _rl_saved_line_for_history if there is one. */ 00249 int 00250 rl_maybe_unsave_line () 00251 { 00252 if (_rl_saved_line_for_history) 00253 { 00254 /* Can't call with `1' because rl_undo_list might point to an undo 00255 list from a history entry, as in rl_replace_from_history() below. */ 00256 rl_replace_line (_rl_saved_line_for_history->line, 0); 00257 rl_undo_list = (UNDO_LIST *)_rl_saved_line_for_history->data; 00258 _rl_free_history_entry (_rl_saved_line_for_history); 00259 _rl_saved_line_for_history = (HIST_ENTRY *)NULL; 00260 rl_point = rl_end; /* rl_replace_line sets rl_end */ 00261 } 00262 else 00263 rl_ding (); 00264 return 0; 00265 } 00266 00267 /* Save the current line in _rl_saved_line_for_history. */ 00268 int 00269 rl_maybe_save_line () 00270 { 00271 if (_rl_saved_line_for_history == 0) 00272 { 00273 _rl_saved_line_for_history = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY)); 00274 _rl_saved_line_for_history->line = savestring (rl_line_buffer); 00275 _rl_saved_line_for_history->data = (char *)rl_undo_list; 00276 } 00277 else if (STREQ (rl_line_buffer, _rl_saved_line_for_history->line) == 0) 00278 { 00279 free (_rl_saved_line_for_history->line); 00280 _rl_saved_line_for_history->line = savestring (rl_line_buffer); 00281 _rl_saved_line_for_history->data = (char *)rl_undo_list; /* XXX possible memleak */ 00282 } 00283 00284 return 0; 00285 } 00286 00287 int 00288 _rl_free_saved_history_line () 00289 { 00290 if (_rl_saved_line_for_history) 00291 { 00292 _rl_free_history_entry (_rl_saved_line_for_history); 00293 _rl_saved_line_for_history = (HIST_ENTRY *)NULL; 00294 } 00295 return 0; 00296 } 00297 00298 static void 00299 _rl_history_set_point () 00300 { 00301 rl_point = (_rl_history_preserve_point && _rl_history_saved_point != -1) 00302 ? _rl_history_saved_point 00303 : rl_end; 00304 if (rl_point > rl_end) 00305 rl_point = rl_end; 00306 00307 #if defined (VI_MODE) 00308 if (rl_editing_mode == vi_mode && _rl_keymap != vi_insertion_keymap) 00309 rl_point = 0; 00310 #endif /* VI_MODE */ 00311 00312 if (rl_editing_mode == emacs_mode) 00313 rl_mark = (rl_point == rl_end ? 0 : rl_end); 00314 } 00315 00316 void 00317 rl_replace_from_history (entry, flags) 00318 HIST_ENTRY *entry; 00319 int flags; /* currently unused */ 00320 { 00321 /* Can't call with `1' because rl_undo_list might point to an undo list 00322 from a history entry, just like we're setting up here. */ 00323 rl_replace_line (entry->line, 0); 00324 rl_undo_list = (UNDO_LIST *)entry->data; 00325 rl_point = rl_end; 00326 rl_mark = 0; 00327 00328 #if defined (VI_MODE) 00329 if (rl_editing_mode == vi_mode) 00330 { 00331 rl_point = 0; 00332 rl_mark = rl_end; 00333 } 00334 #endif 00335 } 00336 00337 /* **************************************************************** */ 00338 /* */ 00339 /* History Commands */ 00340 /* */ 00341 /* **************************************************************** */ 00342 00343 /* Meta-< goes to the start of the history. */ 00344 int 00345 rl_beginning_of_history (count, key) 00346 int count, key; 00347 { 00348 return (rl_get_previous_history (1 + where_history (), key)); 00349 } 00350 00351 /* Meta-> goes to the end of the history. (The current line). */ 00352 int 00353 rl_end_of_history (count, key) 00354 int count, key; 00355 { 00356 rl_maybe_replace_line (); 00357 using_history (); 00358 rl_maybe_unsave_line (); 00359 return 0; 00360 } 00361 00362 /* Move down to the next history line. */ 00363 int 00364 rl_get_next_history (count, key) 00365 int count, key; 00366 { 00367 HIST_ENTRY *temp; 00368 00369 if (count < 0) 00370 return (rl_get_previous_history (-count, key)); 00371 00372 if (count == 0) 00373 return 0; 00374 00375 rl_maybe_replace_line (); 00376 00377 /* either not saved by rl_newline or at end of line, so set appropriately. */ 00378 if (_rl_history_saved_point == -1 && (rl_point || rl_end)) 00379 _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point; 00380 00381 temp = (HIST_ENTRY *)NULL; 00382 while (count) 00383 { 00384 temp = next_history (); 00385 if (!temp) 00386 break; 00387 --count; 00388 } 00389 00390 if (temp == 0) 00391 rl_maybe_unsave_line (); 00392 else 00393 { 00394 rl_replace_from_history (temp, 0); 00395 _rl_history_set_point (); 00396 } 00397 return 0; 00398 } 00399 00400 /* Get the previous item out of our interactive history, making it the current 00401 line. If there is no previous history, just ding. */ 00402 int 00403 rl_get_previous_history (count, key) 00404 int count, key; 00405 { 00406 HIST_ENTRY *old_temp, *temp; 00407 00408 if (count < 0) 00409 return (rl_get_next_history (-count, key)); 00410 00411 if (count == 0) 00412 return 0; 00413 00414 /* either not saved by rl_newline or at end of line, so set appropriately. */ 00415 if (_rl_history_saved_point == -1 && (rl_point || rl_end)) 00416 _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point; 00417 00418 /* If we don't have a line saved, then save this one. */ 00419 rl_maybe_save_line (); 00420 00421 /* If the current line has changed, save the changes. */ 00422 rl_maybe_replace_line (); 00423 00424 temp = old_temp = (HIST_ENTRY *)NULL; 00425 while (count) 00426 { 00427 temp = previous_history (); 00428 if (temp == 0) 00429 break; 00430 00431 old_temp = temp; 00432 --count; 00433 } 00434 00435 /* If there was a large argument, and we moved back to the start of the 00436 history, that is not an error. So use the last value found. */ 00437 if (!temp && old_temp) 00438 temp = old_temp; 00439 00440 if (temp == 0) 00441 rl_ding (); 00442 else 00443 { 00444 rl_replace_from_history (temp, 0); 00445 _rl_history_set_point (); 00446 } 00447 00448 return 0; 00449 } 00450 00451 /* **************************************************************** */ 00452 /* */ 00453 /* Editing Modes */ 00454 /* */ 00455 /* **************************************************************** */ 00456 /* How to toggle back and forth between editing modes. */ 00457 int 00458 rl_vi_editing_mode (count, key) 00459 int count, key; 00460 { 00461 #if defined (VI_MODE) 00462 _rl_set_insert_mode (RL_IM_INSERT, 1); /* vi mode ignores insert mode */ 00463 rl_editing_mode = vi_mode; 00464 rl_vi_insertion_mode (1, key); 00465 #endif /* VI_MODE */ 00466 00467 return 0; 00468 } 00469 00470 int 00471 rl_emacs_editing_mode (count, key) 00472 int count, key; 00473 { 00474 rl_editing_mode = emacs_mode; 00475 _rl_set_insert_mode (RL_IM_INSERT, 1); /* emacs mode default is insert mode */ 00476 _rl_keymap = emacs_standard_keymap; 00477 return 0; 00478 } 00479 00480 /* Function for the rest of the library to use to set insert/overwrite mode. */ 00481 void 00482 _rl_set_insert_mode (im, force) 00483 int im, force; 00484 { 00485 #ifdef CURSOR_MODE 00486 _rl_set_cursor (im, force); 00487 #endif 00488 00489 rl_insert_mode = im; 00490 } 00491 00492 /* Toggle overwrite mode. A positive explicit argument selects overwrite 00493 mode. A negative or zero explicit argument selects insert mode. */ 00494 int 00495 rl_overwrite_mode (count, key) 00496 int count, key; 00497 { 00498 if (rl_explicit_arg == 0) 00499 _rl_set_insert_mode (rl_insert_mode ^ 1, 0); 00500 else if (count > 0) 00501 _rl_set_insert_mode (RL_IM_OVERWRITE, 0); 00502 else 00503 _rl_set_insert_mode (RL_IM_INSERT, 0); 00504 00505 return 0; 00506 }
1.4.7

