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