| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | /* macro.c -- keyboard macros for readline. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Copyright (C) 1994 Free Software Foundation, Inc.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    This file is part of the GNU Readline Library, a library for | 
					
						
							|  |  |  |    reading lines of text with interactive input and history editing. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    The GNU Readline Library is free software; you can redistribute it | 
					
						
							|  |  |  |    and/or modify it under the terms of the GNU General Public License | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |    as published by the Free Software Foundation; either version 2, or | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |    (at your option) any later version. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    The GNU Readline Library is distributed in the hope that it will be | 
					
						
							|  |  |  |    useful, but WITHOUT ANY WARRANTY; without even the implied warranty | 
					
						
							|  |  |  |    of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |    GNU General Public License for more details. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    The GNU General Public License is often shipped with GNU software, and | 
					
						
							|  |  |  |    is generally kept in a file called COPYING or LICENSE.  If you do not | 
					
						
							|  |  |  |    have a copy of the license, write to the Free Software Foundation, | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |    59 Temple Place, Suite 330, Boston, MA 02111 USA. */ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #define READLINE_LIBRARY
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (HAVE_CONFIG_H)
 | 
					
						
							|  |  |  | #  include <config.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <sys/types.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (HAVE_UNISTD_H)
 | 
					
						
							|  |  |  | #  include <unistd.h>           /* for _POSIX_VERSION */
 | 
					
						
							|  |  |  | #endif /* HAVE_UNISTD_H */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (HAVE_STDLIB_H)
 | 
					
						
							|  |  |  | #  include <stdlib.h>
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #  include "ansi_stdlib.h"
 | 
					
						
							|  |  |  | #endif /* HAVE_STDLIB_H */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* System-specific feature definitions and include files. */ | 
					
						
							|  |  |  | #include "rldefs.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Some standard library routines. */ | 
					
						
							|  |  |  | #include "readline.h"
 | 
					
						
							|  |  |  | #include "history.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | #include "rlprivate.h"
 | 
					
						
							|  |  |  | #include "xmalloc.h"
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | #define SWAP(s, e)  do { int t; t = s; s = e; e = t; } while (0)
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /*			Hacking Keyboard Macros 		    */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Non-zero means to save keys that we dispatch on in a kbd macro. */ | 
					
						
							|  |  |  | int _rl_defining_kbd_macro = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* The currently executing macro string.  If this is non-zero,
 | 
					
						
							|  |  |  |    then it is a malloc ()'ed string where input is coming from. */ | 
					
						
							|  |  |  | char *_rl_executing_macro = (char *)NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* The offset in the above string to the next character to be read. */ | 
					
						
							|  |  |  | static int executing_macro_index; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* The current macro string being built.  Characters get stuffed
 | 
					
						
							|  |  |  |    in here by add_macro_char (). */ | 
					
						
							|  |  |  | static char *current_macro = (char *)NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* The size of the buffer allocated to current_macro. */ | 
					
						
							|  |  |  | static int current_macro_size; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* The index at which characters are being added to current_macro. */ | 
					
						
							|  |  |  | static int current_macro_index; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* A structure used to save nested macro strings.
 | 
					
						
							|  |  |  |    It is a linked list of string/index for each saved macro. */ | 
					
						
							|  |  |  | struct saved_macro { | 
					
						
							|  |  |  |   struct saved_macro *next; | 
					
						
							|  |  |  |   char *string; | 
					
						
							|  |  |  |   int sindex; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* The list of saved macros. */ | 
					
						
							|  |  |  | static struct saved_macro *macro_list = (struct saved_macro *)NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Set up to read subsequent input from STRING.
 | 
					
						
							|  |  |  |    STRING is free ()'ed when we are done with it. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | _rl_with_macro_input (string) | 
					
						
							|  |  |  |      char *string; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   _rl_push_executing_macro (); | 
					
						
							|  |  |  |   _rl_executing_macro = string; | 
					
						
							|  |  |  |   executing_macro_index = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Return the next character available from a macro, or 0 if
 | 
					
						
							|  |  |  |    there are no macro characters. */ | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | _rl_next_macro_key () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (_rl_executing_macro == 0) | 
					
						
							|  |  |  |     return (0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (_rl_executing_macro[executing_macro_index] == 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       _rl_pop_executing_macro (); | 
					
						
							|  |  |  |       return (_rl_next_macro_key ()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (_rl_executing_macro[executing_macro_index++]); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Save the currently executing macro on a stack of saved macros. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | _rl_push_executing_macro () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   struct saved_macro *saver; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   saver = (struct saved_macro *)xmalloc (sizeof (struct saved_macro)); | 
					
						
							|  |  |  |   saver->next = macro_list; | 
					
						
							|  |  |  |   saver->sindex = executing_macro_index; | 
					
						
							|  |  |  |   saver->string = _rl_executing_macro; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   macro_list = saver; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Discard the current macro, replacing it with the one
 | 
					
						
							|  |  |  |    on the top of the stack of saved macros. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | _rl_pop_executing_macro () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   struct saved_macro *macro; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (_rl_executing_macro) | 
					
						
							|  |  |  |     free (_rl_executing_macro); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   _rl_executing_macro = (char *)NULL; | 
					
						
							|  |  |  |   executing_macro_index = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (macro_list) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       macro = macro_list; | 
					
						
							|  |  |  |       _rl_executing_macro = macro_list->string; | 
					
						
							|  |  |  |       executing_macro_index = macro_list->sindex; | 
					
						
							|  |  |  |       macro_list = macro_list->next; | 
					
						
							|  |  |  |       free (macro); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Add a character to the macro being built. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | _rl_add_macro_char (c) | 
					
						
							|  |  |  |      int c; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (current_macro_index + 1 >= current_macro_size) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (current_macro == 0) | 
					
						
							|  |  |  | 	current_macro = xmalloc (current_macro_size = 25); | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	current_macro = xrealloc (current_macro, current_macro_size += 25); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   current_macro[current_macro_index++] = c; | 
					
						
							|  |  |  |   current_macro[current_macro_index] = '\0'; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | _rl_kill_kbd_macro () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (current_macro) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       free (current_macro); | 
					
						
							|  |  |  |       current_macro = (char *) NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   current_macro_size = current_macro_index = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (_rl_executing_macro) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       free (_rl_executing_macro); | 
					
						
							|  |  |  |       _rl_executing_macro = (char *) NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   executing_macro_index = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   _rl_defining_kbd_macro = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Begin defining a keyboard macro.
 | 
					
						
							|  |  |  |    Keystrokes are recorded as they are executed. | 
					
						
							|  |  |  |    End the definition with rl_end_kbd_macro (). | 
					
						
							|  |  |  |    If a numeric argument was explicitly typed, then append this | 
					
						
							|  |  |  |    definition to the end of the existing macro, and start by | 
					
						
							|  |  |  |    re-executing the existing macro. */ | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | rl_start_kbd_macro (ignore1, ignore2) | 
					
						
							|  |  |  |      int ignore1, ignore2; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (_rl_defining_kbd_macro) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       _rl_abort_internal (); | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (rl_explicit_arg) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (current_macro) | 
					
						
							|  |  |  | 	_rl_with_macro_input (savestring (current_macro)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     current_macro_index = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   _rl_defining_kbd_macro = 1; | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Stop defining a keyboard macro.
 | 
					
						
							|  |  |  |    A numeric argument says to execute the macro right now, | 
					
						
							|  |  |  |    that many times, counting the definition as the first time. */ | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | rl_end_kbd_macro (count, ignore) | 
					
						
							|  |  |  |      int count, ignore; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (_rl_defining_kbd_macro == 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       _rl_abort_internal (); | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   current_macro_index -= rl_key_sequence_length - 1; | 
					
						
							|  |  |  |   current_macro[current_macro_index] = '\0'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   _rl_defining_kbd_macro = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (rl_call_last_kbd_macro (--count, 0)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Execute the most recently defined keyboard macro.
 | 
					
						
							|  |  |  |    COUNT says how many times to execute it. */ | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | rl_call_last_kbd_macro (count, ignore) | 
					
						
							|  |  |  |      int count, ignore; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (current_macro == 0) | 
					
						
							|  |  |  |     _rl_abort_internal (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (_rl_defining_kbd_macro) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       ding ();		/* no recursive macros */ | 
					
						
							|  |  |  |       current_macro[--current_macro_index] = '\0';	/* erase this char */ | 
					
						
							|  |  |  |       return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   while (count--) | 
					
						
							|  |  |  |     _rl_with_macro_input (savestring (current_macro)); | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | rl_push_macro_input (macro) | 
					
						
							|  |  |  |      char *macro; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   _rl_with_macro_input (macro); | 
					
						
							|  |  |  | } |