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::ParseLineHtmlEx (unsigned dwCookie, const TCHAR *pszChars, int nLength, TEXTBLOCK * pBuf, int &nActualItems, int nEmbeddedLanguage)
30 return dwCookie & (COOKIE_EXT_COMMENT|COOKIE_EXT_USER1|COOKIE_ELEMENT|COOKIE_BLOCK_SCRIPT|COOKIE_BLOCK_STYLE);
32 bool bRedefineBlock = true;
33 if (!(dwCookie & COOKIE_ELEMENT))
34 bRedefineBlock = !(dwCookie & (COOKIE_EXT_USER1|COOKIE_BLOCK_SCRIPT|COOKIE_BLOCK_STYLE));
35 bool bDecIndex = false;
39 for (I = 0;; nPrevI = I, I = static_cast<int>(::CharNext(pszChars+I) - pszChars))
43 // CharNext did not advance, so we're at the end of the string
44 // and we already handled this character, so stop
53 if (dwCookie & COOKIE_EXT_COMMENT)
55 DEFINE_BLOCK (nPos, COLORINDEX_COMMENT);
57 else if (dwCookie & (COOKIE_CHAR | COOKIE_STRING))
59 DEFINE_BLOCK (nPos, COLORINDEX_STRING);
61 else if (dwCookie & COOKIE_ELEMENT)
63 DEFINE_BLOCK (nPos, COLORINDEX_PREPROCESSOR);
67 if (xisalnum (pszChars[nPos]) || pszChars[nPos] == '.')
69 DEFINE_BLOCK (nPos, COLORINDEX_NORMALTEXT);
73 DEFINE_BLOCK (nPos, COLORINDEX_OPERATOR);
74 bRedefineBlock = true;
79 bRedefineBlock = false;
84 // Can be bigger than length if there is binary data
85 // See bug #1474782 Crash when comparing SQL with with binary data
86 if (I >= nLength || pszChars[I] == 0)
89 if (!(dwCookie & COOKIE_ELEMENT) && (dwCookie & (COOKIE_EXT_USER1|COOKIE_BLOCK_SCRIPT|COOKIE_BLOCK_STYLE)))
91 if (dwCookie & COOKIE_BLOCK_SCRIPT)
93 const TCHAR *pszEnd = _tcsstr(pszChars + I, _T("</script>"));
94 int nextI = pszEnd ? (pszEnd - pszChars) : nLength;
95 dwCookie = ParseLineJava(dwCookie & ~COOKIE_BLOCK_SCRIPT, pszChars + I, nextI - I, pBuf, nActualItems);
97 dwCookie |= COOKIE_BLOCK_SCRIPT;
101 bRedefineBlock = true;
105 else if (dwCookie & COOKIE_BLOCK_STYLE)
107 const TCHAR *pszEnd = _tcsstr(pszChars + I, _T("</style>"));
108 int nextI = pszEnd ? (pszEnd - pszChars) : nLength;
109 dwCookie = ParseLineCss(dwCookie & ~COOKIE_BLOCK_STYLE, pszChars + I, nextI - I, pBuf, nActualItems);
111 dwCookie |= COOKIE_BLOCK_STYLE;
115 bRedefineBlock = true;
119 else if ((dwCookie & COOKIE_EXT_USER1))
121 const TCHAR *pszEnd = _tcsstr(pszChars + I, _T("?>"));
123 pszEnd = _tcsstr(pszChars + I, _T("%>"));
124 int nextI = pszEnd ? (pszEnd - pszChars) : nLength;
126 unsigned (*pParseLineFunc)(unsigned, const TCHAR *, int, TEXTBLOCK *, int &);
127 switch (nEmbeddedLanguage)
129 case SRC_BASIC: pParseLineFunc = ParseLineBasic; break;
130 case SRC_PHP: pParseLineFunc = ParseLinePhpLanguage; break;
131 default: pParseLineFunc = ParseLineJava; break;
133 dwCookie = pParseLineFunc(dwCookie & ~COOKIE_EXT_USER1, pszChars + I, nextI - I, pBuf, nActualItems);
135 dwCookie |= COOKIE_EXT_USER1;
139 bRedefineBlock = true;
146 // String constant "...."
147 if (dwCookie & COOKIE_STRING)
149 if (pszChars[I] == '"' && (I == 0 || I == 1 && pszChars[nPrevI] != '\\' || I >= 2 && (pszChars[nPrevI] != '\\' || *::CharPrev(pszChars, pszChars + nPrevI) == '\\')))
151 dwCookie &= ~COOKIE_STRING;
152 bRedefineBlock = true;
157 // Char constant '..'
158 if (dwCookie & COOKIE_CHAR)
160 if (pszChars[I] == '\'' && (I == 0 || I == 1 && pszChars[nPrevI] != '\\' || I >= 2 && (pszChars[nPrevI] != '\\' || *::CharPrev(pszChars, pszChars + nPrevI) == '\\')))
162 dwCookie &= ~COOKIE_CHAR;
163 bRedefineBlock = true;
168 // Extended comment <!--....-->
169 if (dwCookie & COOKIE_EXT_COMMENT)
171 if (I > 1 && pszChars[I] == '>' && pszChars[nPrevI] == '-' && *::CharPrev(pszChars, pszChars + nPrevI) == '-')
173 dwCookie &= ~COOKIE_EXT_COMMENT;
174 bRedefineBlock = true;
180 if ((dwCookie & COOKIE_ELEMENT) && pszChars[I] == '"')
182 DEFINE_BLOCK (I, COLORINDEX_STRING);
183 dwCookie |= COOKIE_STRING;
187 if ((dwCookie & COOKIE_ELEMENT) && pszChars[I] == '\'')
189 // 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] == '\'')
190 if (!I || !xisalnum (pszChars[nPrevI]))
192 DEFINE_BLOCK (I, COLORINDEX_STRING);
193 dwCookie |= COOKIE_CHAR;
198 if (I < nLength - 3 && pszChars[I] == '<' && pszChars[I + 1] == '!' && pszChars[I + 2] == '-' && pszChars[I + 3] == '-')
200 DEFINE_BLOCK (I, COLORINDEX_COMMENT);
202 dwCookie |= COOKIE_EXT_COMMENT;
203 dwCookie &= ~COOKIE_ELEMENT;
208 if (I < nLength && pszChars[I] == '<' && I < nLength - 1 && (pszChars[I + 1] == '?' || pszChars[I + 1] == '%'))
210 DEFINE_BLOCK (I, COLORINDEX_NORMALTEXT);
211 dwCookie |= COOKIE_EXT_USER1;
217 continue; // We don't need to extract keywords,
218 // for faster parsing skip the rest of loop
220 if (xisalnum (pszChars[I]) || pszChars[I] == '.')
222 if (nIdentBegin == -1)
227 if (nIdentBegin >= 0)
229 if (dwCookie & COOKIE_ELEMENT)
231 if (IsHtmlKeyword (pszChars + nIdentBegin, I - nIdentBegin) && (pszChars[nIdentBegin - 1] == _T ('<') || pszChars[nIdentBegin - 1] == _T ('/')))
233 DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
234 if (nIdentBegin > 0 && _tcsnicmp(pszChars + nIdentBegin - 1, _T("<script"), sizeof(_T("<script") - 1)) == 0)
235 dwCookie |= COOKIE_BLOCK_SCRIPT;
236 else if (nIdentBegin > 0 && _tcsnicmp(pszChars + nIdentBegin - 1, _T("<style"), sizeof(_T("<style") - 1)) == 0)
237 dwCookie |= COOKIE_BLOCK_STYLE;
239 else if (IsHtmlUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
241 DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
243 else if (IsXNumber (pszChars + nIdentBegin, I - nIdentBegin))
245 DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
252 else if (dwCookie & COOKIE_USER1)
254 if (IsHtmlUser2Keyword (pszChars + nIdentBegin, I - nIdentBegin))
256 DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER2);
263 bRedefineBlock = true;
270 // Preprocessor start: < or bracket
271 if (I < nLength && pszChars[I] == '<' && !(I < nLength - 3 && pszChars[I + 1] == '!' && pszChars[I + 2] == '-' && pszChars[I + 3] == '-'))
273 DEFINE_BLOCK (I, COLORINDEX_OPERATOR);
274 DEFINE_BLOCK (I + 1, COLORINDEX_PREPROCESSOR);
275 dwCookie |= COOKIE_ELEMENT;
280 // Preprocessor end: > or bracket
281 if (dwCookie & COOKIE_ELEMENT)
283 if (pszChars[I] == '>')
285 dwCookie &= ~COOKIE_ELEMENT;
287 bRedefineBlock = true;
293 // Preprocessor start: &
294 if (pszChars[I] == '&')
296 dwCookie |= COOKIE_USER1;
301 // Preprocessor end: ;
302 if (dwCookie & COOKIE_USER1)
304 if (pszChars[I] == ';')
306 dwCookie &= ~COOKIE_USER1;
314 if (nIdentBegin >= 0 && (dwCookie & COOKIE_ELEMENT))
316 if (IsHtmlKeyword (pszChars + nIdentBegin, I - nIdentBegin) && (pszChars[nIdentBegin - 1] == _T ('<') || pszChars[nIdentBegin - 1] == _T ('/')))
318 DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
319 if (nIdentBegin > 0 && _tcsnicmp(pszChars + nIdentBegin - 1, _T("<script"), sizeof(_T("<script") - 1)) == 0)
320 dwCookie |= COOKIE_BLOCK_SCRIPT;
321 else if (nIdentBegin > 0 && _tcsnicmp(pszChars + nIdentBegin - 1, _T("<style"), sizeof(_T("<style") - 1)) == 0)
322 dwCookie |= COOKIE_BLOCK_STYLE;
324 else if (IsHtmlUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
326 DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
328 else if (IsHtmlUser2Keyword (pszChars + nIdentBegin, I - nIdentBegin))
330 DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER2);
332 else if (IsXNumber (pszChars + nIdentBegin, I - nIdentBegin))
334 DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
338 dwCookie &= (COOKIE_EXT_COMMENT | COOKIE_STRING | COOKIE_ELEMENT | COOKIE_EXT_USER1 | COOKIE_BLOCK_SCRIPT | COOKIE_BLOCK_STYLE);
343 CrystalLineParser::ParseLineHtml (unsigned dwCookie, const TCHAR *pszChars, int nLength, TEXTBLOCK * pBuf, int &nActualItems)
345 return ParseLineHtmlEx(dwCookie, pszChars, nLength, pBuf, nActualItems, SRC_JAVA);