1 /*
2  * Copyright 2018 Jiri Techet <techet@gmail.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18 
19 #include "cmds/txtobjs.h"
20 
21 
find_upper_level_brace(ScintillaObject * sci,gint pos,gint open_brace,gint close_brace)22 static gint find_upper_level_brace(ScintillaObject *sci, gint pos, gint open_brace, gint close_brace)
23 {
24 	while (pos > 0)
25 	{
26 		pos = PREV(sci, pos);
27 		gchar c = SSM(sci, SCI_GETCHARAT, pos, 0);
28 
29 		if (c == open_brace)
30 			return pos;
31 		else if (c == close_brace)
32 		{
33 			pos = SSM(sci, SCI_BRACEMATCH, pos, 0);
34 			if (pos < 0)
35 				break;
36 		}
37 	}
38 	return -1;
39 }
40 
41 
find_char(ScintillaObject * sci,gint pos,gint ch,gboolean forward)42 static gint find_char(ScintillaObject *sci, gint pos, gint ch, gboolean forward)
43 {
44 	while (pos > 0)
45 	{
46 		gint last_pos = pos;
47 		gchar c;
48 
49 		pos = forward ? NEXT(sci, pos) : PREV(sci, pos);
50 		c = SSM(sci, SCI_GETCHARAT, pos, 0);
51 
52 		if (c == ch)
53 			return pos;
54 		if (pos == last_pos)
55 			break;
56 	}
57 	return -1;
58 }
59 
60 
select_brace(CmdContext * c,CmdParams * p,gint open_brace,gint close_brace,gboolean inner)61 static void select_brace(CmdContext *c, CmdParams *p, gint open_brace, gint close_brace, gboolean inner)
62 {
63 	gint pos = p->pos;
64 	gint start_pos = 0;
65 	gint end_pos = 0;
66 	gint i;
67 
68 	for (i = 0; i < p->num; i++)
69 	{
70 		if (open_brace == close_brace)
71 		{
72 			start_pos = find_char(p->sci, pos, open_brace, FALSE);
73 			if (start_pos < 0)
74 				return;
75 			end_pos = find_char(p->sci, pos, close_brace, TRUE);
76 		}
77 		else
78 		{
79 			start_pos = find_upper_level_brace(p->sci, pos, open_brace, close_brace);
80 			if (start_pos < 0)
81 				return;
82 			end_pos = SSM(p->sci, SCI_BRACEMATCH, start_pos, 0);
83 		}
84 
85 		if (end_pos < 0)
86 			return;
87 
88 		pos = start_pos;
89 	}
90 
91 	if (inner)
92 		start_pos = NEXT(p->sci, start_pos);
93 	else
94 		end_pos = NEXT(p->sci, end_pos);
95 
96 	if (VI_IS_VISUAL(vi_get_mode()))
97 	{
98 		c->sel_anchor = start_pos;
99 		SET_POS(p->sci, end_pos, TRUE);
100 	}
101 	else
102 	{
103 		p->sel_start = start_pos;
104 		p->sel_len = end_pos - start_pos;
105 	}
106 }
107 
108 
cmd_select_quotedbl(CmdContext * c,CmdParams * p)109 void cmd_select_quotedbl(CmdContext *c, CmdParams *p)
110 {
111 	select_brace(c, p, '\"', '\"', FALSE);
112 }
113 
114 
cmd_select_quoteleft(CmdContext * c,CmdParams * p)115 void cmd_select_quoteleft(CmdContext *c, CmdParams *p)
116 {
117 	select_brace(c, p, '`', '`', FALSE);
118 }
119 
120 
cmd_select_apostrophe(CmdContext * c,CmdParams * p)121 void cmd_select_apostrophe(CmdContext *c, CmdParams *p)
122 {
123 	select_brace(c, p, '\'', '\'', FALSE);
124 }
125 
126 
cmd_select_brace(CmdContext * c,CmdParams * p)127 void cmd_select_brace(CmdContext *c, CmdParams *p)
128 {
129 	select_brace(c, p, '{', '}', FALSE);
130 }
131 
132 
cmd_select_paren(CmdContext * c,CmdParams * p)133 void cmd_select_paren(CmdContext *c, CmdParams *p)
134 {
135 	select_brace(c, p, '(', ')', FALSE);
136 }
137 
138 
cmd_select_less(CmdContext * c,CmdParams * p)139 void cmd_select_less(CmdContext *c, CmdParams *p)
140 {
141 	select_brace(c, p, '<', '>', FALSE);
142 }
143 
144 
cmd_select_bracket(CmdContext * c,CmdParams * p)145 void cmd_select_bracket(CmdContext *c, CmdParams *p)
146 {
147 	select_brace(c, p, '[', ']', FALSE);
148 }
149 
150 
cmd_select_quotedbl_inner(CmdContext * c,CmdParams * p)151 void cmd_select_quotedbl_inner(CmdContext *c, CmdParams *p)
152 {
153 	select_brace(c, p, '\"', '\"', TRUE);
154 }
155 
156 
cmd_select_quoteleft_inner(CmdContext * c,CmdParams * p)157 void cmd_select_quoteleft_inner(CmdContext *c, CmdParams *p)
158 {
159 	select_brace(c, p, '`', '`', TRUE);
160 }
161 
162 
cmd_select_apostrophe_inner(CmdContext * c,CmdParams * p)163 void cmd_select_apostrophe_inner(CmdContext *c, CmdParams *p)
164 {
165 	select_brace(c, p, '\'', '\'', TRUE);
166 }
167 
168 
cmd_select_brace_inner(CmdContext * c,CmdParams * p)169 void cmd_select_brace_inner(CmdContext *c, CmdParams *p)
170 {
171 	select_brace(c, p, '{', '}', TRUE);
172 }
173 
174 
cmd_select_paren_inner(CmdContext * c,CmdParams * p)175 void cmd_select_paren_inner(CmdContext *c, CmdParams *p)
176 {
177 	select_brace(c, p, '(', ')', TRUE);
178 }
179 
180 
cmd_select_less_inner(CmdContext * c,CmdParams * p)181 void cmd_select_less_inner(CmdContext *c, CmdParams *p)
182 {
183 	select_brace(c, p, '<', '>', TRUE);
184 }
185 
186 
cmd_select_bracket_inner(CmdContext * c,CmdParams * p)187 void cmd_select_bracket_inner(CmdContext *c, CmdParams *p)
188 {
189 	select_brace(c, p, '[', ']', TRUE);
190 }
191