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