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