/// <summary> /// Get the object, which was inserted under the keyword (line, at offset, with length length), /// returns null, if no such keyword was inserted. /// </summary> public object this[IDocument document, LineSegment line, int offset, int length] { get { if(length == 0) { return null; } Node next = root; int wordOffset = line.Offset + offset; if (casesensitive) { for (int i = 0; i < length; ++i) { int index = ((int)document.GetCharAt(wordOffset + i)) % 256; next = next.leaf[index]; if (next == null) { return null; } if (next.color != null && TextUtility.RegionMatches(document, wordOffset, length, next.word)) { return next.color; } } } else { for (int i = 0; i < length; ++i) { int index = ((int)Char.ToUpper(document.GetCharAt(wordOffset + i))) % 256; next = next.leaf[index]; if (next == null) { return null; } if (next.color != null && TextUtility.RegionMatches(document, casesensitive, wordOffset, length, next.word)) { return next.color; } } } return null; } }
int CreateLines(string text, int insertPosition, int offset) { int count = 0; int start = 0; ISegment nextDelimiter = NextDelimiter(text, 0); while (nextDelimiter != null && nextDelimiter.Offset >= 0) { int index = nextDelimiter.Offset + (nextDelimiter.Length - 1); LineSegment newLine = new LineSegment(offset + start, offset + index, nextDelimiter.Length); markLines.Add(newLine); if (insertPosition + count >= lineCollection.Count) { lineCollection.Add(newLine); } else { lineCollection.Insert(insertPosition + count, newLine); } ++count; start = index + 1; nextDelimiter = NextDelimiter(text, start); } if (start < text.Length) { if (insertPosition + count < lineCollection.Count) { LineSegment l = (LineSegment)lineCollection[insertPosition + count]; int delta = text.Length - start; l.Offset -= delta; l.TotalLength += delta; } else { LineSegment newLine = new LineSegment(offset + start, text.Length - start); markLines.Add(newLine); lineCollection.Add(newLine); ++count; } } OnLineCountChanged(new LineManagerEventArgs(document, insertPosition, count)); return count; }
int Insert(int lineNumber, int offset, string text) { if (text == null || text.Length == 0) { return 0; } textLength += text.Length; if (lineCollection.Count == 0 || lineNumber >= lineCollection.Count) { return CreateLines(text, lineCollection.Count, offset); } LineSegment line = (LineSegment)lineCollection[lineNumber]; ISegment nextDelimiter = NextDelimiter(text, 0); if (nextDelimiter == null || nextDelimiter.Offset < 0) { line.TotalLength += text.Length; // Console.WriteLine("1:Line length of line {0} set to {1}", lineNumber, line.TotalLength - line.DelimiterLength); markLines.Add(line); OnLineLengthChanged(new LineLengthEventArgs(document, lineNumber, offset -line.Offset, text.Length)); return 0; } int restLength = line.Offset + line.TotalLength - offset; if (restLength > 0) { // Console.WriteLine("Insert: Set restline in line {0} to length {1}", lineNumber, restLength); LineSegment lineRest = new LineSegment(offset, restLength); lineRest.DelimiterLength = line.DelimiterLength; lineRest.Offset += text.Length; markLines.Add(lineRest); if (restLength - line.DelimiterLength < 0) { throw new ApplicationException("tried to insert inside delimiter string " + lineRest.ToString() + "!!!"); } lineCollection.Insert(lineNumber + 1, lineRest); OnLineCountChanged(new LineManagerEventArgs(document, lineNumber - 1, 1)); } line.DelimiterLength = nextDelimiter.Length; int nextStart = offset + nextDelimiter.Offset + nextDelimiter.Length; line.TotalLength = nextStart - line.Offset; // Console.WriteLine("2:Line length of line {0} set to {1}", lineNumber, line.TotalLength - line.DelimiterLength); markLines.Add(line); text = text.Substring(nextDelimiter.Offset + nextDelimiter.Length); return CreateLines(text, lineNumber + 1, nextStart) + 1; }
/// <remarks> /// Returns true, if the line lineNumber is empty or filled with whitespaces. /// </remarks> public static bool IsEmptyLine(IDocument document, LineSegment line) { for (int i = line.Offset; i < line.Offset + line.Length; ++i) { char ch = document.GetCharAt(i); if (!Char.IsWhiteSpace(ch)) { return false; } } return true; }
void DrawLine(Graphics g, LineSegment line, float yPos, RectangleF margin) { float xPos = 0; float fontHeight = Font.GetHeight(g); // bool gotNonWhitespace = false; curTabIndent = 0 ; foreach (TextWord word in line.Words) { switch (word.Type) { case TextWordType.Space: Advance(ref xPos, ref yPos, margin.Width, textAreaControl.TextArea.TextViewMargin.GetWidth(' '), fontHeight); // if (!gotNonWhitespace) { // curTabIndent = xPos; // } break; case TextWordType.Tab: Advance(ref xPos, ref yPos, margin.Width, TabIndent * textAreaControl.TextArea.TextViewMargin.GetWidth(' '), fontHeight); // if (!gotNonWhitespace) { // curTabIndent = xPos; // } break; case TextWordType.Word: // if (!gotNonWhitespace) { // gotNonWhitespace = true; // curTabIndent += TabIndent * textAreaControl.TextArea.TextView.GetWidth(' '); // } g.DrawString(word.Word, word.Font, BrushRegistry.GetBrush(word.Color), xPos + margin.X, yPos); SizeF drawingSize = g.MeasureString(word.Word, word.Font, new SizeF(margin.Width, fontHeight * 100), printingStringFormat); Advance(ref xPos, ref yPos, margin.Width, drawingSize.Width, fontHeight); break; } } }
// Mark document文档中的一行. bool MarkTokensInLine(IDocument document, int lineNumber, ref bool spanChanged) { bool processNextLine = false; LineSegment previousLine = (lineNumber > 0 ? document.GetLineSegment(lineNumber - 1) : null); currentSpanStack = ((previousLine != null && previousLine.HighlightSpanStack != null) ? ((Stack)(previousLine.HighlightSpanStack.Clone())) : null); if (currentSpanStack != null) { while (currentSpanStack.Count > 0 && ((Span)currentSpanStack.Peek()).StopEOL) { currentSpanStack.Pop(); } if (currentSpanStack.Count == 0) { currentSpanStack = null; } } currentLine = (LineSegment)document.LineSegmentCollection[lineNumber]; if (currentLine.Length == -1) { // happens when buffer is empty ! return false; } ArrayList words = ParseLine(document); if (currentSpanStack != null && currentSpanStack.Count == 0) { currentSpanStack = null; } // Check if the span state has changed, if so we must re-render the next line // This check may seem utterly complicated but I didn't want to introduce any function calls // or alllocations here for perf reasons. if(currentLine.HighlightSpanStack != currentSpanStack) { if (currentLine.HighlightSpanStack == null) { processNextLine = false; foreach (Span sp in currentSpanStack) { if (!sp.StopEOL) { spanChanged = true; processNextLine = true; break; } } } else if (currentSpanStack == null) { processNextLine = false; foreach (Span sp in currentLine.HighlightSpanStack) { if (!sp.StopEOL) { spanChanged = true; processNextLine = true; break; } } } else { IEnumerator e1 = currentSpanStack.GetEnumerator(); IEnumerator e2 = currentLine.HighlightSpanStack.GetEnumerator(); bool done = false; while (!done) { bool blockSpanIn1 = false; while (e1.MoveNext()) { if (!((Span)e1.Current).StopEOL) { blockSpanIn1 = true; break; } } bool blockSpanIn2 = false; while (e2.MoveNext()) { if (!((Span)e2.Current).StopEOL) { blockSpanIn2 = true; break; } } if (blockSpanIn1 || blockSpanIn2) { if (blockSpanIn1 && blockSpanIn2) { if (e1.Current != e2.Current) { done = true; processNextLine = true; spanChanged = true; } } else { spanChanged = true; done = true; processNextLine = true; } } else { done = true; processNextLine = false; } } } } else { processNextLine = false; } //// Alex: remove old words if (currentLine.Words!=null) currentLine.Words.Clear(); currentLine.Words = words; currentLine.HighlightSpanStack = (currentSpanStack != null && currentSpanStack.Count > 0) ? currentSpanStack : null; return processNextLine; }
float MeasurePrintingHeight(Graphics g, LineSegment line, float maxWidth) { float xPos = 0; float yPos = 0; float fontHeight = Font.GetHeight(g); // bool gotNonWhitespace = false; curTabIndent = 0; foreach (TextWord word in line.Words) { switch (word.Type) { case TextWordType.Space: Advance(ref xPos, ref yPos, maxWidth, textAreaControl.TextArea.TextViewMargin.GetWidth(' '), fontHeight); // if (!gotNonWhitespace) { // curTabIndent = xPos; // } break; case TextWordType.Tab: Advance(ref xPos, ref yPos, maxWidth, TabIndent * textAreaControl.TextArea.TextViewMargin.GetWidth(' '), fontHeight); // if (!gotNonWhitespace) { // curTabIndent = xPos; // } break; case TextWordType.Word: // if (!gotNonWhitespace) { // gotNonWhitespace = true; // curTabIndent += TabIndent * textAreaControl.TextArea.TextView.GetWidth(' '); // } SizeF drawingSize = g.MeasureString(word.Word, word.Font, new SizeF(maxWidth, fontHeight * 100), printingStringFormat); Advance(ref xPos, ref yPos, maxWidth, drawingSize.Width, fontHeight); break; } } return yPos + fontHeight; }
// Mark整个文档. public void MarkTokens(IDocument document) { if (RuleSets.Count == 0) {//如果没有Rule Set则退出,即不给当前文档mark token return; } int lineNumber = 0;//从第一行开始mark token while (lineNumber < document.TotalNumberOfLines) {//一直循环到最后一行完成后结束,注:最后一行可能只有一个行结束符. LineSegment previousLine = (lineNumber > 0 ? document.GetLineSegment(lineNumber - 1) : null); if (lineNumber >= document.LineSegmentCollection.Count) { // may be, if the last line ends with a delimiter break; // then the last line is not in the LineSegmentCollection :) } //当前行中的SpanStack总是获取前面一行中的SpanStack currentSpanStack = ((previousLine != null && previousLine.HighlightSpanStack != null) ? ((Stack)(previousLine.HighlightSpanStack.Clone())) : null); if (currentSpanStack != null) { while (currentSpanStack.Count > 0 && ((Span)currentSpanStack.Peek()).StopEOL) { currentSpanStack.Pop(); } if (currentSpanStack.Count == 0) currentSpanStack = null; } currentLine = (LineSegment)document.LineSegmentCollection[lineNumber]; if (currentLine.Length == -1) { // happens when buffer is empty ! return; } ArrayList words = ParseLine(document); if (currentLine.Words!=null) currentLine.Words.Clear(); currentLine.Words = words; currentLine.HighlightSpanStack = (currentSpanStack==null || currentSpanStack.Count==0) ? null : currentSpanStack; ++lineNumber; } document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.WholeTextArea)); document.OnUpdateCommited(); }
HighlightColor GetColor(HighlightRuleSet ruleSet, IDocument document, LineSegment currentSegment, int currentOffset, int currentLength) { if (ruleSet != null) { if (ruleSet.Reference != null) { return ruleSet.Highlighter.GetColor(document, currentSegment, currentOffset, currentLength); } else { return (HighlightColor)ruleSet.KeyWords[document, currentSegment, currentOffset, currentLength]; } } return null; }
public HighlightColor GetColor(IDocument document, LineSegment currentSegment, int currentOffset, int currentLength) { //如果不指定RuleSet,则用defaultRuleSet来作为规则集. return GetColor(defaultRuleSet, document, currentSegment, currentOffset, currentLength); }
public int GetVisualColumn(LineSegment line, int logicalColumn) { int tabIndent = Document.TextEditorProperties.TabIndent; int column = 0; for (int i = 0; i < logicalColumn; ++i) { char ch; if (i >= line.Length) { ch = ' '; } else { ch = Document.GetCharAt(line.Offset + i); } switch (ch) { case '\t': int oldColumn = column; column += tabIndent; column = (column / tabIndent) * tabIndent; break; default: ++column; break; } } return column; }
public TextWord(IDocument document, LineSegment line, int offset, int length, HighlightColor highlightColor, bool hasDefaultColor) { Debug.Assert(document != null); Debug.Assert(line != null); Debug.Assert(highlightColor != null); this.document = document; this.line = line; this.offset = offset; this.length = length; this.highlightColor = highlightColor; this.hasDefaultColor = hasDefaultColor; }