/** * Searches all entries in the given treemap and highlights them with the given attributes. * * @param treeMap the treeMap with the words to highlight * @param pText the text of the paragraph * @param attributes the attributes to apply * @param deniedAreas the list with the denied areas * @param caseSensitive match case-sensitive? * @param reqWord are words required? (word-boundary on each side) */ private void replaceWords( StringTreeMap treeMap, String pText, TextAttributes attributes, List deniedAreas, boolean caseSensitive, boolean reqWord) { // nothing to do? if (treeMap.size() == 0) return; // TODO we can optimize that by using a Heap in the StringTreeMap for the // successors instead of Maps, right? Point varea = _visibleArea.getArea(_para); StringBuffer buf = new StringBuffer(); int p = -1; TreeNode n = treeMap.getRoot(); // loop through the visible area for (int i = varea.x, len = varea.y; i < len; i++) { p++; char c = pText.charAt(i); char last = reqWord && p > 0 ? pText.charAt(i - 1) : 0; // we append it to the buffer if it is empty or we have a word-boundary if (!reqWord || buf.length() > 0 || last == 0 || isWordBoundary(last)) { buf.append(c); // if the path does not exist we may have found a match (without // the current char) n = n.getSuccessor(c); if (n == null) { if (buf.length() > 1 && (!reqWord || isWordBoundary(c))) { // check if the entry exists in the map String func = buf.substring(0, buf.length() - 1); if (treeMap.contains(func)) { // apply the attribute, if the area is not denied int start = i - buf.length() + 1; int end = start + func.length(); if (!isInDeniedArea(deniedAreas, start, end)) { highlightText(start, end, attributes, pText); deniedAreas.add(new Point(start, end)); } } } // clear the buffer for new matches buf = new StringBuffer(); if (!reqWord || isWordBoundary(last)) { n = treeMap.getRoot().getSuccessor(c); if (n == null) n = treeMap.getRoot(); else buf.append(c); } else n = treeMap.getRoot(); } } } // replace match at the end? if (buf.length() > 0) { // check if the entry exists in the map if (treeMap.contains(buf.toString())) { // apply the attribute, if the area is not denied int start = varea.y - buf.length(); int end = start + buf.length(); if (!isInDeniedArea(deniedAreas, start, end)) { highlightText(start, end, attributes, pText); deniedAreas.add(new Point(start, end)); } } } }
/** Performs the default-highlighting. */ private void highlightDefault() { // is there nothing to do? if (_visibleArea.isInvisible() || _para.getElementLength() == 0) return; Highlighter hl = getHighlighter(); String pText = _para.getText(); List deniedAreas = new ArrayList(); TextAttributes attributes; // grab some vars from the highlighter Map mlTypes = hl.getMultiCommentLimiters(); Map slTypes = hl.getSingleComments(); Map strQuotes = hl.getStringQuotes(); char escChar = hl.getEscapeChar(); Point area = _visibleArea.getArea(_para); // at first we clear the not-denied intervals attributes = new TextAttributes(); highlightText(area.x, area.y, attributes, pText); // init some flags and vars int cStart = -1; int sStart = -1; char sStartChar = 0; Object stringId = null; Object commentId = null; boolean inStr = false; boolean inComment = false; boolean foundSLC = false; // search for multiline comments and strings for (int i = area.x, len = area.y; i < len; i++) { char c = pText.charAt(i); // search for strings Object strId = null; if (!inComment && (strId = getStringId(strQuotes, c)) != null && !StringUtils.isEscaped(pText, i, escChar)) { // is it a closing char? if (c == sStartChar && inStr) { inStr = false; TextAttributes strAttrs = hl.getStringAttributes(strId); highlightText(sStart, i + 1, strAttrs, pText); deniedAreas.add(new Point(sStart, i + 1)); } // just add the start if it is a real start (not in other elements) else if (!inStr) { sStart = i; sStartChar = c; stringId = strId; inStr = true; } continue; } // don't search comments in strings if (!inStr) { if (!inComment) { // search for single-line-comments Object slStartId = getSLCommentStart(slTypes, pText, i); if (slStartId != null) { // if there is one, highlight it and break here TextAttributes slAttrs = hl.getSLCommentAttributes(slStartId); highlightText(i, _para.getElementLength(), slAttrs, pText); foundSLC = true; deniedAreas.add(new Point(i, _para.getElementLength())); break; } // search for comment-start-tags Object startTagId = getCommentStart(mlTypes, pText, i); if (startTagId != null) { cStart = i; inComment = true; commentId = startTagId; continue; } } // search for comment-end-tags Object endTagId = getCommentEnd(mlTypes, pText, i); if (endTagId != null) { // is the comment-start also in this paragraph? if (inComment) { if (mlTypes.get(commentId).equals(mlTypes.get(endTagId))) { inComment = false; TextAttributes mlAttrs = hl.getMLCommentAttributes(endTagId); highlightText(cStart, i + 2, mlAttrs, pText); deniedAreas.add(new Point(cStart, i + 2)); } } } } } // is a comment not closed? if (inComment && (!inStr || sStart > cStart)) { _visibleArea.setEnd(cStart); TextAttributes mlAttrs = hl.getMLCommentAttributes(commentId); highlightText(cStart, _para.getElementLength(), mlAttrs, pText); } // is a string not closed? else if (inStr) { _visibleArea.setEnd(sStart); TextAttributes strAttrs = hl.getStringAttributes(stringId); highlightText(sStart, _para.getElementLength(), strAttrs, pText); } String pLower = pText.toLowerCase(); // replace keywords Map keywords = hl.getKeywords(); Iterator it = keywords.entrySet().iterator(); while (it.hasNext()) { Entry e = (Entry) it.next(); StringTreeMap treeMap = (StringTreeMap) e.getValue(); KeywordSettings settings = hl.getKeywordSettings(e.getKey()); replaceWords( treeMap, settings.isCaseSensitive() ? pText : pLower, hl.getKeywordAttributes(e.getKey()), deniedAreas, settings.isCaseSensitive(), settings.requireWord()); } // numbers if (hl.highlightNumbers()) { attributes = hl.getAttributes(Highlighter.NUMBER); Pattern p = _numberPattern; if (p == null) { p = Pattern.compile("\\b-?(\\d+|\\d*\\.\\d+)\\b"); _numberPattern = p; } Matcher m = p.matcher(pText); while (m.find()) { String match = m.group(); int start = m.start(); int end = start + match.length(); // highlight, if the area is not denied if (!isInDeniedArea(deniedAreas, start, end)) { highlightText(start, end, attributes, pText); deniedAreas.add(new Point(start, end)); } } } // symbols replaceWords( hl.getSymbols(), pLower, hl.getAttributes(Highlighter.SYMBOL), deniedAreas, true, false); // other regeexps if (hl.getRegexps().size() > 0) { Map regexps = hl.getRegexps(); it = regexps.entrySet().iterator(); while (it.hasNext()) { Entry e = (Entry) it.next(); attributes = hl.getRegexpAttributes(e.getKey()); RegExDesc regex = (RegExDesc) e.getValue(); // find matches Matcher m = regex.getPattern().matcher(pText); while (m.find()) { String match = m.group(regex.getGroup()); int start = m.start(regex.getGroup()); int end = start + match.length(); // highlight, if the area is not denied if (!isInDeniedArea(deniedAreas, start, end)) { highlightText(start, end, attributes, pText); } } } } removeStrings(); removeStringStarts(); removeComments(); removeCommentStarts(); // mark the paragraph-content as dirty, because applyAttributes() does not // mark the sections as dirty! _para.getTextField().getViewManager().markParagraphDirty(_para); // comment-start? if (inComment && (!inStr || sStart > cStart)) { if (_visibleArea.isVisible(cStart)) _hlTypes.add(new HighlightType(HighlightType.CONTAINS_OTHER)); _hlTypes.add(new HighlightType(HighlightType.CONTAINS_COMMENT_START, commentId)); return; } // open string? if (inStr && !foundSLC) { if (_visibleArea.isVisible(sStart)) _hlTypes.add(new HighlightType(HighlightType.CONTAINS_OTHER)); _hlTypes.add( new HighlightType( HighlightType.CONTAINS_STRING_START, getStringId(strQuotes, sStartChar))); return; } // default removeOther(); _hlTypes.add(new HighlightType(HighlightType.CONTAINS_OTHER)); _visibleArea.setEnd(); }