1 /* h_simple.cpp
2 *
3 * Copyright (c) 1994-1996, Marko Macek
4 *
5 * You may distribute under the terms of either the GNU General Public
6 * License or the Artistic License, as specified in the README file.
7 *
8 */
9
10 #include "fte.h"
11
12 #ifdef CONFIG_HILIT_SIMPLE
13
14 #include "c_bind.h"
15 #include "o_buflist.h"
16 #include "s_util.h"
17 #include "sysdep.h"
18
Hilit_SIMPLE(EBuffer * BF,int LN,PCell B,int Pos,int Width,ELine * Line,hlState & State,hsState * StateMap,int * ECol)19 int Hilit_SIMPLE(EBuffer *BF, int LN, PCell B, int Pos, int Width, ELine *Line, hlState &State, hsState *StateMap, int *ECol) {
20 EColorize *col = BF->Mode->fColorize;
21 HMachine *hm = col->hm;
22 HILIT_VARS(col->Colors, Line);
23 HState *st = 0;
24 HTrans *tr = 0;
25 int t, cc;
26 int quotech = 0;
27 int matchFlags;
28 int matchLen;
29 int nextState;
30 char *match;
31 int lastPos = -1;
32 hlState entryState;
33 int iterCount;
34 bool reportError = true;
35
36 if (hm == 0 || hm->stateCount == 0)
37 return 0;
38
39 if (State >= hm->stateCount)
40 State = 0;
41 st = hm->state + State;
42 Color = st->color;
43
44 /*{
45 fprintf(stderr, "ColMode:%s, State:%d\n", col->Name, State);
46 for (int s = 0; s < hm->stateCount; s++) {
47 fprintf(stderr,
48 "State:%d, transCount:%d, firstTrans:%d, options:%d, color:%d, nextState:%d\n",
49 s,
50 hm->state[s].transCount,
51 hm->state[s].firstTrans,
52 hm->state[s].options,
53 hm->state[s].color,
54 hm->state[s].nextState);
55 }
56 for (int t = 0; t < hm->transCount; t++) {
57 fprintf(stderr,
58 "Trans:%d, matchLen:%d, matchFlags:%d, nextState:%d, color:%d\n",
59 t,
60 hm->trans[t].matchLen,
61 hm->trans[t].matchFlags,
62 hm->trans[t].nextState,
63 hm->trans[t].color);
64 }
65 //exit(1);
66 sleep(5);
67 }*/
68
69 for (i = 0; i < Line->Count; ) {
70 // Check for infinite loops
71 if (i == lastPos) {
72 if (++iterCount > hm->stateCount) {
73 // Passed the same position more times than number of states -> must be looping
74 if (reportError) {
75 // Report only once per line since other errors may be false alarms caused by hiliter restart
76 reportError = false;
77 BF->Msg(S_INFO, "Hiliter looping at line %d, column %d, entry state %d", LN + 1, i + 1, entryState);
78 } else {
79 // Already reported - advance by one character
80 Color = hm->state[entryState].color;
81 IF_TAB()
82 else
83 ColorNext();
84 }
85 // Restart with state 0
86 State = 0;
87 st = hm->state;
88 iterCount = 1;
89 goto next_state;
90 }
91 } else {
92 lastPos = i;
93 entryState = State;
94 iterCount = 1;
95 }
96
97 if (quotech) {
98 quotech = 0;
99 } else {
100 for (t = 0; t < st->transCount; t++) {
101 tr = hm->trans + st->firstTrans + t;
102 matchLen = tr->matchLen;
103 matchFlags = tr->matchFlags;
104 match = tr->match;
105 nextState = tr->nextState;
106
107 //fprintf(stderr,
108 // "line:%d, char:%d (%c), len:%d, state:%d, tr:%d, st->transCount:%d, st->firstTrans:%d, nextState:%d, matchFlags:%08x\n",
109 // LN, i, *p, len, State, t, st->transCount, st->firstTrans, nextState, matchFlags);
110
111 if (len < matchLen)
112 continue;
113
114 if ((i > 0) && (matchFlags & MATCH_MUST_BOL))
115 continue;
116
117 if ((matchFlags & (MATCH_SET | MATCH_NOTSET)) == 0) {
118 if (matchFlags & MATCH_REGEXP) {
119 RxMatchRes b;
120 if (!RxExecMatch(tr->regexp, Line->Chars, Line->Count, p, &b, (matchFlags & MATCH_NO_CASE) ? 0 : RX_CASE)) continue;
121 if (b.Open[1] != -1 && b.Close[1] != -1) matchLen = b.Open[1] - i;
122 else matchLen = b.Close[0] - i;
123 } else if (matchFlags & MATCH_NO_CASE) {
124 if (memicmp(match, p, matchLen))
125 continue;
126 } else {
127 for (cc = 0; cc < matchLen; cc++)
128 if (p[cc] != match[cc])
129 goto next_trans;
130 }
131 } else if (matchFlags & MATCH_SET) {
132 if (!WGETBIT(match, *p))
133 continue;
134 } else if (matchFlags & MATCH_NOTSET) {
135 if (WGETBIT(match, *p))
136 continue;
137 }
138
139 if ((len != matchLen) && (matchFlags & MATCH_MUST_EOL))
140 continue;
141
142 if (matchFlags & MATCH_NOGRAB) {
143 State = nextState;
144 if (State >= hm->stateCount)
145 State = 0;
146 st = hm->state + State;
147 //fprintf(stderr, "nograb\n");
148 } else {
149 if (matchFlags & MATCH_TAGASNEXT) {
150 State = nextState;
151 if (State >= hm->stateCount)
152 State = 0;
153 st = hm->state + State;
154 }
155 Color = tr->color;
156 for (cc = 0; cc < matchLen; cc++)
157 IF_TAB()
158 else
159 ColorNext();
160 if (!(matchFlags & MATCH_TAGASNEXT)) {
161 State = nextState;
162 if (State >= hm->stateCount)
163 State = 0;
164 st = hm->state + State;
165 }
166 if (len > 0) {
167 if (matchFlags & MATCH_QUOTECH)
168 quotech = 1;
169 } else if (len == 0) {
170 if (matchFlags & MATCH_QUOTEEOL)
171 goto end_parse; /* see note below !! */
172 }
173 }
174 //fprintf(stderr, "next state\n");
175 goto next_state;
176 next_trans: /* */;
177 }
178 if (st->wordChars != 0) {
179 int j;
180 hlState MState = State;
181
182 j = 0;
183 while (((i + j) < Line->Count) &&
184 (WGETBIT(st->wordChars, Line->Chars[i + j]))) j++;
185
186 //GP (fix)
187 Color = st->color;
188
189 if (j == 0) {
190 if (st->nextKwdNoCharState != -1) {
191 State = st->nextKwdNoCharState;
192 if (State >= hm->stateCount)
193 State = 0;
194 st = hm->state + State;
195 Color = st->color;
196 goto next_state;
197 }
198 } else {
199 if (st->GetHilitWord(Color, &Line->Chars[i], j) ||
200 BF->GetHilitWord(Color, &Line->Chars[i], j, BFI( BF, BFI_MatchCase ) ? 0 : 1))
201 {
202 if (st->nextKwdMatchedState != -1)
203 State = st->nextKwdMatchedState;
204 } else {
205 if (st->nextKwdNotMatchedState != -1) {
206 State = st->nextKwdNotMatchedState;
207 if (st->options & STATE_NOGRAB) {
208 if (State >= hm->stateCount)
209 State = 0;
210 st = hm->state + State;
211 Color = st->color;
212 goto next_state;
213 }
214 }
215 }
216
217 if (State >= hm->stateCount)
218 State = 0;
219
220 // highlight/tag as next state
221 if (st->options & STATE_TAGASNEXT) {
222 MState = State;
223 st = hm->state + State;
224 Color = st->color;
225 }
226
227 if (StateMap)
228 memset(StateMap + i, MState, j);
229 if (B)
230 MoveMem(B, C - Pos, Width, Line->Chars + i, HILIT_CLRD(), j);
231 i += j;
232 len -= j;
233 p += j;
234 C += j;
235
236 if (!(st->options & STATE_TAGASNEXT)) {
237 st = hm->state + State;
238 Color = st->color;
239 }
240 goto next_state;
241 }
242 }
243 }
244 Color = st->color;
245 IF_TAB()
246 else
247 ColorNext();
248 next_state: /* */;
249 }
250
251 /* check if there are any matches for EOL */
252 /* NOTE: this is skipped when Q option is used above. !! */
253 for (t = 0; t < st->transCount; t++) {
254 tr = hm->trans + st->firstTrans + t;
255 matchLen = tr->matchLen;
256 matchFlags = tr->matchFlags;
257 match = tr->match;
258 nextState = tr->nextState;
259
260 if (((i > 0) && (matchFlags & MATCH_MUST_BOL)) || (matchFlags & MATCH_REGEXP))
261 continue;
262
263 //cant match eol beyond eol.
264 //if ((len != matchLen) && (matchFlags & MATCH_MUST_EOL))
265 //continue;
266
267 if (matchLen == 0) {
268 State = nextState;
269 if (State >= hm->stateCount)
270 State = 0;
271 break;
272 }
273 }
274 end_parse: ;
275 *ECol = C;
276 return 0;
277 }
278
279 #endif
280