_EXPORT bool Balance(CLanguageProxy& proxy, int32& start, int32& end) { bool in = false; const char *txt = proxy.Text(), *st; int32 size = proxy.Size(); if (start < 0 || start > end || end > size) return false; st = txt + start; while (txt < st) { const char *t = in ? skip_in(txt + 1) : skip_out(txt + 1); in = !in; if (*t && t > st) { start = txt - proxy.Text() + 1; end = t - proxy.Text(); return true; } txt = t; } return false; } /* Balance */
_EXPORT int32 FindNextWord(const CLanguageProxy& proxy) { int32 mark = 0, i = 0; int32 unicode, state, len; const char *txt = proxy.Text(); state = 1; while (state && i < proxy.Size()) { proxy.CharInfo(txt + i, unicode, len); if (proxy.isspace_uc(unicode)) { state = 0; } else { mark = i + len - 1; } i += len; } return mark; } /* FindNextWord */
int32 FindNextWord(const CLanguageProxy& proxy) { int32 mark = 0, i = 0; int32 unicode, state, len; state = 1; while (state > 0 && i < proxy.Size()) { proxy.CharInfo(proxy.Text() + i, unicode, len); int cl = 0; if (unicode == '\n') cl = 3; else if (proxy.isspace_uc(unicode)) cl = 2; else if (proxy.isalnum_uc(unicode)) cl = 4; else switch (unicode) { case 160: case 8199: case 8209: cl = 1; break; case '&': case '*': case '+': case '-': // case '/': // case '<': case '=': // case '>': case '\\': case '^': case '|': cl = 5; break; default: cl = 4; } unsigned char t = kWordWrapTable[(state - 1) * 6 + cl]; state = t & 0x7f; if (t & 0x80) mark = i + len - 1; i += len; } return mark; } /* FindNextWord */
void ScanForFunctions(CLanguageProxy& proxy) { const char *text = proxy.Text(), *max = text + proxy.Size(); if (*max != 0) return; while (text < max) { text = comment(text); switch (*text++) { case 'c': case 'C': if (!strncasecmp(text, "onstructor", 10)) text = parseFunction(text + 10, proxy); break; case 'd': case 'D': if (!strncasecmp(text, "estructor", 9)) text = parseFunction(text + 9, proxy); break; case 'f': case 'F': if (!strncasecmp(text, "unction", 7)) text = parseFunction(text + 7, proxy); break; case 'p': case 'P': if (!strncasecmp(text, "rocedure", 8)) text = parseFunction(text + 8, proxy); break; case 'u': case 'U': if (!strncasecmp(text, "ses", 3)) text = parseUses(text + 3, proxy); break; } } }
void ScanForFunctions(CLanguageProxy& proxy) { const char *text = proxy.Text(), *max = text + proxy.Size(); if (*max != 0) return; while (text < max) { text = skip(text, '<'); text = skip_white(text); switch (toupper(*text)) { case 0: return; case 'A': if (isspace(*++text)) text = Anchor(text, proxy); else text = skip_nc(text, '>'); break; case 'H': if (*++text >= '1' && *text <= '6') { text = Heading(text, proxy); } else text = skip_nc(text, '>'); break; case 'S': if (strncasecmp(text, "SCRIPT", 6) == 0) text = JavaScript(text, proxy); break; default: text = skip_nc(text + 1, '>'); break; } } } /* ScanForFunctions */
void ScanForFunctions(CLanguageProxy& proxy) { const char* text = proxy.Text(), *max = text + proxy.Size(); char* scope = (char*)"file"; if (*max != 0) return; while (text < max) { text = comment(text, false); switch (*text) { case 0: return; case '\'': text = skip(text + 1, '\''); break; case '"': text = skip(text + 1, '"'); break; case '(': case '{': case '[': text = parens(text + 1, *text); break; case '#': text = preprocessor(text + 1, proxy); break; default: if (isidentf(*text)) text = ident(text, proxy, scope); else text++; break; } } } /* ScanForFunctions */
_EXPORT void ColorLine(CLanguageProxy& proxy, int32& state) { const char *text = proxy.Text(); int32 size = proxy.Size(); int32 i = 0, s = 0, kws = 0, cc_cnt = 0, esc = 0; char c; bool leave = false; if (state == COMMENT || state == LCOMMENT) proxy.SetColor(0, kColorComment1); else proxy.SetColor(0, kColorText); if (size <= 0) return; while (!leave) { GETCHAR; switch (state) { case START: if (isalpha(c) || c == '_') { kws = proxy.Move(c, 1); state = IDENT; } else if (c == '/' && text[i] == '*') state = COMMENT; else if (c == '/' && text[i] == '/') state = LCOMMENT; else if (c == '"') state = STRING; else if (c == '\'') { state = CHAR_CONST; cc_cnt = 0; } else if (c == '\n' || c == 0) leave = true; if (leave || (state != START && s < i)) { proxy.SetColor(s, kColorText); s = i - 1; } break; case COMMENT: if ((s == 0 || i > s + 1) && c == '*' && text[i] == '/') { proxy.SetColor(s, kColorComment1); s = i + 1; state = START; } else if (c == 0 || c == '\n') { proxy.SetColor(s, kColorComment1); leave = true; } break; case LCOMMENT: proxy.SetColor(s, kColorComment1); leave = true; if (text[size - 1] == '\n') state = START; break; case IDENT: if (!isalnum(c) && c != '_' && c != '.') { int32 kwc; if (i > s + 1 && (kwc = proxy.IsKeyword(kws)) != 0) { switch (kwc) { case 1: proxy.SetColor(s, kColorKeyword1); break; case 2: proxy.SetColor(s, kColorUserSet1); break; case 3: proxy.SetColor(s, kColorUserSet2); break; case 4: proxy.SetColor(s, kColorUserSet3); break; case 5: proxy.SetColor(s, kColorUserSet4); break; // default: ASSERT(false); } } else { proxy.SetColor(s, kColorText); } s = --i; state = START; } else if (kws) kws = proxy.Move((int)(unsigned char)c, kws); break; case STRING: if (c == '"' && !esc) { proxy.SetColor(s, kColorString1); s = i; state = START; } else if (c == '\n' || c == 0) { if (text[i - 2] == '\\' && text[i - 3] != '\\') { proxy.SetColor(s, kColorString1); } else { proxy.SetColor(s, kColorText); state = START; } s = size; leave = true; } else esc = !esc && (c == '\\'); break; case CHAR_CONST: if (c == '\t' || c == '\n' || c == 0) // don't like this { proxy.SetColor(s, kColorText); s = i; state = START; } else if (c == '\'' && !esc) { if (cc_cnt != 1 && cc_cnt != 2 && cc_cnt != 4) { proxy.SetColor(s, kColorText); s = --i; state = START; } else { proxy.SetColor(s, kColorCharConst); s = i; state = START; } } else { if (!esc) cc_cnt++; esc = !esc && (c == '\\'); } break; default: // error condition, gracefully leave the loop leave = true; break; } } } /* ColorLine */
_EXPORT void ColorLine(CLanguageProxy& proxy, int32& state) { const char *text = proxy.Text(); int32 size = proxy.Size(); char c; // Current character int32 nxt = 0, // Position after current character in text (i) beg = 0, // (s) kws = 0, // forceState = START, // color, // kwc; // Keywordcode bool leave = false, esc = false, script = false, percent = false, style = false; proxy.SetColor(0, kColorText); if (size <= 0) return; script = (state >= JAVASCRIPT); percent = false; #if DEBUG_PHP printf("#############################################################################\nColorLine(%s:%s)\n%s\n", DEB_StateName(state), script ? "IsScript" : "NoScript", text); #endif while (!leave) { c = get_char(nxt, size, text); switch (state) { case START: DEB_PrintState(state, c); if (c == '<') state = TAG_START; else if (c == '&') state = SPECIAL; else if (c == 0 || c == '\n') leave = true; if ((leave || state != START) && beg < nxt) { proxy.SetColor(beg, kColorText); beg = nxt-1; } break; case TAG_START: DEB_PrintState(state, c); if (c == '/') state = TAG_KEYWORD_END; else if (c == '!') { state = COMMENT_DTD; forceState = START; } else if (c == '?' || c == '%') { proxy.SetColor(beg, kColorTag); beg = nxt; if (strncasecmp(text+beg, "php", 3) == 0) { proxy.SetColor(beg, kColorTag); beg = (nxt += 3); } state = PHP_SCRIPT; percent = (c == '%'); } else if (isalpha(c)) { proxy.SetColor(beg, kColorTag); beg = nxt-1; kws = proxy.Move(CASE_SENSITIVE_TAG ? c : tolower(c), 1); state = TAG_KEYWORD_START; } else if (c == 0 || c == '\n') { proxy.SetColor(beg, kColorTag); leave = true; } else if (!isspace(c)) { nxt--; state = TAG; } break; case TAG_KEYWORD_END: DEB_PrintState(state, c); if (isalpha(c)) { proxy.SetColor(beg, kColorTag); beg = nxt-1; kws = proxy.Move(CASE_SENSITIVE_TAG ? c : tolower(c), 1); state = TAG_KEYWORD_START; } else if (c == 0 || c == '\n') { proxy.SetColor(beg, kColorTag); leave = true; } else if (!isspace(c)) { nxt--; state = TAG; } break; case TAG_KEYWORD_START: DEB_PrintState(state, c); if (!isalnum(c) && c != '-') { switch (kwc = proxy.IsKeyword(kws, kKwHtmlTag|kKwUsersets)) { case kKwHtmlTag: color = kColorTag; break; case kKwUserset1: color = kColorUserSet1; break; case kKwUserset2: color = kColorUserSet2; break; case kKwUserset3: color = kColorUserSet3; break; case kKwUserset4: color = kColorUserSet4; break; default: color = kColorText; break; } proxy.SetColor(beg, color); DEB_PrintSetKw(state, kwc); if (text[beg-1] != '/') { if (strncasecmp(text+beg, "script", 6) == 0) script = true; else if (strncasecmp(text+beg, "style", 5) == 0) style = true; } state = TAG; beg = --nxt; } else if (kws) kws = proxy.Move(CASE_SENSITIVE_TAG ? c : tolower(c), kws); break; case TAG: DEB_PrintState(state, c); switch (c) { case 0: case '\n': proxy.SetColor(beg, kColorTag); leave = true; break; case '>': proxy.SetColor(beg, kColorTag); beg = nxt; proxy.SetColor(beg, kColorText); if (script) state = JAVASCRIPT; else if (style) state = STYLESHEET; else state = START; break; case '"': proxy.SetColor(beg, kColorTag); beg = nxt-1; state = TAG_STRING_DOUBLE_QUOTES; break; case '\'': proxy.SetColor(beg, kColorTag); beg = nxt-1; state = TAG_STRING_SINGLE_QUOTES; break; case '!': if (nxt == beg+2) { proxy.SetColor(beg, kColorTag); state = COMMENT_DTD; forceState = START; } break; default: if (isalpha(c)) { proxy.SetColor(beg, kColorTag); beg = nxt-1; kws = proxy.Move(CASE_SENSITIVE_ATTR ? c : tolower(c), 1); state = TAG_ATTRIBUTE; } break; } break; case TAG_STRING_DOUBLE_QUOTES: DEB_PrintState(state, c); if (c == '"') { proxy.SetColor(beg, kColHtmlTagStringDoubleQuotes); beg = nxt; state = TAG; } else if (c == '\n' || c == 0) { proxy.SetColor(beg, kColHtmlTagStringDoubleQuotes); leave = true; } break; case TAG_STRING_SINGLE_QUOTES: DEB_PrintState(state, c); if (c == '\'') { proxy.SetColor(beg, kColHtmlTagStringSingleQuotes); beg = nxt; state = TAG; } else if (c == '\n' || c == 0) { proxy.SetColor(beg, kColHtmlTagStringSingleQuotes); leave = true; } break; case TAG_ATTRIBUTE: DEB_PrintState(state, c); if (!isalnum(c) && c != '-') { switch (kwc = proxy.IsKeyword(kws, kKwHtmlAttribute|kKwUsersets)) { case kKwHtmlAttribute: color = kColHtmlAttribute; break; case kKwUserset1: color = kColorUserSet1; break; case kKwUserset2: color = kColorUserSet2; break; case kKwUserset3: color = kColorUserSet3; break; case kKwUserset4: color = kColorUserSet4; break; default: color = kColorText; break; } proxy.SetColor(beg, color); DEB_PrintSetKw(state, kwc); beg = --nxt; state = TAG; } else if (kws) kws = proxy.Move(CASE_SENSITIVE_ATTR ? c : tolower(c), kws); break; case SPECIAL: DEB_PrintState(state, c); if (c == 0 || c == '\n') { proxy.SetColor(beg, kColorText); state = START; leave = true; } else if (c == ';') { proxy.SetColor(beg, kColHtmlEntity); beg = nxt; state = START; } else if (isspace(c)) state = START; break; case COMMENT_DTD: DEB_PrintState(state, c); if (c == '-' && text[nxt] == '-' && nxt == beg+3 && text[nxt-2] == '!' && text[nxt-3] == '<') { proxy.SetColor(beg, kColHtmlDtd); beg = nxt-1; state = COMMENT; } else if (c == '>') { proxy.SetColor(beg, kColHtmlDtd); beg = nxt; state = forceState; } else if (c == 0 || c == '\n') { proxy.SetColor(beg, kColHtmlDtd); leave = true; } break; case COMMENT: DEB_PrintState(state, c); if (beg == 0 && c == ':') { if (strncasecmp(text+nxt, "javascript", 10) == 0) forceState = JAVASCRIPT; else if (strncasecmp(text+nxt, "php", 3) == 0) forceState = PHP_SCRIPT; } else if (c == '-' && text[nxt] == '-') { proxy.SetColor(beg, kColHtmlComment); beg = ++nxt; state = COMMENT_DTD; } else if (c == 0 || c == '\n') { proxy.SetColor(beg, kColHtmlComment); leave = true; } break; case STYLESHEET: DEB_PrintState(state, c); if (c == '<' && text[nxt] == '/') { if (strncasecmp(text+nxt+1, "style", 5) == 0) { nxt++; state = TAG_START; } } else if (c == '/' && text[nxt] == '*') state = CSS_COMMENT; // else if (isalpha(c)) // { // kws = proxy.Move(CASE_SENSITIVE_JS ? c : tolower(c), 1); // state = JS_IDENTIFIER; // } else if (c == '{') state = CSS_DEFINITION; else if (c == 0 || c == '\n') leave = true; if ((leave || state != STYLESHEET) && beg < nxt) { proxy.SetColor(beg, kColCssText); beg = nxt-1; } break; case CSS_COMMENT: DEB_PrintState(state, c); if ((beg == 0 || nxt > beg+1) && c == '*' && text[nxt] == '/') { proxy.SetColor(beg, kColJsComment); beg = nxt+1; state = STYLESHEET; } else if (c == 0 || c == '\n') { proxy.SetColor(beg, kColJsComment); leave = true; } break; case CSS_DEFINITION: DEB_PrintState(state, c); if (c == '}') { state = STYLESHEET; } else if (c == 0 || c == '\n') leave = true; break; case JAVASCRIPT: DEB_PrintState(state, c); script = false; if (c == '<' && strncasecmp(text+nxt, "!--", 3) == 0) { proxy.SetColor(beg, kColorTag); proxy.SetColor(nxt+1, kColorComment1); nxt += 3; beg = nxt; } else if (c == '<' && text[nxt] == '/') { if (strncasecmp(text+nxt+1, "script", 6) == 0) { nxt++; state = TAG_START; } } else if (c == '/' && text[nxt] == '*') state = JS_COMMENT_MULTI_LINE; else if (c == '/' && text[nxt] == '/') state = JS_COMMENT_SINGLE_LINE; else if (isalpha(c)) { kws = proxy.Move(CASE_SENSITIVE_JS ? c : tolower(c), 1); state = JS_IDENTIFIER; } else if (c == '\'') state = JS_STRING_SINGLE_QUOTES; else if (c == '"') state = JS_STRING_DOUBLE_QUOTES; else if (c == 0 || c == '\n') leave = true; if ((leave || state != JAVASCRIPT) && beg < nxt) { proxy.SetColor(beg, kColorText); beg = nxt-1; } break; case JS_COMMENT_MULTI_LINE: DEB_PrintState(state, c); if ((beg == 0 || nxt > beg+1) && c == '*' && text[nxt] == '/') { proxy.SetColor(beg, kColJsComment); beg = nxt+1; state = JAVASCRIPT; } else if (c == 0 || c == '\n') { proxy.SetColor(beg, kColJsComment); leave = true; } break; case JS_COMMENT_SINGLE_LINE: DEB_PrintState(state, c); if (c == '-' && text[nxt] == '-') { proxy.SetColor(beg, kColJsCommentL); beg = nxt+1; state = TAG; } else if (c == '\n' || c == 0) { proxy.SetColor(beg, kColJsCommentL); state = JAVASCRIPT; leave = true; } break; case JS_IDENTIFIER: DEB_PrintState(state, c); if (!isalnum(c) && c != '_') { if (nxt > beg+1 && (kwc = proxy.IsKeyword(kws, kKwJs|kKwUsersets)) != 0) { switch (kwc) { case kKwJsLanguage: color = kColorKeyword1; break; case kKwJsConstants: color = kColorCharConst; break; case kKwUserset1: color = kColorUserSet1; break; case kKwUserset2: color = kColorUserSet2; break; case kKwUserset3: color = kColorUserSet3; break; case kKwUserset4: color = kColorUserSet4; break; default: color = kColorText; break; } proxy.SetColor(beg, color); DEB_PrintSetKw(state, kwc); } else { proxy.SetColor(beg, kColorText); } beg = --nxt; state = JAVASCRIPT; } else if (kws) kws = proxy.Move(CASE_SENSITIVE_JS ? c : tolower(c), kws); break; case JS_STRING_SINGLE_QUOTES: case JS_STRING_DOUBLE_QUOTES: DEB_PrintState(state, c); if (!esc && ((state == JS_STRING_SINGLE_QUOTES && c == '\'') || (state == JS_STRING_DOUBLE_QUOTES && c == '"'))) { proxy.SetColor(beg, (state == JS_STRING_SINGLE_QUOTES) ? kColJsStringSingleQuotes : kColJsStringDoubleQuotes); beg = nxt; state = JAVASCRIPT; } else if (c == '\n' || c == 0) { if (text[nxt-2] == '\\' && text[nxt-3] != '\\') { proxy.SetColor(beg, (state == JS_STRING_SINGLE_QUOTES) ? kColJsStringSingleQuotes : kColJsStringDoubleQuotes); } else { proxy.SetColor(beg, kColorText); state = JAVASCRIPT; } beg = size; leave = true; } else esc = !esc && (c == '\\'); break; case PHP_SCRIPT: DEB_PrintState(state, c); if (((c == '?' && !percent) || (c == '%' && percent)) && text[nxt] == '>') { proxy.SetColor(beg, kColorTag); beg = ++nxt; state = START; } else if (isalpha(c)) { kws = proxy.Move(CASE_SENSITIVE_PHP ? c : tolower(c), 1); state = PHP_IDENTIFIER; } else if (c == '"') state = PHP_STRING_DOUBLE_QUOTES; else if (c == '\'') state = PHP_STRING_SINGLE_QUOTES; else if (c == '#' || (c == '/' && text[nxt] == '/')) state = PHP_COMMENT_SINGLE_LINE; else if (c == '/' && text[nxt] == '*') state = PHP_COMMENT_MULTI_LINE; else if (c == 0 || c == '\n') leave = true; if ((leave || state != START) && beg < nxt) { proxy.SetColor(beg, kColorText); beg = nxt-1; } break; case PHP_IDENTIFIER: if (!isalnum(c) && c != '_') { if (nxt > beg+1 && (kwc = proxy.IsKeyword(kws, kKwPhp|kKwUsersets))) { DEB_PrintState(state, c, "KWD"); switch (kwc) { case kKwPhpLanguage: color = kColPhpLanguage; break; case kKwPhpFunctions: color = kColPhpFunction; break; case kKwPhpConstants: color = kColPhpConstants; break; case kKwUserset1: color = kColorUserSet1; break; case kKwUserset2: color = kColorUserSet2; break; case kKwUserset3: color = kColorUserSet3; break; case kKwUserset4: color = kColorUserSet4; break; default: color = kColorText; break; } proxy.SetColor(beg, color); DEB_PrintSetKw(state, kwc); } else { DEB_PrintState(state, c, "TXT"); proxy.SetColor(beg, kColorText); } beg = --nxt; state = PHP_SCRIPT; } else if (kws) DEB_PrintState(state, c, "MOV"); kws = proxy.Move(CASE_SENSITIVE_PHP ? c : tolower(c), kws); break; case PHP_STRING_DOUBLE_QUOTES: DEB_PrintState(state, c); if (!esc && c == '"') { proxy.SetColor(beg, kColPhpStringDoubleQuotes); beg = nxt; state = PHP_SCRIPT; } else if (c == '\n' || c == 0) { proxy.SetColor(beg, kColPhpStringDoubleQuotes); beg = size; leave = true; } else esc = !esc && (c == '\\'); break; case PHP_STRING_SINGLE_QUOTES: DEB_PrintState(state, c); if (!esc && c == '\'') { proxy.SetColor(beg, kColPhpStringSingleQuotes); beg = nxt; state = PHP_SCRIPT; } else if (c == '\n' || c == 0) { proxy.SetColor(beg, kColPhpStringSingleQuotes); beg = size; leave = true; } else esc = !esc && (c == '\\'); break; case PHP_COMMENT_MULTI_LINE: DEB_PrintState(state, c); if ((beg == 0 || nxt > beg+1) && c == '*' && text[nxt] == '/') { proxy.SetColor(beg, kColPhpComment); beg = nxt+1; state = PHP_SCRIPT; } else if (c == 0 || c == '\n') { proxy.SetColor(beg, kColPhpComment); leave = true; } else if (((percent && c == '%') || (!percent && c == '?')) && text[nxt] == '>') { proxy.SetColor(beg, kColPhpComment); beg = nxt-1; proxy.SetColor(beg, kColorTag); beg = ++nxt; state = START; } break; case PHP_COMMENT_SINGLE_LINE: DEB_PrintState(state, c); if (c == 0 || c == '\n') { proxy.SetColor(beg, kColPhpCommentL); state = PHP_SCRIPT; leave = true; } else if (((percent && c == '%') || (!percent && c == '?')) && text[nxt] == '>') { proxy.SetColor(beg, kColPhpCommentL); beg = nxt-1; proxy.SetColor(beg, kColorTag); beg = ++nxt; state = START; } break; default: // error condition, gracefully leave the loop leave = true; break; } } #if DEBUG_PHP printf("--> (%s:%s)\n", DEB_StateName(state), script ? "IsScript" : "NoScript"); #endif // if (script) // state |= 0x8000; // // if (percent) // state |= 0x4000; } /* ColorLine */
_EXPORT bool Balance(CLanguageProxy& proxy, int32& start, int32& end) { int32 langStart; Language lang = get_language_for_offset(proxy, start, langStart); const char *txt = proxy.Text(); int32 size = proxy.Size(); if (lang == kLanguageHtml) { bool in = false; if (start < 0 || start > end || end > size) return false; const char *st = txt + start; while (txt < st) { const char *t = in ? skip_in(txt + 1) : skip_out(txt + 1); in = !in; if (*t && st < t) { start = txt - proxy.Text() + 1; end = t - proxy.Text(); return true; } txt = t; } } else { if (start < 0 || start > end || end > size) return false; const char *et(txt + end); const char *st(txt + langStart); std::stack<int32> bls, sbls, pls; while (*txt && txt < et) { switch (*txt) { case '{': bls.push(txt - st); break; case '[': sbls.push(txt - st); break; case '(': pls.push(txt - st); break; case '}': if (!bls.empty()) bls.pop(); break; case ']': if (!sbls.empty()) sbls.pop(); break; case ')': if (!pls.empty()) pls.pop(); break; } txt = skip(txt + 1); } char ec = 0, oc = 0; std::stack<int32> *s = 0; int32 db, dsb, dp; db = bls.empty() ? -1 : start - bls.top(); dsb = sbls.empty() ? -1 : start - sbls.top(); dp = pls.empty() ? -1 : start - pls.top(); if (db < 0 && dsb < 0 && dp < 0) return false; if (db >= 0 && (dsb < 0 || db < dsb) && (dp < 0 || db < dp)) { oc = '{'; ec = '}'; s = &bls; } if (dsb >= 0 && (db < 0 || dsb < db) && (dp < 0 || dsb < dp)) { oc= '['; ec = ']'; s = &sbls; } if (dp >= 0 && (dsb < 0 || dp < dsb) && (db < 0 || dp < db)) { oc = '('; ec = ')'; s = &pls; } if (ec) { int32 l = 1; while (*txt) { if (*txt == ec) { if (--l == 0) { start = s->top() + 1 + langStart; end = txt - st + langStart; return true; } if (!s->empty()) s->pop(); } else if (*txt == oc) { l++; s->push(0); } txt = skip(txt + 1); } } } return false; } /* Balance */
void ScanForFunctions(CLanguageProxy& proxy) { bool sorted = proxy.Sorted(); PopupList lstHeadings, lstAnchors, lstPhpFunctions, lstPhpClasses, lstJsFunctions, lstJsClasses; const char *text = proxy.Text(), *max = text + proxy.Size(); if (*max != 0) return; if (strncasecmp(text, "<!--:javascript", 15) == 0) text = JavaScript(text, lstJsFunctions, lstJsClasses, sorted); else if (strncasecmp(text, "<!--:php", 8) == 0) text = PhpScript(text + 11, lstPhpFunctions, lstPhpClasses, sorted); while (*text && text < max) { text = skip(text, '<'); text = skip_whitespace(text); switch (toupper(*text)) { case '?': text = PhpScript(text, lstPhpFunctions, lstPhpClasses, sorted); break; case 'A': if (isspace(*++text)) text = anchor(text, proxy, lstAnchors, sorted); else text = skip_nc(text, '>'); break; case 'L': if (strncasecmp(text, "LINK", 4) == 0) text = anchor(text + 4, proxy, lstAnchors, sorted); else text = skip_nc(text, '>'); break; case 'H': if (*++text >= '1' && *text <= '6') { text = heading(text, lstHeadings, sorted); } else text = skip_nc(text, '>'); break; case 'S': if (strncasecmp(text, "SCRIPT", 6) == 0) text = JavaScript(text, lstJsFunctions, lstJsClasses, sorted); break; default: text = skip_nc(text + 1, '>'); break; } } add_to_popup("PHP-Classes", lstPhpClasses, proxy); add_to_popup("PHP-Functions", lstPhpFunctions, proxy); add_to_popup("JS-Classes", lstJsClasses, proxy); add_to_popup("JS-Functions", lstJsFunctions, proxy); add_to_popup("HTML-Anchors", lstAnchors, proxy); add_to_popup("HTML-Headings", lstHeadings, proxy); } /* ScanForFunctions */
_EXPORT void ColorLine(CLanguageProxy& proxy, int32& state) { const char *text = proxy.Text(); int32 size = proxy.Size(); char c; int32 i = 0, s = 0, kws = 0; bool leave = false, esc = false; proxy.SetColor(0, kColorText); if (size <= 0) return; while (!leave) { GETCHAR; switch (state) { case START: if (c == '<') state = TAG; else if (c == '&') state = SPECIAL; else if (c == 0 || c == '\n') leave = true; if ((leave || state != START) && s < i) { proxy.SetColor(s, kColorText); s = i - 1; } break; case TAG: case JSTAG: switch (c) { case 0: case '\n': proxy.SetColor(s, kColorTag); leave = true; break; case '>': proxy.SetColor(s, kColorTag); s = i; proxy.SetColor(s, kColorText); state--; // START break; case '"': proxy.SetColor(s, kColorTag); s = i - 1; state++; // TAGSTRING1 break; case '\'': proxy.SetColor(s, kColorTag); s = i - 1; state += 2; // TAGSTRING2 break; case '!': if (i == s + 2) { proxy.SetColor(s, kColorTag); state += 5; // COMMENT_DTD } break; default: if (isalpha(c)) { proxy.SetColor(s, kColorTag); s = i - 1; kws = proxy.Move(tolower(c), 1); state += 3; // TAGKEYWORD } break; } break; case TAGSTRING1: case JSTAGSTRING1: if (c == '"') { proxy.SetColor(s, kColorString2); s = i; state--; // TAG } else if (c == '\n' || c == 0) { proxy.SetColor(s, kColorString2); leave = true; } break; case TAGSTRING2: case JSTAGSTRING2: if (c == '\'') { proxy.SetColor(s, kColorString2); s = i; state -= 2; // TAG } else if (c == '\n' || c == 0) { proxy.SetColor(s, kColorString2); leave = true; } break; case TAGKEYWORD: case JSTAGKEYWORD: if (! isalnum(c)) { switch (proxy.IsKeyword(kws)) { case 1: proxy.SetColor(s, kColorKeyword1); break; case 2: proxy.SetColor(s, kColorUserSet1); break; case 3: proxy.SetColor(s, kColorUserSet2); break; case 4: proxy.SetColor(s, kColorUserSet3); break; case 5: proxy.SetColor(s, kColorUserSet4); break; default: proxy.SetColor(s, kColorTag); break; } if (strncasecmp(text + s, "SCRIPT", 6) == 0) { if (state == TAGKEYWORD) state += JAVASCRIPT; else state -= JAVASCRIPT; } s = --i; state -= 3; // TAG } else if (kws) kws = proxy.Move(tolower(c), kws); break; case SPECIAL: case JSSPECIAL: if (c == 0 || c == '\n') { proxy.SetColor(s, kColorText); state = START; leave = true; } else if (c == ';') { proxy.SetColor(s, kColorCharConst); s = i; state = START; } else if (isspace(c)) state = START; break; case COMMENT_DTD: case JSCOMMENT_DTD: if (c == '-' && text[i] == '-' && i == s + 3 && text[i - 2] == '!' && text[i - 3] == '<') { proxy.SetColor(s, kColorTag); s = i - 1; state++; } else if (c == '>') { proxy.SetColor(s, kColorTag); s = i; state -= 5; } else if (c == 0 || c == '\n') { proxy.SetColor(s, kColorTag); leave = true; } break; case COMMENT: if (c == '-' && text[i] == '-') { proxy.SetColor(s, kColorComment1); s = ++i; state = COMMENT_DTD; } else if (c == 0 || c == '\n') { proxy.SetColor(s, kColorComment1); leave = true; } break; case JSCOMMENT: state = JAVASCRIPT; i--; break; case JAVASCRIPT: if (c == '<') { if (strncasecmp(text + i, "/script", 7) == 0) state = JSTAG; } // { // if (strncmp(text + i, "!--", 3)) // state = JSTAG; // } else if (c == '/' && text[i] == '*') state = JS_COMMENT; else if (c == '/' && text[i] == '/') state = JS_LCOMMENT; else if (isalpha(c)) { kws = proxy.Move(tolower(c), 1); state = JS_IDENT; } else if (c == '\'') state = JS_STRING1; else if (c == '"') state = JS_STRING2; else if (c == 0 || c == '\n') leave = true; if ((leave || state != JAVASCRIPT) && s < i) { proxy.SetColor(s, kColorText); s = i - 1; } break; case JS_COMMENT: if ((s == 0 || i > s + 1) && c == '*' && text[i] == '/') { proxy.SetColor(s, kColorComment1); s = i + 1; state = JAVASCRIPT; } else if (c == 0 || c == '\n') { proxy.SetColor(s, kColorComment1); leave = true; } break; case JS_LCOMMENT: proxy.SetColor(s, kColorComment1); leave = true; if (text[size - 1] == '\n') state = JAVASCRIPT; break; case JS_IDENT: if (!isalnum(c) && c != '_' && c != '.') { int32 kwc; if (i > s + 1 && (kwc = proxy.IsKeyword(kws)) != 0) { switch (kwc) { case 1: case 6: proxy.SetColor(s, kColorKeyword1); break; case 2: proxy.SetColor(s, kColorUserSet1); break; case 3: proxy.SetColor(s, kColorUserSet2); break; case 4: proxy.SetColor(s, kColorUserSet3); break; case 5: proxy.SetColor(s, kColorUserSet4); break; // default: ASSERT(false); } } else { proxy.SetColor(s, kColorText); } s = --i; state = JAVASCRIPT; } else if (kws) kws = proxy.Move((int)(unsigned char)c, kws); break; case JS_STRING1: case JS_STRING2: if (!esc && ((state == JS_STRING1 && c == '\'') || (state == JS_STRING2 && c == '"'))) { proxy.SetColor(s, kColorString1); s = i; state = JAVASCRIPT; } else if (c == '\n' || c == 0) { if (text[i - 2] == '\\' && text[i - 3] != '\\') { proxy.SetColor(s, kColorString1); } else { proxy.SetColor(s, kColorText); state = JAVASCRIPT; } s = size; leave = true; } else esc = !esc && (c == '\\'); break; default: // error condition, gracefully leave the loop leave = true; break; } } } /* ColorLine */
_EXPORT void ColorLine(CLanguageProxy& proxy, int& state) { const char *text = proxy.Text(); int size = proxy.Size(); int i = 0, s = 0, kws = 0, esc = 0; char c, mc = 0; bool leave = false; if (state == COMMENT || state == LCOMMENT) proxy.SetColor(0, kColorComment1); else proxy.SetColor(0, kColorText); if (size <= 0) return; while (!leave) { GETCHAR; switch (state) { case START: if (c == '#' && text[i - 2] != '$') state = LCOMMENT; else if (isalpha(c) || c == '_') { kws = proxy.Move(c, 1); state = IDENT; } else if (c == '"') state = STRING1; else if (c == '\'') state = STRING2; else if (c == '&') state = SCOPE; else if (c == '$') { if (isalpha(text[i]) || text[i] == '#') { i++; state = VAR; } else { i++; proxy.SetColor(s, kColorText); s = i; } } else if (c == '@' || c == '*') state = VAR; else if (c == '/') { mc = '/'; state = REGEX1; } else if (c == '\n' || c == 0) leave = true; if (leave || (state != START && s < i)) { proxy.SetColor(s, kColorText); s = i - 1; } break; case LCOMMENT: proxy.SetColor(s, kColorComment1); leave = true; if (text[size - 1] == '\n') state = START; break; case IDENT: if (!isalnum(c) && c != '_') { int kwc; if (i >= s + 1 && (kwc = proxy.IsKeyword(kws)) != 0) { switch (kwc) { case 1: proxy.SetColor(s, kColorKeyword1); break; case 2: proxy.SetColor(s, kColorUserSet1); break; case 3: proxy.SetColor(s, kColorUserSet2); break; case 4: proxy.SetColor(s, kColorUserSet3); break; case 5: proxy.SetColor(s, kColorUserSet4); break; // default:ASSERT(false); } } else { proxy.SetColor(s, kColorText); } if (i == s + 2) { switch (*(text + s)) { case 'm': state = REGEX1; break; case 's': state = REGEX2; break; case 'q': state = REGEX1; break; case 'y': state = REGEX2; break; default: state = START; break; } } else if (i == s + 3) { if (strncmp(text + s, "qq", 2) == 0) state = REGEX1; else if (strncmp(text + s, "qx", 2) == 0) state = REGEX1; else if (strncmp(text + s, "qw", 2) == 0) state = REGEX1; else if (strncmp(text + s, "tr", 2) == 0) state = REGEX2; else state = START; } else if (i == s + 4 && strncmp(text + s, "sub", 3) == 0)// && ci < 2) state = SUB1; else state = START; if (state == START || state == SUB1) s = --i; else { switch (c) { case '(': mc = ')'; break; case '{': mc = '}'; break; case '[': mc = ']'; break; case '<': mc = '>'; break; case ' ': state = START; s = --i; break; default: mc = c; break; } if (state != START) s = i - 1; } } else if (kws) kws = proxy.Move((int)(unsigned char)c, kws); break; case SUB1: if (isalpha(c)) state = SUB2; else if (!isspace(c)) { state = START; s = --i; } break; case SUB2: if (!isalnum(c) && c != '\'' && c != '_') { proxy.SetColor(s, kColorText); state = START; s = --i; } break; case STRING1: if (c == '"' && !esc) { proxy.SetColor(s, kColorString1); s = i; state = START; } else if (c == '\n' || c == 0) { if (text[i - 2] == '\\' && text[i - 3] != '\\') { proxy.SetColor(s, kColorString1); } else { proxy.SetColor(s, kColorText); state = START; } s = size; leave = true; } else esc = !esc && (c == '\\'); break; case STRING2: if (c == '\'' && !esc) { proxy.SetColor(s, kColorString1); s = i; state = START; } else if (c == '\n' || c == 0) { if (text[i - 2] == '\\' && text[i - 3] != '\\') { proxy.SetColor(s, kColorString1); } else { proxy.SetColor(s, kColorText); state = START; } s = size; leave = true; } else esc = !esc && (c == '\\'); break; case REGEX1: if (c == 0) // don't like this { proxy.SetColor(s, kColorText); s = i; state = START; } else if (c == mc && !esc) { proxy.SetColor(s, kColorCharConst); s = i; state = START; } else esc = !esc && (c == '\\'); break; case REGEX2: if (c == 0) // don't like this { proxy.SetColor(s, kColorText); s = i; state = START; } else if (c == mc && !esc) { if (mc == ')' || mc == '}' || mc == ']' || mc == '>') { switch (text[i]) { case '(': mc = ')'; break; case '{': mc = '}'; break; case '[': mc = ']'; break; case '<': mc = '>'; break; case ' ': state = START; s = --i; break; default: mc = text[i]; break; } i++; } if (state != START) state = REGEX1; } else esc = !esc && (c == '\\'); break; case SCOPE: if (c == '\'' || (!isalnum(c) && c != '_')) { proxy.SetColor(s, kColorText); state = START; } break; case VAR: if (!isalnum(c) && c != '_') { proxy.SetColor(s, kColorText); state = START; } break; default: // error condition, gracefully leave the loop leave = true; break; } } } /* CperlIntf::ColorLine */
_EXPORT void ColorLine(CLanguageProxy& proxy, int& state) { const char *text = proxy.Text(); int size = proxy.Size(); int i = 0, s = 0, kws = 0, cc_cnt = 0, esc = 0; char c; bool leave = false; // floating point flag, true when the NUMERIC: label finds a . inside a number, and checks to make sure that a number with two '.' is invalid. (and not highlighted as numeric) bool floating_point = false; // same flag, only for hex numbers. allows proper highlighting only for 1 x per number. (0x21 is ok. 0x023x31 is not. will look wierd.) bool hex_num = false; int ifZeroCounter = state >> STATE_SHIFT; state = state & STATE_MASK; if (state == COMMENT || state == LCOMMENT) proxy.SetColor(0, kColorComment1); else proxy.SetColor(0, kColorText); if (size <= 0) return; while (!leave) { GETCHAR; switch (state) { case START: s = i - 1; proxy.SetColor(s, kColorText); if (c == '#') { kws = proxy.Move(c, 1); state = PRAGMA1; } else if (isalpha(c) || c == '_') { kws = proxy.Move(c, 1); state = IDENT; } else if (c == '/' && text[i] == '*') { i++; state = COMMENT; } else if (c == '/' && text[i] == '/') { i++; state = LCOMMENT; } else if (c == '"') state = STRING; else if (c == '\'') { state = CHAR_CONST; cc_cnt = 0; } // m7m: here are the 3 magic IFs. else if (isNumeric(c)) { state = NUMERIC; } else if (isOperator(c)) { state = OPERATOR; } else if (isSymbol(c)) { state = SYMBOL; } else if (c == '\n' || c == 0) leave = true; break; case COMMENT: if ((s == 0 || i > s + 1) && c == '*' && text[i] == '/') { proxy.SetColor(s, kColorComment1); i++; state = START; } else if (c == 0 || c == '\n') { proxy.SetColor(s, kColorComment1); leave = true; } break; case LCOMMENT: proxy.SetColor(s, kColorComment1); leave = true; if (text[size - 1] == '\n') state = START; break; case IDENT: if (!isalnum(c) && c != '_') { int kwc; if (i > s + 1 && (kwc = proxy.IsKeyword(kws)) != 0) { switch (kwc) { case 1: proxy.SetColor(s, kColorKeyword1); break; case 2: proxy.SetColor(s, kColorUserSet1); break; case 3: proxy.SetColor(s, kColorUserSet2); break; case 4: proxy.SetColor(s, kColorUserSet3); break; case 5: proxy.SetColor(s, kColorUserSet4); break; // default: ASSERT(false); } } else proxy.SetColor(s, kColorText); i--; state = START; } else if (kws) kws = proxy.Move((int)(unsigned char)c, kws); break; case PRAGMA1: if (c == ' ' || c == '\t') ; else if (islower(c)) { kws = proxy.Move((int)(unsigned char)c, kws); state = PRAGMA2; } else { proxy.SetColor(s, kColorText); i--; state = START; } break; case PRAGMA2: if (!islower(c)) { int kwc; if (i > s + 2 && (kwc = proxy.IsKeyword(kws)) != 0) { switch (kwc) { case 1: proxy.SetColor(s, kColorKeyword1); break; case 2: proxy.SetColor(s, kColorUserSet1); break; case 3: proxy.SetColor(s, kColorUserSet2); break; case 4: proxy.SetColor(s, kColorUserSet3); break; case 5: proxy.SetColor(s, kColorUserSet4); break; // default: ASSERT(false); } // check for "#if 0" or "elif 0" bool ifZero = false; int k = s + 1; while (text[k] == ' ' || text[k] == '\t') k++; int len = i - 1 - k; if (strings_equal(text + k, "if", len, 2) || strings_equal(text + k, "elif", len, 4)) { k = i - 1; while (text[k] == ' ' || text[k] == '\t') k++; if (text[k] == '0' && (k + 1 == size || text[k + 1] == 0 || isspace(text[k + 1]))) { proxy.SetColor(s, kColorComment1); state = IF_ZERO; ifZeroCounter = 1; leave = true; } } } else { proxy.SetColor(s, kColorText); } if (state != IF_ZERO) { state = strncmp(text+i-8, "include", 7) ? START : INCL1; s = --i; } } else if (kws) kws = proxy.Move((int)(unsigned char)c, kws); break; case INCL1: if (c == '"') state = INCL2; else if (c == '<') state = INCL3; else if (c != ' ' && c != '\t') { state = START; i--; } break; case INCL2: if (c == '"') { proxy.SetColor(s, kColorString1); state = START; } else if (c == '\n' || c == 0) { proxy.SetColor(s, kColorText); leave = true; state = START; } break; case INCL3: if (c == '>') { proxy.SetColor(s, kColorString1); state = START; } else if (c == '\n' || c == 0) { proxy.SetColor(s, kColorText); leave = true; state = START; } break; case STRING: if (c == '"' && !esc) { proxy.SetColor(s, kColorString1); state = START; } else if (c == '\n' || c == 0) { if (text[i - 2] == '\\' && text[i - 3] != '\\') { proxy.SetColor(s, kColorString1); } else { proxy.SetColor(s, kColorText); state = START; } leave = true; } else esc = !esc && (c == '\\'); break; case CHAR_CONST: if (c == '\t' || c == '\n' || c == 0 || (c == '\'' && !esc && (cc_cnt == 0 || cc_cnt > 5))) { // invalid char constant - either invalid char or too short/long proxy.SetColor(s, kColorText); state = START; } else if (c == '\'' && !esc) { proxy.SetColor(s, kColorCharConst); state = START; } else { if (!esc) cc_cnt++; esc = !esc && (c == '\\'); } break; case NUMERIC: { proxy.SetColor(s, kColorNumber1); if (isNumeric(text[i-1]) || (hex_num && isHexNum(text[i - 1]))) ; else if (text[i-1]=='.' && floating_point==false && hex_num==false) floating_point = true; else if (text[i-1]=='x' && hex_num==false && floating_point==false) hex_num = true; else { i--; hex_num = false; state = START; } } break; case OPERATOR: { proxy.SetColor(s, kColorOperator1); if (isOperator(text[i-1])) ; else { i--; state = START; } } break; case SYMBOL: { proxy.SetColor(s, kColorSeparator1); if (isSymbol(text[i-1])) ; else { i--; state = START; } } break; case IF_ZERO: { if (isspace(c)) break; proxy.SetColor(i - 1, kColorComment1); if (c == '#') { // get the preprocessor keyword while (isspace(GETCHAR)); int s = i - 1; int end = s; while (end < size && text[end] != 0 && !isspace(text[end])) end++; int len = end - s; // on "#if", "#ifdef", "#ifndef" increment the nesting // counter if (strings_equal(text + s, "if", len, 2) || strings_equal(text + s, "ifdef", len, 5) || strings_equal(text + s, "ifndef", len, 6)) { ifZeroCounter++; i = end + 1; } // on "endif" decrement the nesting counter else if (strings_equal(text + s, "endif", len, 5)) { ifZeroCounter--; i = end + 1; // if the counter drops to zero, we fall be to normal // parsing if (ifZeroCounter == 0) { state = START; leave = true; break; } } // on "else" or "elif" and nest count 1, fall back to normal // parsing: else if (ifZeroCounter == 1 && (strings_equal(text + s, "else", len, 4) || strings_equal(text + s, "elif", len, 4))) { i = end + 1; ifZeroCounter == 0; state = START; leave = true; break; } } // we need to check for C style comments int commentOffset; if (find_comment_start(text + i - 1, size - i + 1, commentOffset)) { state = IF_ZERO_COMMENT; i += commentOffset + 1; } else leave = true; } break; case IF_ZERO_COMMENT: { proxy.SetColor(i - 1, kColorComment1); int commentEnd; if (find_comment_end(text + i - 1, size - i + 1, commentEnd)) { i += commentEnd + 1; state = IF_ZERO; } else leave = true; } break; default: // error condition, gracefully leave the loop leave = true; break; } } state |= ifZeroCounter << STATE_SHIFT; } /* ColorLine */
_EXPORT void ColorLine(CLanguageProxy& proxy, int32& state) { const char *text = proxy.Text(); int32 size = proxy.Size(); int32 i = 0, s = 0, kws = 0, esc = 0; char c; bool leave = false; bool floating_point = false; bool hex_num = false; // int sqrBraquetStrCount = 0; if (state == LCOMMENT) proxy.SetColor(0, kColorComment1); else proxy.SetColor(0, kColorText); if (size <= 0) return; while (!leave) { GETCHAR; switch (state) { case START: if (isalpha(c) || c == '_') { kws = proxy.Move(tolower(c), 1); state = IDENT; } else if (c == '-' && text[i] == '-') { i++; state = LCOMMENT; } else if (c == '"') state = STRING; else if (c == '\'') state = STRING2; /* else if (c == '[' && text[i] == '[') { sqrBraquetStrCount++; state = STRING3; } */ else if (isNumeric(c) || (c == '$' && isHexNum(text[i]))) { state = NUMERIC; } else if (isOperator(c)) { state = OPERATOR; } else if (isSymbol(c)) { state = SYMBOL; } else if (c == '\n' || c == 0) leave = true; if (leave || (state != START && s < i)) { proxy.SetColor(s, kColorText); s = i - 1; } break; // -- format comments case LCOMMENT: proxy.SetColor(s - 1, kColorComment1); leave = true; if (text[size - 1] == '\n') state = START; break; case IDENT: if (!isalnum(c) && c != '_') { int32 kwc; if (i > s + 1 && (kwc = proxy.IsKeyword(kws)) != 0) { switch (kwc) { case 1: proxy.SetColor(s, kColorKeyword1); break; case 2: proxy.SetColor(s, kColorUserSet1); break; case 3: proxy.SetColor(s, kColorUserSet2); break; case 4: proxy.SetColor(s, kColorUserSet3); break; case 5: proxy.SetColor(s, kColorUserSet4); break; } s = --i; state = START; } else { proxy.SetColor(s, kColorText); s = --i; state = START; } } else if (kws) kws = proxy.Move((int)(unsigned char) c, kws); break; case STRING: if (c == '"' && !esc) { proxy.SetColor(s, kColorString1); s = i; state = START; } else if (c == '\n' || c == 0) { if (text[i - 2] == '\\' && text[i - 3] != '\\') { proxy.SetColor(s, kColorString1); } else { proxy.SetColor(s, kColorText); state = START; } s = size; leave = true; } else esc = !esc && (c == '\\'); break; case STRING2: if (c == '\'' && !esc) { proxy.SetColor(s, kColorString1); s = i; state = START; } else if (c == '\n' || c == 0) { if (text[i - 2] == '\\' && text[i - 3] != '\\') { proxy.SetColor(s, kColorString1); } else { proxy.SetColor(s, kColorText); state = START; } s = size; leave = true; } else esc = !esc && (c == '\\'); break; /* case STRING3: break; */ case NUMERIC: proxy.SetColor(s, kColorNumber1); if (isNumeric(text[i - 1]) || (hex_num && isHexNum(text[i - 1]))) ; else if (text[i - 1] == '.' && floating_point == false) floating_point = true; else if (isHexNum(text[i - 1]) && hex_num == false) hex_num = true; else { s = i - 1; i--; state = START; } break; case OPERATOR: proxy.SetColor(s, kColorOperator1); if (isOperator(text[i - 1])) ; else { s = i - 1; i--; state = START; } break; case SYMBOL: proxy.SetColor(s, kColorSeparator1); if (isSymbol(text[i - 1])) ; else { s = i - 1; i--; state = START; } break; default: leave = true; break; } } }
_EXPORT void ColorLine(CLanguageProxy& proxy, int32& state) { const char *text = proxy.Text(); int32 size = proxy.Size(); int32 i = 0, s = 0, kws = 0, esc = 0; char c; bool leave = false; if (state == LCOMMENT) proxy.SetColor(0, kColorComment1); else proxy.SetColor(0, kColorText); if (size <= 0) return; while (!leave) { GETCHAR; if (c == '`') { GETCHAR; c = ' '; } switch (state) { case START: if (c == '\\') state = COMMAND1; else if (c == '%') state = LCOMMENT; else if (c == '$') state = MATH; else if (c == '\n' || c == 0) leave = true; else if (isalnum(c)) state = WORD; /* This is a bit strange to have some of the characters covered above, but who cares?*/ else if (c == '#' || c == '&' || c == '~' || c == '_' || c == '^' || c == '{' || c == '}' || c == '[' || c == ']' ) state = CONSTCHAR; if ((leave || state != START) && s < i) { proxy.SetColor(s, kColorText); s = i - 1; } break; case CONSTCHAR: proxy.SetColor(s, kColorCharConst); s = --i; state = START; break; case WORD: if (!isalnum(c)) { proxy.SetColor(s, kColorText); s = --i; state = START; } break; case LCOMMENT: proxy.SetColor(s, kColorComment1); leave = true; if (text[size - 1] == '\n') state = START; break; case COMMAND1: if (c=='('){ state = MATH; } else if ((isalnum(c)) || (c=='@')) /* a generic command has been found. */ /* Note that commands with "@" in their name only appear in .cls or .sty files */ { kws = proxy.Move(c, 1); state = COMMAND2; } else /* we are escaping a special text character such as \# or \$*/ { proxy.SetColor(s, kColorText); s = i; state = START; } break; case COMMAND2: /* Inside the name of a generic command */ if (!(isalnum(c)) && !(c=='@')) /* found end of command name */ { /* now check the command name against a keyword list */ int kwc; if (i > s + 1 && (kwc = proxy.IsKeyword(kws)) != 0) { switch (kwc) { /* use a specific keyword category color */ case 1: proxy.SetColor(s, kColorKeyword1); break; case 2: proxy.SetColor(s, kColorUserSet1); break; case 3: proxy.SetColor(s, kColorUserSet2); break; case 4: proxy.SetColor(s, kColorUserSet3); break; case 5: proxy.SetColor(s, kColorUserSet4); break; // default: ASSERT(false); } } else /* use a generic keyword color */ { proxy.SetColor(s, kColorKeyword1); } s = --i; state = START; } else if (kws) /* still in command name */ kws = proxy.Move((int)(unsigned char)c, kws); break; case MATH: /* both "$" and "\)" will end math mode */ if ( (c == '$' && !esc) || (c == ')' && esc) ) { proxy.SetColor(s, kColorString1); s = i; state = START; } else if (c == '\n' || c == 0) { proxy.SetColor(s, kColorString1); leave = true; } else esc = !esc && (c == '\\'); break; default: // error condition, gracefully leave the loop leave = true; break; } } } /* ColorLine */
_EXPORT void ColorLine(CLanguageProxy& proxy, int32& state) { const char *text = proxy.Text(); int32 size = proxy.Size(); int32 i = 0, s = 0, kws = 0, esc = 0; char c = 0; bool leave = false; if (state == LCOMMENT) proxy.SetColor(0, kColorComment1); else proxy.SetColor(0, kColorText); if (size <= 0) return; while (!leave) { char b = c; GETCHAR; switch (state) { case START: if (c == '#' && (!b || isspace(b))) state = LCOMMENT; else if (isalpha(c) || c == '_') { kws = proxy.Move(c, 1); state = IDENT; } else if (c == '"') state = STRING1; else if (c == '\'') state = STRING2; else if (c == '\n' || c == 0) leave = true; if (leave || (state != START && s < i)) { proxy.SetColor(s, kColorText); s = i - 1; } break; case LCOMMENT: proxy.SetColor(s, kColorComment1); leave = true; if (text[size - 1] == '\n') state = START; break; case IDENT: if (!isalnum(c) && c != '_') { int kwc; if (i >= s + 1 && (kwc = proxy.IsKeyword(kws)) != 0) { switch (kwc) { case 1: proxy.SetColor(s, kColorKeyword1); break; case 2: proxy.SetColor(s, kColorUserSet1); break; case 3: proxy.SetColor(s, kColorUserSet2); break; case 4: proxy.SetColor(s, kColorUserSet3); break; case 5: proxy.SetColor(s, kColorUserSet4); break; // default:ASSERT(false); } } else { proxy.SetColor(s, kColorText); } s = --i; state = START; } else if (kws) kws = proxy.Move((int)(unsigned char)c, kws); break; case STRING1: if (c == '"' && !esc) { proxy.SetColor(s, kColorString1); s = i; state = START; } else if (c == '\n' || c == 0) { if (text[i - 2] == '\\' && text[i - 3] != '\\') { proxy.SetColor(s, kColorString1); } else { proxy.SetColor(s, kColorText); state = START; } s = size; leave = true; } else esc = !esc && (c == '\\'); break; case STRING2: if (c == '\'' && !esc) { proxy.SetColor(s, kColorString1); s = i; state = START; } else if (c == '\n' || c == 0) { if (text[i - 2] == '\\' && text[i - 3] != '\\') { proxy.SetColor(s, kColorString1); } else { proxy.SetColor(s, kColorText); state = START; } s = size; leave = true; } else esc = !esc && (c == '\\'); break; default: // error condition, gracefully leave the loop leave = true; break; } } } /* CshellIntf::ColorLine */
Language get_language_for_offset(const CLanguageProxy& proxy, int32 inOffset, int32& outLangStart) { const char *text = proxy.Text(); int32 size = proxy.Size(), forceState = START; if (inOffset > size) inOffset = size; char c = 0; int32 i = 0, bo = 0, s = 0; bool leave = false, esc = false, script = false, percent = false; int state = 0; while (i < inOffset) { c = get_char(i, size, text); switch (state) { case START: if (c == '<') state = TAG_START; else if (c == '&') state = SPECIAL; else if (c == 0 || c == '\n') leave = true; if ((leave || state != START) && s < i) s = i - 1; break; case TAG_START: if (c == '/') state = TAG_KEYWORD_END; else if (c == '!') { state = COMMENT_DTD; forceState = START; } else if (c == '?' || c == '%') { s = i; outLangStart = s; if (strncasecmp(text + s, "php", 3) == 0) s = (i += 3); state = PHP_SCRIPT; percent = (c == '%'); } else if (isalpha(c)) { s = i - 1; state = TAG_KEYWORD_START; } else if (c == 0 || c == '\n') { leave = true; } else if (!isspace(c)) { --i; state = TAG; } break; case TAG_KEYWORD_END: if (isalpha(c)) { s = i - 1; state = TAG_KEYWORD_START; } else if (c == 0 || c == '\n') { leave = true; } else if (!isspace(c)) { --i; state = TAG; } break; case TAG_KEYWORD_START: if (!isalnum(c) && c != '-') { if (strncasecmp(text + s, "script", 6) == 0 && text[s - 1] != '/') script = true; state = TAG; s = --i; } break; case TAG: switch (c) { case 0: case '\n': leave = true; break; case '>': s = i; if (script) { outLangStart = s; state = JAVASCRIPT; } else state = START; break; case '"': s = i - 1; state = TAG_STRING_DOUBLE_QUOTES; break; case '\'': s = i - 1; state = TAG_STRING_SINGLE_QUOTES; break; case '!': if (i == s + 2) { state = COMMENT_DTD; forceState = START; } break; default: if (isalpha(c)) { s = i - 1; state = TAG_ATTRIBUTE; } break; } break; case TAG_STRING_DOUBLE_QUOTES: if (c == '"') { s = i; state = TAG; } else if (c == '\n' || c == 0) leave = true; break; case TAG_STRING_SINGLE_QUOTES: if (c == '\'') { s = i; state = TAG; } else if (c == '\n' || c == 0) leave = true; break; case TAG_ATTRIBUTE: if (!isalnum(c) && c != '-') { s = --i; state = TAG; } break; case SPECIAL: if (c == 0 || c == '\n') { state = START; leave = true; } else if (c == ';') { s = i; state = START; } else if (isspace(c)) state = START; break; case COMMENT_DTD: if (c == '-' && text[i] == '-' && i == s + 3 && text[i - 2] == '!' && text[i - 3] == '<') { s = i - 1; forceState = START; state = COMMENT; } else if (c == '>') { s = i; state = forceState; } else if (c == 0 || c == '\n') { leave = true; } break; case COMMENT: if (c == ':') { if (strncasecmp(text, "JavaScript", 10) == 0) forceState = JAVASCRIPT; else if (strncasecmp(text, "PHP", 3) == 0) forceState = PHP_SCRIPT; } else if (c == '-' && text[i] == '-') { s = ++i; state = COMMENT_DTD; } else if (c == 0 || c == '\n') { leave = true; } break; case JAVASCRIPT: script = false; if (c == '<' && strncasecmp(text + i, "!--", 3) == 0) { i += 3; s = i; } else if (c == '<' && text[i] == '/') { if (strncasecmp(text + i + 1, "script", 6) == 0) { i--; state = TAG_START; outLangStart = i - 1; } } else if (c == '/' && text[i] == '*') state = JS_COMMENT_MULTI_LINE; else if (c == '/' && text[i] == '/') state = JS_COMMENT_SINGLE_LINE; else if (isalpha(c)) state = JS_IDENTIFIER; else if (c == '\'') state = JS_STRING_SINGLE_QUOTES; else if (c == '"') state = JS_STRING_DOUBLE_QUOTES; else if (c == 0 || c == '\n') leave = true; if ((leave || state != JAVASCRIPT) && s < i) s = i - 1; break; case JS_COMMENT_MULTI_LINE: if ((s == 0 || i > s + 1) && c == '*' && text[i] == '/') { s = i + 1; state = JAVASCRIPT; } else if (c == 0 || c == '\n') leave = true; break; case JS_COMMENT_SINGLE_LINE: if (c == '-' && text[i] == '-') { s = i + 1; state = TAG; outLangStart = s; } else if (c == '\n' || c == 0) { state = JAVASCRIPT; leave = true; } break; case JS_IDENTIFIER: if (!isalnum(c) && c != '_') { s = --i; state = JAVASCRIPT; } break; case JS_STRING_SINGLE_QUOTES: case JS_STRING_DOUBLE_QUOTES: if (!esc && ((state == JS_STRING_SINGLE_QUOTES && c == '\'') || (state == JS_STRING_DOUBLE_QUOTES && c == '"'))) { s = i; state = JAVASCRIPT; } else if (c == '\n' || c == 0) { if (!(text[i - 2] == '\\' && text[i - 3] != '\\')) state = JAVASCRIPT; s = size; leave = true; } else esc = !esc && (c == '\\'); break; case PHP_SCRIPT: if (((c == '?' && !percent) || (c == '%' && percent)) && text[i] == '>') { s = ++i; state = START; outLangStart = s; } else if (isalpha(c)) { state = PHP_IDENTIFIER; } else if (c == '"') state = PHP_STRING_DOUBLE_QUOTES; else if (c == '\'') state = PHP_STRING_SINGLE_QUOTES; else if (c == '#' || (c == '/' && text[i] == '/')) state = PHP_COMMENT_SINGLE_LINE; else if (c == '/' && text[i] == '*') state = PHP_COMMENT_MULTI_LINE; else if (c == 0 || c == '\n') leave = true; if ((leave || state != START) && s < i) s = i - 1; break; case PHP_IDENTIFIER: if (!isalnum(c) && c != '_') { s = --i; state = PHP_SCRIPT; } break; case PHP_STRING_DOUBLE_QUOTES: if (!esc && c == '"') { s = i; state = PHP_SCRIPT; } else if (c == '\n' || c == 0) { s = size; leave = true; } else esc = !esc && (c == '\\'); break; case PHP_STRING_SINGLE_QUOTES: if (!esc && c == '\'') { s = i; state = PHP_SCRIPT; } else if (c == '\n' || c == 0) { s = size; leave = true; } else esc = !esc && (c == '\\'); break; case PHP_COMMENT_MULTI_LINE: if ((s == 0 || i > s + 1) && c == '*' && text[i] == '/') { s = i + 1; state = PHP_SCRIPT; } else if (c == 0 || c == '\n') { leave = true; } else if (((percent && c == '%') || (!percent && c == '?')) && text[i] == '>') { s = i - 1; s = ++i; state = START; outLangStart = s; } break; case PHP_COMMENT_SINGLE_LINE: if (c == 0 || c == '\n') { state = PHP_SCRIPT; leave = true; } else if (((percent && c == '%') || (!percent && c == '?')) && text[i] == '>') { s = i - 1; s = ++i; state = START; outLangStart = s; } break; default: // error condition, gracefully leave the loop leave = true; break; } if (leave) { while (c != '\n' && c != 0 && i < inOffset) c = get_char(i, size, text); s = i; leave = false; } } if (state >= JAVASCRIPT && state <= JS_STRING_DOUBLE_QUOTES) return kLanguageJs; else if (state >= PHP_SCRIPT && state <= PHP_STRING_SINGLE_QUOTES) return kLanguagePhp; else return kLanguageHtml; } /* get_language_for_offset */