| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | /* parens.c -- implementation of matching parentheses feature. */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | /* Copyright (C) 1987, 1989, 1992-2009 Free Software Foundation, Inc.
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |    This file is part of the GNU Readline Library (Readline), a library | 
					
						
							|  |  |  |    for reading lines of text with interactive input and history editing.       | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |    Readline is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  |    it under the terms of the GNU General Public License as published by | 
					
						
							|  |  |  |    the Free Software Foundation, either version 3 of the License, or | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |    (at your option) any later version. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |    Readline 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 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |    GNU General Public License for more details. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |    You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |    along with Readline.  If not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #define READLINE_LIBRARY
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | #if defined (__TANDEM)
 | 
					
						
							|  |  |  | #  include <floss.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #include "rlconf.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #if defined (HAVE_CONFIG_H)
 | 
					
						
							|  |  |  | #  include <config.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  | #include <sys/types.h>
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | #if defined (HAVE_UNISTD_H)
 | 
					
						
							|  |  |  | #  include <unistd.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #if defined (FD_SET) && !defined (HAVE_SELECT)
 | 
					
						
							|  |  |  | #  define HAVE_SELECT
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (HAVE_SELECT)
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #  include <sys/time.h>
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #endif /* HAVE_SELECT */
 | 
					
						
							|  |  |  | #if defined (HAVE_SYS_SELECT_H)
 | 
					
						
							|  |  |  | #  include <sys/select.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (HAVE_STRING_H)
 | 
					
						
							|  |  |  | #  include <string.h>
 | 
					
						
							|  |  |  | #else /* !HAVE_STRING_H */
 | 
					
						
							|  |  |  | #  include <strings.h>
 | 
					
						
							|  |  |  | #endif /* !HAVE_STRING_H */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if !defined (strchr) && !defined (__STDC__)
 | 
					
						
							|  |  |  | extern char *strchr (), *strrchr (); | 
					
						
							|  |  |  | #endif /* !strchr && !__STDC__ */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #include "readline.h"
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | #include "rlprivate.h"
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | static int find_matching_open PARAMS((char *, int, int)); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Non-zero means try to blink the matching open parenthesis when the
 | 
					
						
							|  |  |  |    close parenthesis is inserted. */ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #if defined (HAVE_SELECT)
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | int rl_blink_matching_paren = 1; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #else /* !HAVE_SELECT */
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | int rl_blink_matching_paren = 0; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #endif /* !HAVE_SELECT */
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | static int _paren_blink_usec = 500000; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | /* Change emacs_standard_keymap to have bindings for paren matching when
 | 
					
						
							|  |  |  |    ON_OR_OFF is 1, change them back to self_insert when ON_OR_OFF == 0. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | _rl_enable_paren_matching (on_or_off) | 
					
						
							|  |  |  |      int on_or_off; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (on_or_off) | 
					
						
							|  |  |  |     {	/* ([{ */ | 
					
						
							|  |  |  |       rl_bind_key_in_map (')', rl_insert_close, emacs_standard_keymap); | 
					
						
							|  |  |  |       rl_bind_key_in_map (']', rl_insert_close, emacs_standard_keymap); | 
					
						
							|  |  |  |       rl_bind_key_in_map ('}', rl_insert_close, emacs_standard_keymap); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     {	/* ([{ */ | 
					
						
							|  |  |  |       rl_bind_key_in_map (')', rl_insert, emacs_standard_keymap); | 
					
						
							|  |  |  |       rl_bind_key_in_map (']', rl_insert, emacs_standard_keymap); | 
					
						
							|  |  |  |       rl_bind_key_in_map ('}', rl_insert, emacs_standard_keymap); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | int | 
					
						
							|  |  |  | rl_set_paren_blink_timeout (u) | 
					
						
							|  |  |  |      int u; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   int o; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   o = _paren_blink_usec; | 
					
						
							|  |  |  |   if (u > 0) | 
					
						
							|  |  |  |     _paren_blink_usec = u; | 
					
						
							|  |  |  |   return (o); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | int | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | rl_insert_close (count, invoking_key) | 
					
						
							|  |  |  |      int count, invoking_key; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (rl_explicit_arg || !rl_blink_matching_paren) | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |     _rl_insert_char (count, invoking_key); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #if defined (HAVE_SELECT)
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       int orig_point, match_point, ready; | 
					
						
							|  |  |  |       struct timeval timer; | 
					
						
							|  |  |  |       fd_set readfds; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       _rl_insert_char (1, invoking_key); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       (*rl_redisplay_function) (); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       match_point = | 
					
						
							|  |  |  | 	find_matching_open (rl_line_buffer, rl_point - 2, invoking_key); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* Emacs might message or ring the bell here, but I don't. */ | 
					
						
							|  |  |  |       if (match_point < 0) | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       FD_ZERO (&readfds); | 
					
						
							|  |  |  |       FD_SET (fileno (rl_instream), &readfds); | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |       timer.tv_sec = 0; | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |       timer.tv_usec = _paren_blink_usec; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       orig_point = rl_point; | 
					
						
							|  |  |  |       rl_point = match_point; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       (*rl_redisplay_function) (); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       ready = select (1, &readfds, (fd_set *)NULL, (fd_set *)NULL, &timer); | 
					
						
							|  |  |  |       rl_point = orig_point; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #else /* !HAVE_SELECT */
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       _rl_insert_char (count, invoking_key); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #endif /* !HAVE_SELECT */
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | find_matching_open (string, from, closer) | 
					
						
							|  |  |  |      char *string; | 
					
						
							|  |  |  |      int from, closer; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   register int i; | 
					
						
							|  |  |  |   int opener, level, delimiter; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   switch (closer) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     case ']': opener = '['; break; | 
					
						
							|  |  |  |     case '}': opener = '{'; break; | 
					
						
							|  |  |  |     case ')': opener = '('; break; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       return (-1); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   level = 1;			/* The closer passed in counts as 1. */ | 
					
						
							|  |  |  |   delimiter = 0;		/* Delimited state unknown. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (i = from; i > -1; i--) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (delimiter && (string[i] == delimiter)) | 
					
						
							|  |  |  | 	delimiter = 0; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       else if (rl_basic_quote_characters && strchr (rl_basic_quote_characters, string[i])) | 
					
						
							|  |  |  | 	delimiter = string[i]; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       else if (!delimiter && (string[i] == closer)) | 
					
						
							|  |  |  | 	level++; | 
					
						
							|  |  |  |       else if (!delimiter && (string[i] == opener)) | 
					
						
							|  |  |  | 	level--; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (!level) | 
					
						
							|  |  |  | 	break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   return (i); | 
					
						
							|  |  |  | } |