brac.c revision 60786
1219019Sgabor/*
2219019Sgabor * Copyright (C) 1984-2000  Mark Nudelman
3219019Sgabor *
4219019Sgabor * You may distribute under the terms of either the GNU General Public
5219019Sgabor * License or the Less License, as specified in the README file.
6219019Sgabor *
7219019Sgabor * For more information about less, or for information on how to
8219019Sgabor * contact the author, see the README file.
9219019Sgabor */
10219019Sgabor
11219019Sgabor
12219019Sgabor/*
13219019Sgabor * Routines to perform bracket matching functions.
14219019Sgabor */
15219019Sgabor
16219019Sgabor#include "less.h"
17219019Sgabor#include "position.h"
18219019Sgabor
19219019Sgabor/*
20219019Sgabor * Try to match the n-th open bracket
21219019Sgabor *  which appears in the top displayed line (forwdir),
22219019Sgabor * or the n-th close bracket
23219019Sgabor *  which appears in the bottom displayed line (!forwdir).
24219019Sgabor * The characters which serve as "open bracket" and
25219019Sgabor * "close bracket" are given.
26219019Sgabor */
27219019Sgabor	public void
28219019Sgabormatch_brac(obrac, cbrac, forwdir, n)
29219019Sgabor	register int obrac;
30219019Sgabor	register int cbrac;
31219019Sgabor	int forwdir;
32219019Sgabor	int n;
33219019Sgabor{
34219019Sgabor	register int c;
35219019Sgabor	register int nest;
36219019Sgabor	POSITION pos;
37219019Sgabor	int (*chget)();
38219019Sgabor
39219019Sgabor	extern int ch_forw_get(), ch_back_get();
40219019Sgabor
41219019Sgabor	/*
42219019Sgabor	 * Seek to the line containing the open bracket.
43219019Sgabor	 * This is either the top or bottom line on the screen,
44219019Sgabor	 * depending on the type of bracket.
45219019Sgabor	 */
46219019Sgabor	pos = position((forwdir) ? TOP : BOTTOM);
47219019Sgabor	if (pos == NULL_POSITION || ch_seek(pos))
48219019Sgabor	{
49219019Sgabor		if (forwdir)
50219019Sgabor			error("Nothing in top line", NULL_PARG);
51219019Sgabor		else
52219019Sgabor			error("Nothing in bottom line", NULL_PARG);
53219019Sgabor		return;
54219019Sgabor	}
55219019Sgabor
56219019Sgabor	/*
57219019Sgabor	 * Look thru the line to find the open bracket to match.
58219019Sgabor	 */
59219019Sgabor	do
60219019Sgabor	{
61219019Sgabor		if ((c = ch_forw_get()) == '\n' || c == EOI)
62219019Sgabor		{
63219019Sgabor			if (forwdir)
64219019Sgabor				error("No bracket in top line", NULL_PARG);
65219019Sgabor			else
66219019Sgabor				error("No bracket in bottom line", NULL_PARG);
67219019Sgabor			return;
68219019Sgabor		}
69219019Sgabor	} while (c != obrac || --n > 0);
70219019Sgabor
71219019Sgabor	/*
72219019Sgabor	 * Position the file just "after" the open bracket
73219019Sgabor	 * (in the direction in which we will be searching).
74219019Sgabor	 * If searching forward, we are already after the bracket.
75219019Sgabor	 * If searching backward, skip back over the open bracket.
76219019Sgabor	 */
77219019Sgabor	if (!forwdir)
78219019Sgabor		(void) ch_back_get();
79219019Sgabor
80219019Sgabor	/*
81219019Sgabor	 * Search the file for the matching bracket.
82219019Sgabor	 */
83219019Sgabor	chget = (forwdir) ? ch_forw_get : ch_back_get;
84219019Sgabor	nest = 0;
85219019Sgabor	while ((c = (*chget)()) != EOI)
86219019Sgabor	{
87219019Sgabor		if (c == obrac)
88219019Sgabor			nest++;
89219019Sgabor		else if (c == cbrac && --nest < 0)
90219019Sgabor		{
91219019Sgabor			/*
92219019Sgabor			 * Found the matching bracket.
93219019Sgabor			 * If searching backward, put it on the top line.
94219019Sgabor			 * If searching forward, put it on the bottom line.
95219019Sgabor			 */
96219019Sgabor			jump_line_loc(ch_tell(), forwdir ? -1 : 1);
97219019Sgabor			return;
98219019Sgabor		}
99219019Sgabor	}
100219019Sgabor	error("No matching bracket", NULL_PARG);
101219019Sgabor}
102219019Sgabor