parens.c revision 35486
173149Snyan/* parens.c -- Implementation of matching parentheses feature. */ 2119418Sobrien 3119418Sobrien/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. 4119418Sobrien 573149Snyan This file is part of the GNU Readline Library, a library for 673149Snyan reading lines of text with interactive input and history editing. 7139749Simp 873149Snyan The GNU Readline Library is free software; you can redistribute it 973149Snyan and/or modify it under the terms of the GNU General Public License 1073149Snyan as published by the Free Software Foundation; either version 1, or 1173149Snyan (at your option) any later version. 1273149Snyan 1373149Snyan The GNU Readline Library is distributed in the hope that it will be 1473149Snyan useful, but WITHOUT ANY WARRANTY; without even the implied warranty 1573149Snyan of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1673149Snyan GNU General Public License for more details. 1773149Snyan 1873149Snyan The GNU General Public License is often shipped with GNU software, and 1973149Snyan is generally kept in a file called COPYING or LICENSE. If you do not 2073149Snyan have a copy of the license, write to the Free Software Foundation, 2173149Snyan 675 Mass Ave, Cambridge, MA 02139, USA. */ 2273149Snyan#define READLINE_LIBRARY 2373149Snyan 2473149Snyan#include "rlconf.h" 2573149Snyan 2673149Snyan#if !defined (PAREN_MATCHING) 2773149Snyanextern int rl_insert (); 2873149Snyan 2973149Snyanint 3073149Snyanrl_insert_close (count, invoking_key) 3173149Snyan int count, invoking_key; 3273149Snyan{ 3373149Snyan return (rl_insert (count, invoking_key)); 3473149Snyan} 3573149Snyan 3673149Snyan#else /* PAREN_MATCHING */ 3773149Snyan 3873149Snyan#if defined (HAVE_CONFIG_H) 3973149Snyan# include <config.h> 4073149Snyan#endif 4173149Snyan 4273149Snyan#include <stdio.h> 4373149Snyan#include <sys/types.h> 4473149Snyan 45240172Sjhb#if defined (FD_SET) && !defined (HAVE_SELECT) 46240172Sjhb# define HAVE_SELECT 4773149Snyan#endif 4873149Snyan 4973149Snyan#if defined (HAVE_SELECT) 5073149Snyan# include <sys/time.h> 5173149Snyan#endif /* HAVE_SELECT */ 5273149Snyan#if defined (HAVE_SYS_SELECT_H) 5373149Snyan# include <sys/select.h> 5473149Snyan#endif 5579697Snon 5673149Snyan#if defined (HAVE_STRING_H) 57146049Snyan# include <string.h> 5873149Snyan#else /* !HAVE_STRING_H */ 5973149Snyan# include <strings.h> 60126928Speter#endif /* !HAVE_STRING_H */ 6173149Snyan 6273149Snyan#if !defined (strchr) && !defined (__STDC__) 6373149Snyanextern char *strchr (), *strrchr (); 6478209Snyan#endif /* !strchr && !__STDC__ */ 6573149Snyan 6673149Snyan#include "readline.h" 6773149Snyan 6873149Snyanextern int rl_explicit_arg; 6973149Snyan 7073149Snyan/* Non-zero means try to blink the matching open parenthesis when the 7173149Snyan close parenthesis is inserted. */ 7273149Snyan#if defined (HAVE_SELECT) 7373149Snyanint rl_blink_matching_paren = 1; 7473149Snyan#else /* !HAVE_SELECT */ 7573149Snyanint rl_blink_matching_paren = 0; 7673149Snyan#endif /* !HAVE_SELECT */ 7773149Snyan 7873149Snyanstatic int find_matching_open (); 7992739Salfred 8092739Salfredint 8192739Salfredrl_insert_close (count, invoking_key) 8273149Snyan int count, invoking_key; 8373149Snyan{ 8473149Snyan if (rl_explicit_arg || !rl_blink_matching_paren) 8573149Snyan rl_insert (count, invoking_key); 8673149Snyan else 8773149Snyan { 8873149Snyan#if defined (HAVE_SELECT) 8984719Snyan int orig_point, match_point, ready; 9073149Snyan struct timeval timer; 9173149Snyan fd_set readfds; 9273149Snyan 9373149Snyan rl_insert (1, invoking_key); 9473149Snyan (*rl_redisplay_function) (); 9573149Snyan match_point = 9673149Snyan find_matching_open (rl_line_buffer, rl_point - 2, invoking_key); 9773149Snyan 9873149Snyan /* Emacs might message or ring the bell here, but I don't. */ 9973149Snyan if (match_point < 0) 10073149Snyan return -1; 10173149Snyan 10273149Snyan FD_ZERO (&readfds); 10373149Snyan FD_SET (fileno (rl_instream), &readfds); 10473149Snyan timer.tv_sec = 0; 10573149Snyan timer.tv_usec = 500; 10673149Snyan 10773149Snyan orig_point = rl_point; 10873149Snyan rl_point = match_point; 10973149Snyan (*rl_redisplay_function) (); 11073149Snyan ready = select (1, &readfds, (fd_set *)NULL, (fd_set *)NULL, &timer); 11173149Snyan rl_point = orig_point; 11273149Snyan#else /* !HAVE_SELECT */ 11373149Snyan rl_insert (count, invoking_key); 11473149Snyan#endif /* !HAVE_SELECT */ 11579697Snon } 11673149Snyan return 0; 11773149Snyan} 11873149Snyan 11973149Snyanstatic int 12073149Snyanfind_matching_open (string, from, closer) 121114562Snyan char *string; 122114562Snyan int from, closer; 123114562Snyan{ 124114562Snyan register int i; 125114562Snyan int opener, level, delimiter; 126114562Snyan 127114562Snyan switch (closer) 128114562Snyan { 129114562Snyan case ']': opener = '['; break; 13073149Snyan case '}': opener = '{'; break; 13173149Snyan case ')': opener = '('; break; 13273149Snyan default: 13373149Snyan return (-1); 13473149Snyan } 13573149Snyan 13673149Snyan level = 1; /* The closer passed in counts as 1. */ 13773149Snyan delimiter = 0; /* Delimited state unknown. */ 13873149Snyan 13979697Snon for (i = from; i > -1; i--) 14079697Snon { 14179697Snon if (delimiter && (string[i] == delimiter)) 14279697Snon delimiter = 0; 14379697Snon else if (rl_basic_quote_characters && strchr (rl_basic_quote_characters, string[i])) 14479697Snon delimiter = string[i]; 14579697Snon else if (!delimiter && (string[i] == closer)) 14673149Snyan level++; 14773149Snyan else if (!delimiter && (string[i] == opener)) 14873149Snyan level--; 14973149Snyan 15073149Snyan if (!level) 15173149Snyan break; 15279697Snon } 15373149Snyan return (i); 15473149Snyan} 15573149Snyan 15673149Snyan#endif /* PAREN_MATCHING */ 15773149Snyan