1 #include "CodeEditor.h"
2 
3 namespace Upp {
4 
GetLineIdent(const char * line)5 Array<IdentPos> GetLineIdent(const char *line)
6 {
7 	Array<IdentPos> out;
8 	const char *p = line;
9 	while(*p && *p != '\n')
10 		if(*p == '\"' || *p == '\'')
11 		{
12 			char term = *p++;
13 			while(*p && *p != term)
14 				if(*p++ == '\\' && *p)
15 					p++;
16 			if(*p == term)
17 				p++;
18 		}
19 		else if(*p == 's' && p[1] == '_' && p[2] == '(' && (IsAlpha(p[3]) || p[3] == '_'))
20 		{
21 			IdentPos& pos = out.Add();
22 			pos.begin = int(p - line);
23 			const char *b = (p += 3);
24 			while(IsAlNum(*++p) || *p == '_')
25 				;
26 			pos.ident = String(b, p);
27 			if(*p == ')')
28 				p++;
29 			pos.end = int(p - line);
30 		}
31 		else if(IsAlpha(*p) || *p == '_')
32 		{
33 			while(IsAlNum(*++p) || *p == '_')
34 				;
35 		}
36 		else
37 			p++;
38 	return out;
39 }
40 
GetLineString(const wchar * wline,bool & is_begin,bool & is_end)41 Vector<Point> GetLineString(const wchar *wline, bool& is_begin, bool& is_end)
42 {
43 	Vector<Point> out;
44 	const wchar *p = wline;
45 	while(*p <= ' ' && *p && *p != '\n')
46 		p++;
47 	is_begin = (*p == '\"');
48 	is_end = false;
49 	while(*p && *p != '\n')
50 	{
51 		wchar term = *p;
52 		if(term == '\"' || term == '\'')
53 		{
54 			int begin = int(p++ - wline);
55 			while(*p && *p != '\n')
56 				if(*p == term)
57 				{
58 					const wchar *lim = ++p;
59 					while((byte)*p <= ' ' && *p && *p != '\n')
60 						p++;
61 					if(*p != term)
62 					{
63 						is_end = (*p == '\n' || *p == 0);
64 						p = lim;
65 						break;
66 					}
67 					p++;
68 				}
69 				else if(*p++ == '\\' && *p && *p != '\n')
70 					p++;
71 			if(term == '\"')
72 				out.Add(Point(begin, int(p - wline)));
73 		}
74 		else
75 			p++;
76 	}
77 	return out;
78 }
79 
GetStringRange(int64 cursor,int64 & b,int64 & e) const80 bool CodeEditor::GetStringRange(int64 cursor, int64& b, int64& e) const
81 {
82 	int cl = GetLine(cursor);
83 	cursor -= GetPos64(cl);
84 	bool is_begin, is_end; //@@@@@@
85 	Vector<Point> list = GetLineString(GetWLine(cl), is_begin, is_end);
86 	int i = list.GetCount();
87 	while(--i >= 0 && (list[i].x > cursor || list[i].y < cursor))
88 		;
89 	if(i < 0)
90 		return false;
91 	int bl = cl, bp = list[i].x;
92 	int el = cl, ep = list[i].y;
93 	while(is_begin && bl > 0)
94 	{
95 		list = GetLineString(GetWLine(bl - 1), is_begin, is_end);
96 		if(list.IsEmpty() || !is_end)
97 			break;
98 		bl--;
99 		bp = list.Top().x;
100 	}
101 	while(el + 1 < GetLineCount() && ep >= GetLineLength(el))
102 	{
103 		list = GetLineString(GetWLine(el + 1), is_begin, is_end);
104 		if(list.IsEmpty() || !is_begin)
105 			break;
106 		el++;
107 		ep = list[0].y;
108 	}
109 	b = GetPos64(bl, bp);
110 	e = GetPos64(el, ep);
111 	return b < e;
112 }
113 
FindString(bool back)114 bool CodeEditor::FindString(bool back)
115 {
116 	int64 ll, hh;
117 	hh = GetSelection(ll, hh) ? back ? ll : hh
118 	                          : GetCursor64();
119 	int l = GetLine(hh);
120 	int h = LimitSize(hh - GetPos64(l));
121 
122 	while(l >= 0 && l < GetLineCount())
123 	{
124 		bool is_begin, is_end;
125 		Vector<Point> list = GetLineString(GetWLine(l), is_begin, is_end);
126 		if(back)
127 		{
128 			int i = list.GetCount();
129 			while(--i >= 0 && list[i].x >= h)
130 				;
131 			if(i >= 0)
132 			{
133 				h = list[i].x;
134 				break;
135 			}
136 			h = 1000000;
137 			--l;
138 		}
139 		else
140 		{
141 			int i = 0;
142 			while(i < list.GetCount() && list[i].y <= h)
143 				i++;
144 			if(i < list.GetCount())
145 			{
146 				h = list[i].x;
147 				break;
148 			}
149 			h = 0;
150 			++l;
151 		}
152 	}
153 	int64 b, e;
154 	if(l < 0 || l >= GetLineCount() || !GetStringRange(GetPos64(l, h), b, e))
155 		return false;
156 	SetSelection(b, e);
157 	return true;
158 }
159 
FindLangString(bool back)160 bool CodeEditor::FindLangString(bool back)
161 {
162 	int64 ll, hh;
163 	hh = GetSelection(ll, hh) ? back ? ll : hh
164 	                          : GetCursor64();
165 	int l = GetLine(hh);
166 	int h = LimitSize(hh - GetPos64(l));
167 
168 	for(;;)
169 	{
170 		Array<IdentPos> list = GetLineIdent(GetUtf8Line(l));
171 		int64 b, e;
172 		if(back)
173 		{
174 			int i = list.GetCount();
175 			while(--i >= 0 && list[i].begin >= h)
176 				;
177 			if(i < 0)
178 			{
179 				h = 1000000;
180 				if(--l < 0)
181 					break;
182 				continue;
183 			}
184 			b = GetPos64(l, list[i].begin);
185 			e = GetPos64(l, list[i].end);
186 		}
187 		else
188 		{
189 			int i = 0;
190 			while(i < list.GetCount() && list[i].end <= h)
191 				i++;
192 			if(i >= list.GetCount())
193 			{
194 				h = 0;
195 				if(++l >= GetLineCount())
196 					break;
197 				continue;
198 			}
199 			b = GetPos64(l, list[i].begin);
200 			e = GetPos64(l, list[i].end);
201 		}
202 		SetSelection(b, e);
203 		return true;
204 	}
205 	return false;
206 }
207 
208 }
209