xref: /freebsd/contrib/less/brac.c (revision 1ea316270f1f75922ac53976d5d8808a41442f46)
1 /*
2  * Copyright (C) 1984-2015  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
27 match_brac(int obrac, int cbrac, int forwdir, int n)
28 {
29 	int c;
30 	int nest;
31 	POSITION pos;
32 	int (*chget)(void);
33 
34 	extern int ch_forw_get(void), ch_back_get(void);
35 
36 	/*
37 	 * Seek to the line containing the open bracket.
38 	 * This is either the top or bottom line on the screen,
39 	 * depending on the type of bracket.
40 	 */
41 	pos = position((forwdir) ? TOP : BOTTOM);
42 	if (pos == NULL_POSITION || ch_seek(pos))
43 	{
44 		if (forwdir)
45 			error("Nothing in top line", NULL_PARG);
46 		else
47 			error("Nothing in bottom line", NULL_PARG);
48 		return;
49 	}
50 
51 	/*
52 	 * Look thru the line to find the open bracket to match.
53 	 */
54 	do
55 	{
56 		if ((c = ch_forw_get()) == '\n' || c == EOI)
57 		{
58 			if (forwdir)
59 				error("No bracket in top line", NULL_PARG);
60 			else
61 				error("No bracket in bottom line", NULL_PARG);
62 			return;
63 		}
64 	} while (c != obrac || --n > 0);
65 
66 	/*
67 	 * Position the file just "after" the open bracket
68 	 * (in the direction in which we will be searching).
69 	 * If searching forward, we are already after the bracket.
70 	 * If searching backward, skip back over the open bracket.
71 	 */
72 	if (!forwdir)
73 		(void) ch_back_get();
74 
75 	/*
76 	 * Search the file for the matching bracket.
77 	 */
78 	chget = (forwdir) ? ch_forw_get : ch_back_get;
79 	nest = 0;
80 	while ((c = (*chget)()) != EOI)
81 	{
82 		if (c == obrac)
83 			nest++;
84 		else if (c == cbrac && --nest < 0)
85 		{
86 			/*
87 			 * Found the matching bracket.
88 			 * If searching backward, put it on the top line.
89 			 * If searching forward, put it on the bottom line.
90 			 */
91 			jump_line_loc(ch_tell(), forwdir ? -1 : 1);
92 			return;
93 		}
94 	}
95 	error("No matching bracket", NULL_PARG);
96 }
97