/// <summary> /// Parse and highlight keywords. /// </summary> /// <param name="doc">Document to highlight.</param> /// <param name="dirtyBegin">Index to start highlighting. On return, start index of the range to be invalidated.</param> /// <param name="dirtyEnd">Index to end highlighting. On return, end index of the range to be invalidated.</param> public void Highlight(Document doc, ref int dirtyBegin, ref int dirtyEnd) { if (dirtyBegin < 0 || doc.Length < dirtyBegin) { throw new ArgumentOutOfRangeException("dirtyBegin"); } if (dirtyEnd < 0 || doc.Length < dirtyEnd) { throw new ArgumentOutOfRangeException("dirtyEnd"); } char nextCh; int index, nextIndex; // Determine range to highlight dirtyBegin = Utl.FindReparsePoint(_ReparsePoints, dirtyBegin); dirtyEnd = Utl.FindReparseEndPoint(doc, dirtyEnd); // seek each tags index = 0; while (0 <= index && index < dirtyEnd) { if (Utl.TryHighlight(doc, _Enclosures, index, dirtyEnd, null, out nextIndex)) { Utl.EntryReparsePoint(_ReparsePoints, index); index = nextIndex; } else if (doc[index] == '<') { Utl.EntryReparsePoint(_ReparsePoints, index); // set class for '<' doc.SetCharClass(index, CharClass.Delimiter); index++; if (dirtyEnd <= index) { return; } // if next char is '?' or '/', highlight it too nextCh = doc[index]; if (nextCh == '?' || nextCh == '/' || nextCh == '!') { doc.SetCharClass(index, CharClass.Delimiter); index++; if (dirtyEnd <= index) { return; } } // skip whitespaces while (Char.IsWhiteSpace(doc[index])) { doc.SetCharClass(index, CharClass.Normal); index++; if (dirtyEnd <= index) { return; } } // highlight element name nextIndex = Utl.FindNextToken(doc, index, DefaultWordCharSet); for (int i = index; i < nextIndex; i++) { doc.SetCharClass(i, CharClass.ElementName); } index = nextIndex; // highlight attributes while (index < dirtyEnd && doc[index] != '>') { // highlight enclosing part if this token begins a part if (Utl.TryHighlight(doc, _Enclosures, index, dirtyEnd, null, out nextIndex)) { // successfully highlighted. skip to next. index = nextIndex; continue; } // this token is normal class; reset classes and seek to next token nextIndex = Utl.FindNextToken(doc, index, DefaultWordCharSet); for (int i = index; i < nextIndex; i++) { doc.SetCharClass(i, CharClass.Attribute); } index = nextIndex; } // highlight '>' if (index < dirtyEnd) { doc.SetCharClass(index, CharClass.Delimiter); if (1 <= index && doc[index - 1] == '/') { doc.SetCharClass(index - 1, CharClass.Delimiter); } index++; } } else if (doc[index] == '&') { int seekEndIndex; bool wasEntity; CharClass klass; // find end position of this token FindEntityEnd(doc, index, out seekEndIndex, out wasEntity); DebugUtl.Assert(0 <= seekEndIndex && seekEndIndex <= doc.Length); // highlight this token klass = wasEntity ? CharClass.Entity : CharClass.Normal; for (int i = index; i < seekEndIndex; i++) { doc.SetCharClass(i, klass); } index = seekEndIndex; } else { // normal character. doc.SetCharClass(index, CharClass.Normal); index++; } } }