brac.c revision 330571
1/*
2 * Copyright (C) 1984-2017  Mark Nudelman
3 *
4 * You may distribute under the terms of either the GNU General Public
5 * License or the Less License, as specified in the README file.
6 *
7 * For more information, see the README file.
8 */
9
10
11/*
12 * Routines to perform bracket matching functions.
13 */
14
15#include "less.h"
16#include "position.h"
17
18/*
19 * Try to match the n-th open bracket
20 *  which appears in the top displayed line (forwdir),
21 * or the n-th close bracket
22 *  which appears in the bottom displayed line (!forwdir).
23 * The characters which serve as "open bracket" and
24 * "close bracket" are given.
25 */
26	public void
27match_brac(obrac, cbrac, forwdir, n)
28	int obrac;
29	int cbrac;
30	int forwdir;
31	int n;
32{
33	int c;
34	int nest;
35	POSITION pos;
36	int (*chget)();
37
38	extern int ch_forw_get(), ch_back_get();
39
40	/*
41	 * Seek to the line containing the open bracket.
42	 * This is either the top or bottom line on the screen,
43	 * depending on the type of bracket.
44	 */
45	pos = position((forwdir) ? TOP : BOTTOM);
46	if (pos == NULL_POSITION || ch_seek(pos))
47	{
48		if (forwdir)
49			error("Nothing in top line", NULL_PARG);
50		else
51			error("Nothing in bottom line", NULL_PARG);
52		return;
53	}
54
55	/*
56	 * Look thru the line to find the open bracket to match.
57	 */
58	do
59	{
60		if ((c = ch_forw_get()) == '\n' || c == EOI)
61		{
62			if (forwdir)
63				error("No bracket in top line", NULL_PARG);
64			else
65				error("No bracket in bottom line", NULL_PARG);
66			return;
67		}
68	} while (c != obrac || --n > 0);
69
70	/*
71	 * Position the file just "after" the open bracket
72	 * (in the direction in which we will be searching).
73	 * If searching forward, we are already after the bracket.
74	 * If searching backward, skip back over the open bracket.
75	 */
76	if (!forwdir)
77		(void) ch_back_get();
78
79	/*
80	 * Search the file for the matching bracket.
81	 */
82	chget = (forwdir) ? ch_forw_get : ch_back_get;
83	nest = 0;
84	while ((c = (*chget)()) != EOI)
85	{
86		if (c == obrac)
87			nest++;
88		else if (c == cbrac && --nest < 0)
89		{
90			/*
91			 * Found the matching bracket.
92			 * If searching backward, put it on the top line.
93			 * If searching forward, put it on the bottom line.
94			 */
95			jump_line_loc(ch_tell(), forwdir ? -1 : 1);
96			return;
97		}
98	}
99	error("No matching bracket", NULL_PARG);
100}
101