121308Sache/* parens.c -- Implementation of matching parentheses feature. */ 221308Sache 321308Sache/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. 421308Sache 521308Sache This file is part of the GNU Readline Library, a library for 621308Sache reading lines of text with interactive input and history editing. 721308Sache 821308Sache The GNU Readline Library is free software; you can redistribute it 921308Sache and/or modify it under the terms of the GNU General Public License 1058310Sache as published by the Free Software Foundation; either version 2, or 1121308Sache (at your option) any later version. 1221308Sache 1321308Sache The GNU Readline Library is distributed in the hope that it will be 1421308Sache useful, but WITHOUT ANY WARRANTY; without even the implied warranty 1521308Sache of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1621308Sache GNU General Public License for more details. 1721308Sache 1821308Sache The GNU General Public License is often shipped with GNU software, and 1921308Sache is generally kept in a file called COPYING or LICENSE. If you do not 2021308Sache have a copy of the license, write to the Free Software Foundation, 2158310Sache 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ 2221308Sache#define READLINE_LIBRARY 2321308Sache 24136644Sache#if defined (__TANDEM) 25136644Sache# include <floss.h> 26136644Sache#endif 27136644Sache 2821308Sache#include "rlconf.h" 2921308Sache 3021308Sache#if defined (HAVE_CONFIG_H) 3121308Sache# include <config.h> 3221308Sache#endif 3321308Sache 3421308Sache#include <stdio.h> 3521308Sache#include <sys/types.h> 3621308Sache 37119610Sache#if defined (HAVE_UNISTD_H) 38119610Sache# include <unistd.h> 39119610Sache#endif 40119610Sache 4121308Sache#if defined (FD_SET) && !defined (HAVE_SELECT) 4221308Sache# define HAVE_SELECT 4321308Sache#endif 4421308Sache 4521308Sache#if defined (HAVE_SELECT) 4621308Sache# include <sys/time.h> 4721308Sache#endif /* HAVE_SELECT */ 4821308Sache#if defined (HAVE_SYS_SELECT_H) 4921308Sache# include <sys/select.h> 5021308Sache#endif 5121308Sache 5221308Sache#if defined (HAVE_STRING_H) 5321308Sache# include <string.h> 5421308Sache#else /* !HAVE_STRING_H */ 5521308Sache# include <strings.h> 5621308Sache#endif /* !HAVE_STRING_H */ 5721308Sache 5821308Sache#if !defined (strchr) && !defined (__STDC__) 5921308Sacheextern char *strchr (), *strrchr (); 6021308Sache#endif /* !strchr && !__STDC__ */ 6121308Sache 6221308Sache#include "readline.h" 6358310Sache#include "rlprivate.h" 6421308Sache 65119610Sachestatic int find_matching_open PARAMS((char *, int, int)); 6621308Sache 6721308Sache/* Non-zero means try to blink the matching open parenthesis when the 6821308Sache close parenthesis is inserted. */ 6921308Sache#if defined (HAVE_SELECT) 7021308Sacheint rl_blink_matching_paren = 1; 7121308Sache#else /* !HAVE_SELECT */ 7221308Sacheint rl_blink_matching_paren = 0; 7321308Sache#endif /* !HAVE_SELECT */ 7421308Sache 7575406Sachestatic int _paren_blink_usec = 500000; 7675406Sache 7758310Sache/* Change emacs_standard_keymap to have bindings for paren matching when 7858310Sache ON_OR_OFF is 1, change them back to self_insert when ON_OR_OFF == 0. */ 7958310Sachevoid 8058310Sache_rl_enable_paren_matching (on_or_off) 8158310Sache int on_or_off; 8258310Sache{ 8358310Sache if (on_or_off) 8458310Sache { /* ([{ */ 8558310Sache rl_bind_key_in_map (')', rl_insert_close, emacs_standard_keymap); 8658310Sache rl_bind_key_in_map (']', rl_insert_close, emacs_standard_keymap); 8758310Sache rl_bind_key_in_map ('}', rl_insert_close, emacs_standard_keymap); 8858310Sache } 8958310Sache else 9058310Sache { /* ([{ */ 9158310Sache rl_bind_key_in_map (')', rl_insert, emacs_standard_keymap); 9258310Sache rl_bind_key_in_map (']', rl_insert, emacs_standard_keymap); 9358310Sache rl_bind_key_in_map ('}', rl_insert, emacs_standard_keymap); 9458310Sache } 9558310Sache} 9621308Sache 9721308Sacheint 9875406Sacherl_set_paren_blink_timeout (u) 9975406Sache int u; 10075406Sache{ 10175406Sache int o; 10275406Sache 10375406Sache o = _paren_blink_usec; 10475406Sache if (u > 0) 10575406Sache _paren_blink_usec = u; 10675406Sache return (o); 10775406Sache} 10875406Sache 10975406Sacheint 11021308Sacherl_insert_close (count, invoking_key) 11121308Sache int count, invoking_key; 11221308Sache{ 11321308Sache if (rl_explicit_arg || !rl_blink_matching_paren) 114119610Sache _rl_insert_char (count, invoking_key); 11521308Sache else 11621308Sache { 11721308Sache#if defined (HAVE_SELECT) 11821308Sache int orig_point, match_point, ready; 11921308Sache struct timeval timer; 12021308Sache fd_set readfds; 12121308Sache 122119610Sache _rl_insert_char (1, invoking_key); 12321308Sache (*rl_redisplay_function) (); 12421308Sache match_point = 12521308Sache find_matching_open (rl_line_buffer, rl_point - 2, invoking_key); 12621308Sache 12721308Sache /* Emacs might message or ring the bell here, but I don't. */ 12821308Sache if (match_point < 0) 12921308Sache return -1; 13021308Sache 13121308Sache FD_ZERO (&readfds); 13221308Sache FD_SET (fileno (rl_instream), &readfds); 13335486Sache timer.tv_sec = 0; 13475406Sache timer.tv_usec = _paren_blink_usec; 13521308Sache 13621308Sache orig_point = rl_point; 13721308Sache rl_point = match_point; 13821308Sache (*rl_redisplay_function) (); 13921308Sache ready = select (1, &readfds, (fd_set *)NULL, (fd_set *)NULL, &timer); 14021308Sache rl_point = orig_point; 14121308Sache#else /* !HAVE_SELECT */ 142119610Sache _rl_insert_char (count, invoking_key); 14321308Sache#endif /* !HAVE_SELECT */ 14421308Sache } 14521308Sache return 0; 14621308Sache} 14721308Sache 14821308Sachestatic int 14921308Sachefind_matching_open (string, from, closer) 15021308Sache char *string; 15121308Sache int from, closer; 15221308Sache{ 15321308Sache register int i; 15421308Sache int opener, level, delimiter; 15521308Sache 15621308Sache switch (closer) 15721308Sache { 15821308Sache case ']': opener = '['; break; 15921308Sache case '}': opener = '{'; break; 16021308Sache case ')': opener = '('; break; 16121308Sache default: 16221308Sache return (-1); 16321308Sache } 16421308Sache 16521308Sache level = 1; /* The closer passed in counts as 1. */ 16621308Sache delimiter = 0; /* Delimited state unknown. */ 16721308Sache 16821308Sache for (i = from; i > -1; i--) 16921308Sache { 17021308Sache if (delimiter && (string[i] == delimiter)) 17121308Sache delimiter = 0; 17221308Sache else if (rl_basic_quote_characters && strchr (rl_basic_quote_characters, string[i])) 17321308Sache delimiter = string[i]; 17421308Sache else if (!delimiter && (string[i] == closer)) 17521308Sache level++; 17621308Sache else if (!delimiter && (string[i] == opener)) 17721308Sache level--; 17821308Sache 17921308Sache if (!level) 18021308Sache break; 18121308Sache } 18221308Sache return (i); 18321308Sache} 184