parens.c revision 47558
1/* parens.c -- Implementation of matching parentheses feature. */
2
3/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
4
5   This file is part of the GNU Readline Library, a library for
6   reading lines of text with interactive input and history editing.
7
8   The GNU Readline Library is free software; you can redistribute it
9   and/or modify it under the terms of the GNU General Public License
10   as published by the Free Software Foundation; either version 1, or
11   (at your option) any later version.
12
13   The GNU Readline Library is distributed in the hope that it will be
14   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
15   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   The GNU General Public License is often shipped with GNU software, and
19   is generally kept in a file called COPYING or LICENSE.  If you do not
20   have a copy of the license, write to the Free Software Foundation,
21   675 Mass Ave, Cambridge, MA 02139, USA. */
22#define READLINE_LIBRARY
23
24#include "rlconf.h"
25
26#if !defined (PAREN_MATCHING)
27extern int rl_insert ();
28
29int
30rl_insert_close (count, invoking_key)
31     int count, invoking_key;
32{
33  return (rl_insert (count, invoking_key));
34}
35
36#else /* PAREN_MATCHING */
37
38#if defined (HAVE_CONFIG_H)
39#  include <config.h>
40#endif
41
42#include <stdio.h>
43#include <sys/types.h>
44
45#if defined (FD_SET) && !defined (HAVE_SELECT)
46#  define HAVE_SELECT
47#endif
48
49#if defined (HAVE_SELECT)
50#  include <sys/time.h>
51#endif /* HAVE_SELECT */
52#if defined (HAVE_SYS_SELECT_H)
53#  include <sys/select.h>
54#endif
55
56#if defined (HAVE_STRING_H)
57#  include <string.h>
58#else /* !HAVE_STRING_H */
59#  include <strings.h>
60#endif /* !HAVE_STRING_H */
61
62#if !defined (strchr) && !defined (__STDC__)
63extern char *strchr (), *strrchr ();
64#endif /* !strchr && !__STDC__ */
65
66#include "readline.h"
67
68extern int rl_explicit_arg;
69
70/* Non-zero means try to blink the matching open parenthesis when the
71   close parenthesis is inserted. */
72#if defined (HAVE_SELECT)
73int rl_blink_matching_paren = 1;
74#else /* !HAVE_SELECT */
75int rl_blink_matching_paren = 0;
76#endif /* !HAVE_SELECT */
77
78static int find_matching_open ();
79
80int
81rl_insert_close (count, invoking_key)
82     int count, invoking_key;
83{
84  if (rl_explicit_arg || !rl_blink_matching_paren)
85    rl_insert (count, invoking_key);
86  else
87    {
88#if defined (HAVE_SELECT)
89      int orig_point, match_point, ready;
90      struct timeval timer;
91      fd_set readfds;
92
93      rl_insert (1, invoking_key);
94      (*rl_redisplay_function) ();
95      match_point =
96	find_matching_open (rl_line_buffer, rl_point - 2, invoking_key);
97
98      /* Emacs might message or ring the bell here, but I don't. */
99      if (match_point < 0)
100	return -1;
101
102      FD_ZERO (&readfds);
103      FD_SET (fileno (rl_instream), &readfds);
104      timer.tv_sec = 0;
105      timer.tv_usec = 500000;
106
107      orig_point = rl_point;
108      rl_point = match_point;
109      (*rl_redisplay_function) ();
110      ready = select (1, &readfds, (fd_set *)NULL, (fd_set *)NULL, &timer);
111      rl_point = orig_point;
112#else /* !HAVE_SELECT */
113      rl_insert (count, invoking_key);
114#endif /* !HAVE_SELECT */
115    }
116  return 0;
117}
118
119static int
120find_matching_open (string, from, closer)
121     char *string;
122     int from, closer;
123{
124  register int i;
125  int opener, level, delimiter;
126
127  switch (closer)
128    {
129    case ']': opener = '['; break;
130    case '}': opener = '{'; break;
131    case ')': opener = '('; break;
132    default:
133      return (-1);
134    }
135
136  level = 1;			/* The closer passed in counts as 1. */
137  delimiter = 0;		/* Delimited state unknown. */
138
139  for (i = from; i > -1; i--)
140    {
141      if (delimiter && (string[i] == delimiter))
142	delimiter = 0;
143      else if (rl_basic_quote_characters && strchr (rl_basic_quote_characters, string[i]))
144	delimiter = string[i];
145      else if (!delimiter && (string[i] == closer))
146	level++;
147      else if (!delimiter && (string[i] == opener))
148	level--;
149
150      if (!level)
151	break;
152    }
153  return (i);
154}
155
156#endif /* PAREN_MATCHING */
157