MCEditColorer(WEdit *edit) { try{ if (pf == null) { pf = new ParserFactory(); // cleanup color index map for (int idx = 0; idx < 16*16; idx++){ colorer_color_map[idx] = -1; } } this->edit = edit; colorer_store_handle(edit, this); lineSource = new MCLineSource(edit); baseEditor = new BaseEditor(pf, lineSource); baseEditor->chooseFileType(&DString(colorer_get_filename(edit))); /* Loading color style */ try { if (*colorer_hrd_string == 0) { strcpy(colorer_hrd_string, "default"); } baseEditor->setRegionMapper(&DString("console"), &DString(colorer_hrd_string)); } catch (Exception &e) { baseEditor->setRegionMapper(&DString("console"), &DString("default")); } baseEditor->setRegionCompact(true); const Region *def_Outlined = pf->getHRCParser()->getRegion(&DString("def:Outlined")); const Region *def_Error = pf->getHRCParser()->getRegion(&DString("def:Error")); structOutliner = new Outliner(baseEditor, def_Outlined); //errorOutliner = new Outliner(baseEditor, def_Error); CLR_TRACE("MC", "filename: %s", colorer_get_filename(edit)); CLR_TRACE("MC", "filetype: %s", baseEditor->getFileType()->getName()->getChars()); def_fore = StyledRegion::cast(baseEditor->rd_def_Text)->fore; def_back = StyledRegion::cast(baseEditor->rd_def_Text)->back; def_mc = colorer_convert_color(StyledRegion::cast(baseEditor->rd_def_Text)); // def_mc_bg= try_alloc_color_pair(null, win_colors[def_back]); CLR_TRACE("MC", "def_fore=%d, def_back=%d, def_mc=%d", def_fore, def_back, def_mc); CLR_TRACE("MC", "def_mc_bg=%d", def_mc_bg); pairMatch = null; } catch(Exception &e) { // TODO: notify about disabled colorer CLR_TRACE("MC", "Exception in MCEditColorer: %s", e.getMessage()->getChars()); option_syntax_colorer = 0; return; } }
void FarEditor::addFARColor(int lno, int s, int e, int col) { EditorColor ec; ec.StringNumber = lno; ec.StartPos = s; ec.EndPos = e-1; ec.Color = col; CLR_TRACE("FarEditor", "line:%d, %d-%d, color:%x", lno, s, e, col); info->EditorControl(ECTL_ADDCOLOR, &ec); CLR_TRACE("FarEditor", "line %d: %d-%d: color=%x", lno, s, e, col); }
void BaseEditor::modifyEvent(int topLine){ CLR_TRACE("BaseEditor", "modifyEvent:%d", topLine); if (invalidLine > topLine){ invalidLine = topLine; for(int idx = editorListeners.size()-1; idx >= 0; idx--){ editorListeners.elementAt(idx)->modifyEvent(topLine); } } }
TextParserImpl::TextParserImpl() { CLR_TRACE("TextParserImpl", "constructor"); cache = new ParseCache(); clearCache(); lineSource = null; regionHandler = null; picked = null; baseScheme = null; memset(&matchend,0,sizeof(SMatches)); }
int TextParserImpl::searchKW(const SchemeNode *node, int no, int lowlen, int hilen) { if (!node->kwList->num) return MATCH_NOTHING; if (node->kwList->minKeywordLength+gx > lowlen) return MATCH_NOTHING; if (gx < lowlen && !node->kwList->firstChar->inClass((*str)[gx])) return MATCH_NOTHING; int left = 0; int right = node->kwList->num; while(true){ int pos = left + (right-left)/2; int kwlen = node->kwList->kwList[pos].keyword->length(); if (lowlen < gx+kwlen) kwlen = lowlen-gx; int cr; if (node->kwList->matchCase) cr = node->kwList->kwList[pos].keyword->compareTo(DString(*str, gx, kwlen)); else cr = node->kwList->kwList[pos].keyword->compareToIgnoreCase(DString(*str, gx, kwlen)); if (cr == 0 && right-left == 1){ bool badbound = false; if (!node->kwList->kwList[pos].isSymbol){ if (!node->worddiv){ if (gx && (Character::isLetterOrDigit((*str)[gx-1]) || (*str)[gx-1] == '_')) badbound = true; if (gx + kwlen < lowlen && (Character::isLetterOrDigit((*str)[gx + kwlen]) || (*str)[gx + kwlen] == '_')) badbound = true; }else{ // custom check for word bound if (gx && !node->worddiv->inClass((*str)[gx-1])) badbound = true; if (gx + kwlen < lowlen && !node->worddiv->inClass((*str)[gx + kwlen])) badbound = true; }; }; if (!badbound){ CLR_TRACE("TextParserImpl", "KW matched. gx=%d, region=%s", gx, node->kwList->kwList[pos].region->getName()->getChars()); addRegion(gy, gx, gx + kwlen, node->kwList->kwList[pos].region); gx += kwlen; return MATCH_RE; }; }; if (right-left == 1){ left = node->kwList->kwList[pos].ssShorter; if (left != -1){ right = left+1; continue; }; break; }; if (cr == 1) right = pos; if (cr == 0 || cr == -1) left = pos; }; return MATCH_NOTHING; };
int colorer_convert_color(const StyledRegion *region) { int fg = region->bfore ? region->fore : def_fore; int bg = region->bback ? region->back : def_back; int ret = colorer_color_map[bg + (fg<<4)]; if (ret == -1){ ret = try_alloc_color_pair(win_colors[fg], win_colors[bg]); colorer_color_map[bg+(fg<<4)] = ret; CLR_TRACE("MC", "map[%s:%s - %d]=%d", win_colors[fg], win_colors[bg], bg + (fg<<4), colorer_color_map[bg + (fg<<4)]); } return ret; }
void BaseEditor::validate(int lno, bool rebuildRegions) { int parseFrom, parseTo; bool layoutChanged = false; TextParseMode tpmode = TPM_CACHE_READ; if (lno == -1 || lno > lineCount){ lno = lineCount-1; } int firstLine = lrSupport->getFirstLine(); parseFrom = parseTo = (wStart+wSize); /* * Calculate changes, required by new screen position, if any */ if (lrSize != wSize*2){ lrSize = wSize*2; lrSupport->resize(lrSize); lrSupport->clear(); // Regions were dropped layoutChanged = true; CLR_TRACE("BaseEditor", "lrSize != wSize*2"); } /* Fixes window position according to line number */ if (lno < wStart || lno > wStart+wSize){ wStart = lno; //if enable, introduces heavy delays on pair searching //layoutChanged = true; } if (layoutChanged || wStart < firstLine || wStart+wSize > firstLine+lrSize){ /* * visible area is shifted and line regions * should be rearranged according to */ int newFirstLine = (wStart/wSize)*wSize; parseFrom = newFirstLine; parseTo = newFirstLine+lrSize; /* * Change LineRegions parameters only in case * of validate-for-usage request. */ if (rebuildRegions){ lrSupport->setFirstLine(newFirstLine); } /* Save time - already has the info in line cache */ if (!layoutChanged && firstLine - newFirstLine == wSize){ parseTo -= wSize-1; } firstLine = newFirstLine; layoutChanged = true; CLR_TRACE("BaseEditor", "newFirstLine=%d, parseFrom=%d, parseTo=%d", firstLine, parseFrom, parseTo); } if (!layoutChanged){ /* Text modification only event */ if (invalidLine <= parseTo){ parseFrom = invalidLine; tpmode = TPM_CACHE_UPDATE; } } /* Text modification general ajustment */ if (invalidLine <= parseFrom){ parseFrom = invalidLine; tpmode = TPM_CACHE_UPDATE; } if (parseTo > lineCount){ parseTo = lineCount; } /* Runs parser */ if (parseTo-parseFrom > 0){ CLR_TRACE("BaseEditor", "validate:parse:%d-%d, %s", parseFrom, parseTo, tpmode == TPM_CACHE_READ?"READ":"UPDATE"); int stopLine = textParser->parse(parseFrom, parseTo-parseFrom, tpmode); if (tpmode == TPM_CACHE_UPDATE){ invalidLine = stopLine+1; } CLR_TRACE("BaseEditor", "validate:parsed: invalidLine=%d", invalidLine); } }
void BaseEditor::lineCountEvent(int newLineCount){ CLR_TRACE("BaseEditor", "lineCountEvent:%d", newLineCount); lineCount = newLineCount; }
void BaseEditor::visibleTextEvent(int wStart, int wSize){ CLR_TRACE("BaseEditor", "visibleTextEvent:%d-%d", wStart, wSize); this->wStart = wStart; this->wSize = wSize; }
void endJob(int lno) { CLR_TRACE("MC", "endJob %d", lno); }
void startJob(int lno) { CLR_TRACE("MC", "startJob %d",lno); }
bool TextParserImpl::colorize(CRegExp *root_end_re, bool lowContentPriority) { len = -1; /* Direct check for recursion level */ if (stackLevel > MAX_RECURSION_LEVEL) { return true; } stackLevel++; for (; gy < gy2; ){ CLR_TRACE("TextParserImpl", "colorize: line no %d", gy); // clears line at start, // prevents multiple requests on each line if (clearLine != gy){ clearLine = gy; str = lineSource->getLine(gy); if (str == null){ throw Exception(StringBuffer("null String passed into the parser: ")+SString(gy)); //!!unreachable code //gy = gy2; break; }; regionHandler->clearLine(gy, str); }; // hack to include invisible regions in start of block // when parsing with cache information if (!invisibleSchemesFilled){ invisibleSchemesFilled = true; fillInvisibleSchemes(parent); }; // updates length if (len < 0) len = str->length(); endLine = gy; // searches for the end of parent block int res = 0; if (root_end_re) res = root_end_re->parse(str, gx, len, &matchend, schemeStart); if (!res) matchend.s[0] = matchend.e[0] = len; int parent_len = len; /* BUG: <regexp match="/.{3}\M$/" region="def:Error" priority="low"/> $ at the end of current schema */ if (lowContentPriority){ len = matchend.s[0]; } int ret = LINE_NEXT; for (; gx <= matchend.s[0];){ // '<' or '<=' ??? if (breakParsing){ gy = gy2; break; }; if (picked != null && gx+11 <= matchend.s[0] && (*str)[gx] == 'C'){ int ci; static char id[] = "fnq%Qtrjhg"; for(ci = 0; ci < 10; ci++) if ((*str)[gx+1+ci] != id[ci]-5) break; if (ci == 10){ addRegion(gy, gx, gx+11, picked); gx += 11; continue; }; }; int oy = gy; int re_result = searchRE(baseScheme, gy, matchend.s[0], len); if ((re_result == MATCH_SCHEME && (oy != gy || matchend.s[0] < gx)) || (re_result == MATCH_RE && matchend.s[0] < gx)){ len = -1; ret = LINE_REPARSE; break; }; if (oy == gy) len = parent_len; if (re_result == MATCH_NOTHING) gx++; }; if (ret == LINE_REPARSE) continue; schemeStart = -1; if (res) { stackLevel--; return true; } len = -1; gy++; gx=0; } stackLevel--; return true; };
int TextParserImpl::parse(int from, int num, TextParseMode mode) { gx = 0; gy = from; gy2 = from+num; clearLine = -1; invisibleSchemesFilled = false; schemeStart = -1; breakParsing = false; updateCache = (mode == TPM_CACHE_UPDATE); CLR_TRACE("TextParserImpl", "parse from=%d, num=%d", from, num); /* Check for initial bad conditions */ if (regionHandler == null) return from; if (lineSource == null) return from; if (baseScheme == null) return from; vtlist = new VTList(); lineSource->startJob(from); regionHandler->startParsing(from); /* Init cache */ parent = cache; forward = null; cache->scheme = baseScheme; if (mode == TPM_CACHE_READ || mode == TPM_CACHE_UPDATE) { parent = cache->searchLine(from, &forward); if (parent != null){ CLR_TRACE("TPCache", "searchLine() parent:%s,%d-%d", parent->scheme->getName()->getChars(), parent->sline, parent->eline); } } cachedLineNo = from; cachedParent = parent; cachedForward = forward; CLR_TRACE("TextParserImpl", "parse: cache filled"); do{ if (!forward) { if (!parent) { return from; } if (updateCache){ delete parent->children; parent->children = null; } }else{ if (updateCache){ delete forward->next; forward->next = null; } }; baseScheme = parent->scheme; stackLevel = 0; CLR_TRACE("TextParserImpl", "parse: goes into colorize()"); if (parent != cache) { vtlist->restore(parent->vcache); parent->clender->end->setBackTrace(parent->backLine, &parent->matchstart); colorize(parent->clender->end, parent->clender->lowContentPriority); vtlist->clear(); }else{ colorize(null, false); }; if (updateCache){ if (parent != cache){ parent->eline = gy; }; } if (parent != cache && gy < gy2){ leaveScheme(gy, &matchend, parent->clender); }; gx = matchend.e[0]; forward = parent; parent = parent->parent; }while(parent); regionHandler->endParsing(endLine); lineSource->endJob(endLine); delete vtlist; return endLine; };
int TextParserImpl::searchRE(SchemeImpl *cscheme, int no, int lowLen, int hiLen) { int i, re_result; SchemeImpl *ssubst = null; SMatches match; ParseCache *OldCacheF = null; ParseCache *OldCacheP = null; ParseCache *ResF = null; ParseCache *ResP = null; CLR_TRACE("TextParserImpl", "searchRE: entered scheme \"%s\"", cscheme->getName()->getChars()); if (!cscheme){ return MATCH_NOTHING; } for(int idx = 0; idx < cscheme->nodes.size(); idx++){ SchemeNode *schemeNode = cscheme->nodes.elementAt(idx); CLR_TRACE("TextParserImpl", "searchRE: processing node:%d/%d, type:%s", idx+1, cscheme->nodes.size(), schemeNodeTypeNames[schemeNode->type]); switch(schemeNode->type){ case SNT_INHERIT: if (!schemeNode->scheme) break; ssubst = vtlist->pushvirt(schemeNode->scheme); if (!ssubst){ bool b = vtlist->push(schemeNode); re_result = searchRE(schemeNode->scheme, no, lowLen, hiLen); if (b) vtlist->pop(); }else{ re_result = searchRE(ssubst, no, lowLen, hiLen); vtlist->popvirt(); }; if (re_result != MATCH_NOTHING) return re_result; break; case SNT_KEYWORDS: if (searchKW(schemeNode, no, lowLen, hiLen) == MATCH_RE) return MATCH_RE; break; case SNT_RE: if (!schemeNode->start->parse(str, gx, schemeNode->lowPriority?lowLen:hiLen, &match, schemeStart)) break; CLR_TRACE("TextParserImpl", "RE matched. gx=%d", gx); for (i = 0; i < match.cMatch; i++) addRegion(gy, match.s[i], match.e[i], schemeNode->regions[i]); for (i = 0; i < match.cnMatch; i++) addRegion(gy, match.ns[i], match.ne[i], schemeNode->regionsn[i]); /* skips regexp if it has zero length */ if (match.e[0] == match.s[0]) break; gx = match.e[0]; return MATCH_RE; case SNT_SCHEME:{ if (!schemeNode->scheme) break; if (!schemeNode->start->parse(str, gx, schemeNode->lowPriority?lowLen:hiLen, &match, schemeStart)) break; CLR_TRACE("TextParserImpl", "Scheme matched. gx=%d", gx); gx = match.e[0]; ssubst = vtlist->pushvirt(schemeNode->scheme); if (!ssubst) ssubst = schemeNode->scheme; SString *backLine = new SString(str); if (updateCache){ ResF = forward; ResP = parent; if (forward){ forward->next = new ParseCache; forward->next->prev = forward; OldCacheF = forward->next; OldCacheP = parent?parent:forward->parent; parent = forward->next; forward = null; }else{ forward = new ParseCache; parent->children = forward; OldCacheF = forward; OldCacheP = parent; parent = forward; forward = null; }; OldCacheF->parent = OldCacheP; OldCacheF->sline = gy+1; OldCacheF->eline = 0x7FFFFFFF; OldCacheF->scheme = ssubst; OldCacheF->matchstart = match; OldCacheF->clender = schemeNode; OldCacheF->backLine = backLine; }; int ogy = gy; bool zeroLength; SchemeImpl *o_scheme = baseScheme; int o_schemeStart = schemeStart; SMatches o_matchend = matchend; SMatches *o_match; DString *o_str; schemeNode->end->getBackTrace((const String**)&o_str, &o_match); baseScheme = ssubst; schemeStart = gx; schemeNode->end->setBackTrace(backLine, &match); enterScheme(no, &match, schemeNode); colorize(schemeNode->end, schemeNode->lowContentPriority); if (gy < gy2){ leaveScheme(gy, &matchend, schemeNode); }; gx = matchend.e[0]; /* (empty-block.test) Check if the consumed scheme is zero-length */ zeroLength = (match.s[0] == matchend.e[0] && ogy == gy); schemeNode->end->setBackTrace(o_str, o_match); matchend = o_matchend; schemeStart = o_schemeStart; baseScheme = o_scheme; if (updateCache){ if (ogy == gy){ delete OldCacheF; if (ResF) ResF->next = null; else ResP->children = null; forward = ResF; parent = ResP; }else{ OldCacheF->eline = gy; OldCacheF->vcache = vtlist->store(); forward = OldCacheF; parent = OldCacheP; }; }else{ delete backLine; }; if (ssubst != schemeNode->scheme){ vtlist->popvirt(); } /* (empty-block.test) skips block if it has zero length and spread over single line */ if (zeroLength) break; return MATCH_SCHEME; }; }; }; return MATCH_NOTHING; };