1 ///////////////////////////////////////////////////////////////////////////
4 // Updated: 19-Jul-1998
6 // Copyright: Ferdinand Prantl, portions by Stcherbatchenko Andrei
7 // E-mail: prantl@ff.cuni.cz
9 // HTML syntax highlighing definition
11 // You are free to use or modify this code to the following restrictions:
12 // - Acknowledge me somewhere in your about box, simple "Parts of code by.."
13 // will be enough. If you can't (or don't want to), contact me personally.
14 // - LEAVE THIS HEADER INTACT
15 ////////////////////////////////////////////////////////////////////////////
18 #include "crystallineparser.h"
19 #include "../SyntaxColors.h"
20 #include "../utils/string_util.h"
27 CrystalLineParser::ParseLineHtml (DWORD dwCookie, const TCHAR *pszChars, int nLength, TEXTBLOCK * pBuf, int &nActualItems)
30 return dwCookie & (COOKIE_EXT_COMMENT|COOKIE_EXT_USER1);
32 bool bFirstChar = (dwCookie & ~(COOKIE_EXT_COMMENT|COOKIE_EXT_USER1)) == 0;
33 bool bRedefineBlock = true;
34 bool bDecIndex = false;
38 for (I = 0;; nPrevI = I, I = static_cast<int>(::CharNext(pszChars+I) - pszChars))
42 // CharNext did not advance, so we're at the end of the string
43 // and we already handled this character, so stop
52 if (dwCookie & (COOKIE_COMMENT | COOKIE_EXT_COMMENT))
54 DEFINE_BLOCK (nPos, COLORINDEX_COMMENT);
56 else if (dwCookie & (COOKIE_CHAR | COOKIE_STRING))
58 DEFINE_BLOCK (nPos, COLORINDEX_STRING);
60 else if (dwCookie & COOKIE_PREPROCESSOR)
62 DEFINE_BLOCK (nPos, COLORINDEX_PREPROCESSOR);
64 else if (dwCookie & COOKIE_EXT_USER1)
66 DEFINE_BLOCK (nPos, COLORINDEX_FUNCNAME);
70 if (xisalnum (pszChars[nPos]) || pszChars[nPos] == '.')
72 DEFINE_BLOCK (nPos, COLORINDEX_NORMALTEXT);
76 DEFINE_BLOCK (nPos, COLORINDEX_OPERATOR);
77 bRedefineBlock = true;
82 bRedefineBlock = false;
87 // Can be bigger than length if there is binary data
88 // See bug #1474782 Crash when comparing SQL with with binary data
89 if (I >= nLength || pszChars[I] == 0)
92 if (dwCookie & COOKIE_COMMENT)
94 DEFINE_BLOCK (I, COLORINDEX_COMMENT);
95 dwCookie |= COOKIE_COMMENT;
99 // String constant "...."
100 if (dwCookie & COOKIE_STRING)
102 if (pszChars[I] == '"' && (I == 0 || I == 1 && pszChars[nPrevI] != '\\' || I >= 2 && (pszChars[nPrevI] != '\\' || *::CharPrev(pszChars, pszChars + nPrevI) == '\\')))
104 dwCookie &= ~COOKIE_STRING;
105 bRedefineBlock = true;
110 // Char constant '..'
111 if (dwCookie & COOKIE_CHAR)
113 if (pszChars[I] == '\'' && (I == 0 || I == 1 && pszChars[nPrevI] != '\\' || I >= 2 && (pszChars[nPrevI] != '\\' || *::CharPrev(pszChars, pszChars + nPrevI) == '\\')))
115 dwCookie &= ~COOKIE_CHAR;
116 bRedefineBlock = true;
121 // Extended comment <!--....-->
122 if (dwCookie & COOKIE_EXT_COMMENT)
124 if (I > 1 && pszChars[I] == '>' && pszChars[nPrevI] == '-' && *::CharPrev(pszChars, pszChars + nPrevI) == '-')
126 dwCookie &= ~COOKIE_EXT_COMMENT;
127 bRedefineBlock = true;
132 // Extended comment <?....?>
133 if (dwCookie & COOKIE_EXT_USER1)
135 if (I > 0 && pszChars[I] == '>' && (pszChars[nPrevI] == '?' || pszChars[nPrevI] == '%'))
137 dwCookie &= ~COOKIE_EXT_USER1;
138 bRedefineBlock = true;
144 if ((dwCookie & COOKIE_PREPROCESSOR) && pszChars[I] == '"')
146 DEFINE_BLOCK (I, COLORINDEX_STRING);
147 dwCookie |= COOKIE_STRING;
151 if ((dwCookie & COOKIE_PREPROCESSOR) && pszChars[I] == '\'')
153 // if (I + 1 < nLength && pszChars[I + 1] == '\'' || I + 2 < nLength && pszChars[I + 1] != '\\' && pszChars[I + 2] == '\'' || I + 3 < nLength && pszChars[I + 1] == '\\' && pszChars[I + 3] == '\'')
154 if (!I || !xisalnum (pszChars[nPrevI]))
156 DEFINE_BLOCK (I, COLORINDEX_STRING);
157 dwCookie |= COOKIE_CHAR;
162 if (!(dwCookie & COOKIE_EXT_USER1) && I < nLength - 3 && pszChars[I] == '<' && pszChars[I + 1] == '!' && pszChars[I + 2] == '-' && pszChars[I + 3] == '-')
164 DEFINE_BLOCK (I, COLORINDEX_COMMENT);
166 dwCookie |= COOKIE_EXT_COMMENT;
167 dwCookie &= ~COOKIE_PREPROCESSOR;
173 if (!xisspace (pszChars[I]))
178 continue; // We don't need to extract keywords,
179 // for faster parsing skip the rest of loop
181 if (xisalnum (pszChars[I]) || pszChars[I] == '.')
183 if (nIdentBegin == -1)
188 if (nIdentBegin >= 0)
190 if (dwCookie & COOKIE_PREPROCESSOR)
192 if (IsHtmlKeyword (pszChars + nIdentBegin, I - nIdentBegin) && (pszChars[nIdentBegin - 1] == _T ('<') || pszChars[nIdentBegin - 1] == _T ('/')))
194 DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
196 else if (IsHtmlUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
198 DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
200 else if (IsXNumber (pszChars + nIdentBegin, I - nIdentBegin))
202 DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
209 else if (dwCookie & COOKIE_USER1)
211 if (IsHtmlUser2Keyword (pszChars + nIdentBegin, I - nIdentBegin))
213 DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER2);
220 bRedefineBlock = true;
228 if (I < nLength && pszChars[I] == '<' && I < nLength - 1 && (pszChars[I + 1] == '?' || pszChars[I + 1] == '%'))
230 DEFINE_BLOCK (I, COLORINDEX_FUNCNAME);
231 dwCookie |= COOKIE_EXT_USER1;
236 // Preprocessor start: < or bracket
237 if (!(dwCookie & COOKIE_EXT_USER1) && I < nLength && (pszChars[I] == '<' && !(I < nLength - 3 && pszChars[I + 1] == '!' && pszChars[I + 2] == '-' && pszChars[I + 3] == '-')/* || pszChars[I] == '{'*/))
239 DEFINE_BLOCK (I, COLORINDEX_OPERATOR);
240 DEFINE_BLOCK (I + 1, COLORINDEX_PREPROCESSOR);
241 dwCookie |= COOKIE_PREPROCESSOR;
247 if (dwCookie & COOKIE_EXT_USER1)
249 if (I > 0 && pszChars[I] == '>' && (pszChars[nPrevI] == '?' || pszChars[nPrevI] == '%'))
251 dwCookie &= ~COOKIE_EXT_USER1;
253 bRedefineBlock = true;
259 // Preprocessor end: > or bracket
260 if (dwCookie & COOKIE_PREPROCESSOR)
262 if (pszChars[I] == '>'/* || pszChars[I] == '}'*/)
264 dwCookie &= ~COOKIE_PREPROCESSOR;
266 bRedefineBlock = true;
272 // Preprocessor start: &
273 if (pszChars[I] == '&')
275 dwCookie |= COOKIE_USER1;
280 // Preprocessor end: ;
281 if (dwCookie & COOKIE_USER1)
283 if (pszChars[I] == ';')
285 dwCookie &= ~COOKIE_USER1;
293 if (nIdentBegin >= 0 && (dwCookie & COOKIE_PREPROCESSOR))
295 if (IsHtmlKeyword (pszChars + nIdentBegin, I - nIdentBegin) && (pszChars[nIdentBegin - 1] == _T ('<') || pszChars[nIdentBegin - 1] == _T ('/')))
297 DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
299 else if (IsHtmlUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
301 DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
303 else if (IsHtmlUser2Keyword (pszChars + nIdentBegin, I - nIdentBegin))
305 DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER2);
307 else if (IsXNumber (pszChars + nIdentBegin, I - nIdentBegin))
309 DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
313 bool bFunction = false;
315 for (int j = I; j < nLength; j++)
317 if (!xisspace (pszChars[j]))
319 if (pszChars[j] == '(')
328 DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
334 if (I < nLength && pszChars[I] == '<' && I < nLength - 1 && (pszChars[I + 1] == '?' || pszChars[I + 1] == '%'))
336 DEFINE_BLOCK (I, COLORINDEX_FUNCNAME);
337 dwCookie |= COOKIE_EXT_USER1;
342 // Preprocessor start: < or {
343 if (!(dwCookie & COOKIE_EXT_USER1) && I < nLength && (pszChars[I] == '<' && !(I < nLength - 3 && pszChars[I + 1] == '!' && pszChars[I + 2] == '-' && pszChars[I + 3] == '-')/* || pszChars[I] == '{'*/))
345 DEFINE_BLOCK (I, COLORINDEX_OPERATOR);
346 DEFINE_BLOCK (I + 1, COLORINDEX_PREPROCESSOR);
347 dwCookie |= COOKIE_PREPROCESSOR;
353 if (dwCookie & COOKIE_EXT_USER1)
355 if (I > 0 && pszChars[I] == '>' && (pszChars[nPrevI] == '?' || pszChars[nPrevI] == '%'))
357 dwCookie &= ~COOKIE_EXT_USER1;
362 // Preprocessor end: > or }
363 if (dwCookie & COOKIE_PREPROCESSOR)
365 if (pszChars[I] == '>'/* || pszChars[I] == '}'*/)
367 dwCookie &= ~COOKIE_PREPROCESSOR;
373 dwCookie &= (COOKIE_EXT_COMMENT | COOKIE_STRING | COOKIE_PREPROCESSOR | COOKIE_EXT_USER1);