brac.c revision 60786
160786Sps/*
260786Sps * Copyright (C) 1984-2000  Mark Nudelman
360786Sps *
460786Sps * You may distribute under the terms of either the GNU General Public
560786Sps * License or the Less License, as specified in the README file.
660786Sps *
760786Sps * For more information about less, or for information on how to
860786Sps * contact the author, see the README file.
960786Sps */
1060786Sps
1160786Sps
1260786Sps/*
1360786Sps * Routines to perform bracket matching functions.
1460786Sps */
1560786Sps
1660786Sps#include "less.h"
1760786Sps#include "position.h"
1860786Sps
1960786Sps/*
2060786Sps * Try to match the n-th open bracket
2160786Sps *  which appears in the top displayed line (forwdir),
2260786Sps * or the n-th close bracket
2360786Sps *  which appears in the bottom displayed line (!forwdir).
2460786Sps * The characters which serve as "open bracket" and
2560786Sps * "close bracket" are given.
2660786Sps */
2760786Sps	public void
2860786Spsmatch_brac(obrac, cbrac, forwdir, n)
2960786Sps	register int obrac;
3060786Sps	register int cbrac;
3160786Sps	int forwdir;
3260786Sps	int n;
3360786Sps{
3460786Sps	register int c;
3560786Sps	register int nest;
3660786Sps	POSITION pos;
3760786Sps	int (*chget)();
3860786Sps
3960786Sps	extern int ch_forw_get(), ch_back_get();
4060786Sps
4160786Sps	/*
4260786Sps	 * Seek to the line containing the open bracket.
4360786Sps	 * This is either the top or bottom line on the screen,
4460786Sps	 * depending on the type of bracket.
4560786Sps	 */
4660786Sps	pos = position((forwdir) ? TOP : BOTTOM);
4760786Sps	if (pos == NULL_POSITION || ch_seek(pos))
4860786Sps	{
4960786Sps		if (forwdir)
5060786Sps			error("Nothing in top line", NULL_PARG);
5160786Sps		else
5260786Sps			error("Nothing in bottom line", NULL_PARG);
5360786Sps		return;
5460786Sps	}
5560786Sps
5660786Sps	/*
5760786Sps	 * Look thru the line to find the open bracket to match.
5860786Sps	 */
5960786Sps	do
6060786Sps	{
6160786Sps		if ((c = ch_forw_get()) == '\n' || c == EOI)
6260786Sps		{
6360786Sps			if (forwdir)
6460786Sps				error("No bracket in top line", NULL_PARG);
6560786Sps			else
6660786Sps				error("No bracket in bottom line", NULL_PARG);
6760786Sps			return;
6860786Sps		}
6960786Sps	} while (c != obrac || --n > 0);
7060786Sps
7160786Sps	/*
7260786Sps	 * Position the file just "after" the open bracket
7360786Sps	 * (in the direction in which we will be searching).
7460786Sps	 * If searching forward, we are already after the bracket.
7560786Sps	 * If searching backward, skip back over the open bracket.
7660786Sps	 */
7760786Sps	if (!forwdir)
7860786Sps		(void) ch_back_get();
7960786Sps
8060786Sps	/*
8160786Sps	 * Search the file for the matching bracket.
8260786Sps	 */
8360786Sps	chget = (forwdir) ? ch_forw_get : ch_back_get;
8460786Sps	nest = 0;
8560786Sps	while ((c = (*chget)()) != EOI)
8660786Sps	{
8760786Sps		if (c == obrac)
8860786Sps			nest++;
8960786Sps		else if (c == cbrac && --nest < 0)
9060786Sps		{
9160786Sps			/*
9260786Sps			 * Found the matching bracket.
9360786Sps			 * If searching backward, put it on the top line.
9460786Sps			 * If searching forward, put it on the bottom line.
9560786Sps			 */
9660786Sps			jump_line_loc(ch_tell(), forwdir ? -1 : 1);
9760786Sps			return;
9860786Sps		}
9960786Sps	}
10060786Sps	error("No matching bracket", NULL_PARG);
10160786Sps}
102