Home | History | Annotate | Line # | Download | only in vi
v_match.c revision 1.3.8.2
      1  1.3.8.2  tls /*	$NetBSD: v_match.c,v 1.3.8.2 2014/08/19 23:51:53 tls Exp $ */
      2  1.3.8.2  tls /*-
      3  1.3.8.2  tls  * Copyright (c) 1992, 1993, 1994
      4  1.3.8.2  tls  *	The Regents of the University of California.  All rights reserved.
      5  1.3.8.2  tls  * Copyright (c) 1992, 1993, 1994, 1995, 1996
      6  1.3.8.2  tls  *	Keith Bostic.  All rights reserved.
      7  1.3.8.2  tls  *
      8  1.3.8.2  tls  * See the LICENSE file for redistribution information.
      9  1.3.8.2  tls  */
     10  1.3.8.2  tls 
     11  1.3.8.2  tls #include "config.h"
     12  1.3.8.2  tls 
     13  1.3.8.2  tls #include <sys/cdefs.h>
     14  1.3.8.2  tls #if 0
     15  1.3.8.2  tls #ifndef lint
     16  1.3.8.2  tls static const char sccsid[] = "Id: v_match.c,v 10.10 2001/06/25 15:19:32 skimo Exp  (Berkeley) Date: 2001/06/25 15:19:32 ";
     17  1.3.8.2  tls #endif /* not lint */
     18  1.3.8.2  tls #else
     19  1.3.8.2  tls __RCSID("$NetBSD: v_match.c,v 1.3.8.2 2014/08/19 23:51:53 tls Exp $");
     20  1.3.8.2  tls #endif
     21  1.3.8.2  tls 
     22  1.3.8.2  tls #include <sys/types.h>
     23  1.3.8.2  tls #include <sys/queue.h>
     24  1.3.8.2  tls #include <sys/time.h>
     25  1.3.8.2  tls 
     26  1.3.8.2  tls #include <bitstring.h>
     27  1.3.8.2  tls #include <limits.h>
     28  1.3.8.2  tls #include <stdio.h>
     29  1.3.8.2  tls #include <string.h>
     30  1.3.8.2  tls 
     31  1.3.8.2  tls #include "../common/common.h"
     32  1.3.8.2  tls #include "vi.h"
     33  1.3.8.2  tls 
     34  1.3.8.2  tls /*
     35  1.3.8.2  tls  * v_match -- %
     36  1.3.8.2  tls  *	Search to matching character.
     37  1.3.8.2  tls  *
     38  1.3.8.2  tls  * PUBLIC: int v_match __P((SCR *, VICMD *));
     39  1.3.8.2  tls  */
     40  1.3.8.2  tls int
     41  1.3.8.2  tls v_match(SCR *sp, VICMD *vp)
     42  1.3.8.2  tls {
     43  1.3.8.2  tls 	VCS cs;
     44  1.3.8.2  tls 	MARK *mp;
     45  1.3.8.2  tls 	size_t cno, len, off;
     46  1.3.8.2  tls 	int cnt, isempty, matchc, startc, (*gc)__P((SCR *, VCS *));
     47  1.3.8.2  tls 	CHAR_T *p;
     48  1.3.8.2  tls 	char *cp;
     49  1.3.8.2  tls 	const char *match_chars;
     50  1.3.8.2  tls 
     51  1.3.8.2  tls 	static MARK match = { 0, 0 };
     52  1.3.8.2  tls 	static int match_dir;
     53  1.3.8.2  tls 
     54  1.3.8.2  tls 	/*
     55  1.3.8.2  tls 	 * Historically vi would match (), {} and [] however
     56  1.3.8.2  tls 	 * an update included <>.  This is ok for editing HTML
     57  1.3.8.2  tls 	 * but a pain in the butt for C source.
     58  1.3.8.2  tls 	 * Making it an option lets the user decide what is 'right'.
     59  1.3.8.2  tls 	 * Also fixed to do something sensible with "".
     60  1.3.8.2  tls 	 */
     61  1.3.8.2  tls 	match_chars = O_STR(sp, O_MATCHCHARS);
     62  1.3.8.2  tls 
     63  1.3.8.2  tls 	/*
     64  1.3.8.2  tls 	 * !!!
     65  1.3.8.2  tls 	 * Historic practice; ignore the count.
     66  1.3.8.2  tls 	 *
     67  1.3.8.2  tls 	 * !!!
     68  1.3.8.2  tls 	 * Historical practice was to search for the initial character in the
     69  1.3.8.2  tls 	 * forward direction only.
     70  1.3.8.2  tls 	 */
     71  1.3.8.2  tls 	if (db_eget(sp, vp->m_start.lno, &p, &len, &isempty)) {
     72  1.3.8.2  tls 		if (isempty)
     73  1.3.8.2  tls 			goto nomatch;
     74  1.3.8.2  tls 		return (1);
     75  1.3.8.2  tls 	}
     76  1.3.8.2  tls 	for (off = vp->m_start.cno;; ++off) {
     77  1.3.8.2  tls 		if (off >= len) {
     78  1.3.8.2  tls nomatch:		msgq(sp, M_BERR, "184|No match character on this line");
     79  1.3.8.2  tls 			return (1);
     80  1.3.8.2  tls 		}
     81  1.3.8.2  tls 		startc = p[off];
     82  1.3.8.2  tls 		cp = strchr(match_chars, startc);
     83  1.3.8.2  tls 		if (cp != NULL)
     84  1.3.8.2  tls 			break;
     85  1.3.8.2  tls 	}
     86  1.3.8.2  tls 	cnt = cp - match_chars;
     87  1.3.8.2  tls 	matchc = match_chars[cnt ^ 1];
     88  1.3.8.2  tls 
     89  1.3.8.2  tls 	/* Alternate back-forward search if startc and matchc the same */
     90  1.3.8.2  tls 	if (startc == matchc) {
     91  1.3.8.2  tls 		/* are we continuing from where last match finished? */
     92  1.3.8.2  tls 		if (match.lno == vp->m_start.lno && match.cno ==vp->m_start.cno)
     93  1.3.8.2  tls 			/* yes - continue in sequence */
     94  1.3.8.2  tls 			match_dir++;
     95  1.3.8.2  tls 		else
     96  1.3.8.2  tls 			/* no - go forward, back, back, forward */
     97  1.3.8.2  tls 			match_dir = 1;
     98  1.3.8.2  tls 		if (match_dir & 2)
     99  1.3.8.2  tls 			cnt++;
    100  1.3.8.2  tls 	}
    101  1.3.8.2  tls 	gc = cnt & 1 ? cs_prev : cs_next;
    102  1.3.8.2  tls 
    103  1.3.8.2  tls 	cs.cs_lno = vp->m_start.lno;
    104  1.3.8.2  tls 	cs.cs_cno = off;
    105  1.3.8.2  tls 	if (cs_init(sp, &cs))
    106  1.3.8.2  tls 		return (1);
    107  1.3.8.2  tls 	for (cnt = 1;;) {
    108  1.3.8.2  tls 		if (gc(sp, &cs))
    109  1.3.8.2  tls 			return (1);
    110  1.3.8.2  tls 		if (cs.cs_flags != 0) {
    111  1.3.8.2  tls 			if (cs.cs_flags == CS_EOF || cs.cs_flags == CS_SOF)
    112  1.3.8.2  tls 				break;
    113  1.3.8.2  tls 			continue;
    114  1.3.8.2  tls 		}
    115  1.3.8.2  tls 		if (cs.cs_ch == matchc && --cnt == 0)
    116  1.3.8.2  tls 			break;
    117  1.3.8.2  tls 		if (cs.cs_ch == startc)
    118  1.3.8.2  tls 			++cnt;
    119  1.3.8.2  tls 	}
    120  1.3.8.2  tls 	if (cnt) {
    121  1.3.8.2  tls 		msgq(sp, M_BERR, "185|Matching character not found");
    122  1.3.8.2  tls 		return (1);
    123  1.3.8.2  tls 	}
    124  1.3.8.2  tls 
    125  1.3.8.2  tls 	vp->m_stop.lno = cs.cs_lno;
    126  1.3.8.2  tls 	vp->m_stop.cno = cs.cs_cno;
    127  1.3.8.2  tls 
    128  1.3.8.2  tls 	/*
    129  1.3.8.2  tls 	 * If moving right, non-motion commands move to the end of the range.
    130  1.3.8.2  tls 	 * Delete and yank stay at the start.
    131  1.3.8.2  tls 	 *
    132  1.3.8.2  tls 	 * If moving left, all commands move to the end of the range.
    133  1.3.8.2  tls 	 *
    134  1.3.8.2  tls 	 * !!!
    135  1.3.8.2  tls 	 * Don't correct for leftward movement -- historic vi deleted the
    136  1.3.8.2  tls 	 * starting cursor position when deleting to a match.
    137  1.3.8.2  tls 	 */
    138  1.3.8.2  tls 	if (vp->m_start.lno < vp->m_stop.lno ||
    139  1.3.8.2  tls 	    (vp->m_start.lno == vp->m_stop.lno &&
    140  1.3.8.2  tls 	    vp->m_start.cno < vp->m_stop.cno))
    141  1.3.8.2  tls 		vp->m_final = ISMOTION(vp) ? vp->m_start : vp->m_stop;
    142  1.3.8.2  tls 	else
    143  1.3.8.2  tls 		vp->m_final = vp->m_stop;
    144  1.3.8.2  tls 
    145  1.3.8.2  tls 	match.lno = vp->m_final.lno;
    146  1.3.8.2  tls 	match.cno = vp->m_final.cno;
    147  1.3.8.2  tls 
    148  1.3.8.2  tls 	/*
    149  1.3.8.2  tls 	 * !!!
    150  1.3.8.2  tls 	 * If the motion is across lines, and the earliest cursor position
    151  1.3.8.2  tls 	 * is at or before any non-blank characters in the line, i.e. the
    152  1.3.8.2  tls 	 * movement is cutting all of the line's text, and the later cursor
    153  1.3.8.2  tls 	 * position has nothing other than whitespace characters between it
    154  1.3.8.2  tls 	 * and the end of its line, the buffer is in line mode.
    155  1.3.8.2  tls 	 */
    156  1.3.8.2  tls 	if (!ISMOTION(vp) || vp->m_start.lno == vp->m_stop.lno)
    157  1.3.8.2  tls 		return (0);
    158  1.3.8.2  tls 	mp = vp->m_start.lno < vp->m_stop.lno ? &vp->m_start : &vp->m_stop;
    159  1.3.8.2  tls 	if (mp->cno != 0) {
    160  1.3.8.2  tls 		cno = 0;
    161  1.3.8.2  tls 		if (nonblank(sp, mp->lno, &cno))
    162  1.3.8.2  tls 			return (1);
    163  1.3.8.2  tls 		if (cno < mp->cno)
    164  1.3.8.2  tls 			return (0);
    165  1.3.8.2  tls 	}
    166  1.3.8.2  tls 	mp = vp->m_start.lno < vp->m_stop.lno ? &vp->m_stop : &vp->m_start;
    167  1.3.8.2  tls 	if (db_get(sp, mp->lno, DBG_FATAL, &p, &len))
    168  1.3.8.2  tls 		return (1);
    169  1.3.8.2  tls 	for (p += mp->cno + 1, len -= mp->cno; --len; ++p)
    170  1.3.8.2  tls 		if (!ISBLANK((UCHAR_T)*p))
    171  1.3.8.2  tls 			return (0);
    172  1.3.8.2  tls 	F_SET(vp, VM_LMODE);
    173  1.3.8.2  tls 	return (0);
    174  1.3.8.2  tls }
    175