File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / readline / parens.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 01:01:01 2021 UTC (3 years, 3 months ago) by misho
Branches: readline, MAIN
CVS tags: v8_2p0, v8_1p0, HEAD
readline 8.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>