protected override LayoutWrapper RenderLine (long line) { var layout = new TextLayout (Editor); layout.Font = Editor.Options.Font; StringBuilder sb = new StringBuilder (); long startOffset = line * Editor.BytesInRow; long endOffset = System.Math.Min (startOffset + Editor.BytesInRow, Data.Length); byte[] lineBytes = Data.GetBytes (startOffset, (int)(endOffset - startOffset)); for (int i = 0; i < lineBytes.Length; i++) { byte b = lineBytes[i]; char ch = (char)b; if (b < 128 && (Char.IsLetterOrDigit (ch) || Char.IsPunctuation (ch))) { sb.Append (ch); } else { sb.Append ("."); } } layout.Text = sb.ToString (); Margin.LayoutWrapper result = new LayoutWrapper (layout); if (Data.IsSomethingSelected) { ISegment selection = Data.MainSelection.Segment; HandleSelection (selection.Offset, selection.EndOffset, startOffset, endOffset, null, delegate(long start, long end) { result.Layout.SetForeground (Style.Selection, (int)(start - startOffset), (int)(end - start)); result.Layout.SetBackground (Style.SelectionBg, (int)(start - startOffset), (int)(end - start)); }); } return result; }
internal protected override void Draw(Context ctx, Rectangle area, long line, double x, double y) { ctx.Rectangle(x, y, Width, Editor.LineHeight); ctx.SetColor(Style.HexDigitBg); ctx.Fill(); LayoutWrapper layout = GetLayout(line); if (!Data.IsSomethingSelected && !Caret.InTextEditor && line == Data.Caret.Line) { var column = (int)(Caret.Offset % BytesInRow); if (Editor.Options.StringRepresentationType == StringRepresentationTypes.UTF16) { column /= 2; } var xOffset = charWidth * column; ctx.Rectangle(x + xOffset, y, charWidth, Editor.LineHeight); ctx.SetColor(Style.HighlightOffset); ctx.Fill(); } ctx.SetColor(Style.HexDigit); ctx.DrawTextLayout(layout.Layout, x, y); if (layout.IsUncached) { layout.Dispose(); } }
protected override LayoutWrapper RenderLine(long line) { var layout = new TextLayout(Editor); layout.Font = Editor.Options.Font; // layout.Tabs = tabArray; StringBuilder sb = new StringBuilder(); long startOffset = line * Editor.BytesInRow; long endOffset = System.Math.Min(startOffset + Editor.BytesInRow, Data.Length); byte[] lineBytes = Data.GetBytes(startOffset, (int)(endOffset - startOffset)); for (int i = 0; i < lineBytes.Length; i++) { sb.Append(string.Format("{0:X2}", lineBytes[i])); if ((i + 1) % Editor.Options.GroupBytes == 0) { sb.Append(" "); // \t } } layout.Text = sb.ToString(); Margin.LayoutWrapper result = new LayoutWrapper(layout); if (Data.IsSomethingSelected) { ISegment selection = Data.MainSelection.Segment; HandleSelection(selection.Offset, selection.EndOffset, startOffset, endOffset, null, delegate(long start, long end) { result.Layout.SetForeground(Style.Selection, (int)(start - startOffset) * 3, (int)(end - start) * 3 - 1); result.Layout.SetBackground(Style.SelectionBg, (int)(start - startOffset) * 3, (int)(end - start) * 3 - 1); }); } return(result); }
protected override LayoutWrapper RenderLine(long line) { var layout = new TextLayout(Editor); layout.Font = Editor.Options.Font; StringBuilder sb = new StringBuilder(); long startOffset = line * Editor.BytesInRow; long endOffset = System.Math.Min(startOffset + Editor.BytesInRow, Data.Length); byte[] lineBytes = Data.GetBytes(startOffset, (int)(endOffset - startOffset)); switch (Editor.Options.StringRepresentationType) { case StringRepresentationTypes.ASCII: for (int i = 0; i < lineBytes.Length; i++) { byte b = lineBytes [i]; char ch = (char)b; if (!char.IsControl(ch)) { sb.Append(ch); } else { sb.Append("."); } } break; case StringRepresentationTypes.UTF16: for (int i = 0; i < lineBytes.Length - 1; i += 2) { char ch = Encoding.Unicode.GetChars(lineBytes, i, 2) [0]; if (char.IsLetterOrDigit(ch) || char.IsWhiteSpace(ch) || char.IsSymbol(ch) || char.IsPunctuation(ch)) { sb.Append(ch); } else { sb.Append("."); } } break; default: throw new NotImplementedException(Editor.Options.StringRepresentationType.ToString()); } layout.Text = sb.ToString(); Margin.LayoutWrapper result = new LayoutWrapper(layout); if (Data.IsSomethingSelected) { ISegment selection = Data.MainSelection.Segment; HandleSelection(selection.Offset, selection.EndOffset, startOffset, endOffset, null, delegate(long start, long end) { result.Layout.SetForeground(Style.Selection, (int)(start - startOffset) / 2, (int)(end - start) / 2); result.Layout.SetBackground(Style.SelectionBg, (int)(start - startOffset) / 2, (int)(end - start) / 2); }); } return(result); }
protected override LayoutWrapper RenderLine(long line) { Pango.Layout layout = new Pango.Layout(Editor.PangoContext); layout.FontDescription = Editor.Options.Font; StringBuilder sb = new StringBuilder(); long startOffset = line * Editor.BytesInRow; long endOffset = System.Math.Min(startOffset + Editor.BytesInRow, Data.Length); byte[] lineBytes = Data.GetBytes(startOffset, (int)(endOffset - startOffset)); for (int i = 0; i < lineBytes.Length; i++) { byte b = lineBytes[i]; char ch = (char)b; if (b < 128 && (Char.IsLetterOrDigit(ch) || Char.IsPunctuation(ch))) { sb.Append(ch); } else { sb.Append("."); } } layout.SetText(sb.ToString()); char[] lineChars = layout.Text.ToCharArray(); Margin.LayoutWrapper result = new LayoutWrapper(layout); uint curIndex = 0, byteIndex = 0; if (Data.IsSomethingSelected) { ISegment selection = Data.MainSelection.Segment; HandleSelection(selection.Offset, selection.EndOffset, startOffset, endOffset, null, delegate(long start, long end) { Pango.AttrForeground selectedForeground = new Pango.AttrForeground(Style.Selection.Red, Style.Selection.Green, Style.Selection.Blue); selectedForeground.StartIndex = TranslateToUTF8Index(lineChars, (uint)(start - startOffset), ref curIndex, ref byteIndex); selectedForeground.EndIndex = TranslateToUTF8Index(lineChars, (uint)(end - startOffset), ref curIndex, ref byteIndex); result.Add(selectedForeground); Pango.AttrBackground attrBackground = new Pango.AttrBackground(Style.SelectionBg.Red, Style.SelectionBg.Green, Style.SelectionBg.Blue); attrBackground.StartIndex = selectedForeground.StartIndex; attrBackground.EndIndex = selectedForeground.EndIndex; result.Add(attrBackground); }); } result.SetAttributes(); return(result); }
internal protected override void Draw(Gdk.Drawable drawable, Gdk.Rectangle area, long line, int x, int y) { drawable.DrawRectangle(GetGC(Style.HexOffsetBg), true, x, y, Width, Editor.LineHeight); LayoutWrapper layout = GetLayout(line); int w, h; layout.Layout.GetPixelSize(out w, out h); drawable.DrawLayout(GetGC(line != Caret.Line ? Style.HexOffset : Style.HexOffsetHighlighted), x + Width - w - 4, y, layout.Layout); if (layout.IsUncached) { layout.Dispose(); } }
internal protected override void Draw(Gdk.Drawable drawable, Gdk.Rectangle area, long line, int x, int y) { drawable.DrawRectangle(bgGC, true, x, y, Width, Editor.LineHeight); LayoutWrapper layout = GetLayout(line); if (!Data.IsSomethingSelected && Caret.InTextEditor && line == Data.Caret.Line) { drawable.DrawRectangle(GetGC(Style.HighlightOffset), true, CalculateCaretXPos(false), y, byteWidth, Editor.LineHeight); } drawable.DrawLayout(fgGC, x, y, layout.Layout); if (layout.IsUncached) { layout.Dispose(); } }
protected override LayoutWrapper RenderLine(long line) { Pango.Layout layout = new Pango.Layout(Editor.PangoContext); layout.FontDescription = Editor.Options.Font; layout.Tabs = tabArray; StringBuilder sb = new StringBuilder(); long startOffset = line * Editor.BytesInRow; long endOffset = System.Math.Min(startOffset + Editor.BytesInRow, Data.Length); byte[] lineBytes = Data.GetBytes(startOffset, (int)(endOffset - startOffset)); for (int i = 0; i < lineBytes.Length; i++) { sb.Append(string.Format("{0:X2}", lineBytes[i])); if (i % Editor.Options.GroupBytes == 0) { sb.Append("\t"); } } layout.SetText(sb.ToString()); char[] lineChars = sb.ToString().ToCharArray(); Margin.LayoutWrapper result = new LayoutWrapper(layout); uint curIndex = 0, byteIndex = 0; if (Data.IsSomethingSelected) { ISegment selection = Data.MainSelection.Segment; HandleSelection(selection.Offset, selection.EndOffset, startOffset, endOffset, null, delegate(long start, long end) { Pango.AttrForeground selectedForeground = new Pango.AttrForeground(Style.Selection.Red, Style.Selection.Green, Style.Selection.Blue); selectedForeground.StartIndex = TranslateToUTF8Index(lineChars, TranslateColumn(start - startOffset), ref curIndex, ref byteIndex); selectedForeground.EndIndex = TranslateToUTF8Index(lineChars, TranslateColumn(end - startOffset) - 1, ref curIndex, ref byteIndex); result.Add(selectedForeground); Pango.AttrBackground attrBackground = new Pango.AttrBackground(Style.SelectionBg.Red, Style.SelectionBg.Green, Style.SelectionBg.Blue); attrBackground.StartIndex = selectedForeground.StartIndex; attrBackground.EndIndex = selectedForeground.EndIndex; result.Add(attrBackground); }); } result.SetAttributes(); return(result); }
internal protected override void Draw(Gdk.Drawable drawable, Gdk.Rectangle area, long line, int x, int y) { drawable.DrawRectangle(bgGC, true, x, y, Width, Editor.LineHeight); LayoutWrapper layout = GetLayout(line); if (!Data.IsSomethingSelected && !Caret.InTextEditor && line == Data.Caret.Line) { int column = (int)(Caret.Offset % BytesInRow); int xOffset = charWidth * column; drawable.DrawRectangle(GetGC(Style.HighlightOffset), true, x + xOffset, y, charWidth, Editor.LineHeight); } drawable.DrawLayout(fgGC, x, y, layout.Layout); if (layout.IsUncached) { layout.Dispose(); } }
protected override LayoutWrapper RenderLine (long line) { Pango.Layout layout = new Pango.Layout (Editor.PangoContext); layout.FontDescription = Editor.Options.Font; StringBuilder sb = new StringBuilder (); long startOffset = line * Editor.BytesInRow; long endOffset = System.Math.Min (startOffset + Editor.BytesInRow, Data.Length); byte[] lineBytes = Data.GetBytes (startOffset, (int)(endOffset - startOffset)); for (int i = 0; i < lineBytes.Length; i++) { byte b = lineBytes[i]; char ch = (char)b; if (b < 128 && (Char.IsLetterOrDigit (ch) || Char.IsPunctuation (ch))) { sb.Append (ch); } else { sb.Append ("."); } } layout.SetText (sb.ToString ()); char[] lineChars = layout.Text.ToCharArray (); Margin.LayoutWrapper result = new LayoutWrapper (layout); uint curIndex = 0, byteIndex = 0; if (Data.IsSomethingSelected) { ISegment selection = Data.MainSelection.Segment; HandleSelection (selection.Offset, selection.EndOffset, startOffset, endOffset, null, delegate(long start, long end) { Pango.AttrForeground selectedForeground = new Pango.AttrForeground (Style.Selection.Red, Style.Selection.Green, Style.Selection.Blue); selectedForeground.StartIndex = TranslateToUTF8Index (lineChars, (uint)(start - startOffset), ref curIndex, ref byteIndex); selectedForeground.EndIndex = TranslateToUTF8Index (lineChars, (uint)(end - startOffset), ref curIndex, ref byteIndex); result.Add (selectedForeground); Pango.AttrBackground attrBackground = new Pango.AttrBackground (Style.SelectionBg.Red, Style.SelectionBg.Green, Style.SelectionBg.Blue); attrBackground.StartIndex = selectedForeground.StartIndex; attrBackground.EndIndex = selectedForeground.EndIndex; result.Add (attrBackground); }); } result.SetAttributes (); return result; }
internal protected override void Draw(Context ctx, Rectangle area, long line, double x, double y) { ctx.Rectangle(x, y, Width, Editor.LineHeight); ctx.SetColor(Style.HexOffsetBg); ctx.Fill(); if (line >= 0 && line * Editor.BytesInRow < Data.Length) { LayoutWrapper layout = GetLayout(line); var sz = layout.Layout.GetSize(); ctx.SetColor(line != Caret.Line ? Style.HexOffset : Style.HexOffsetHighlighted); ctx.DrawTextLayout(layout.Layout, x + Width - sz.Width - 4, y); if (layout.IsUncached) { layout.Dispose(); } } }
int CalculateCaretXPos(bool useSubPositon) { int byteInRow = (int)Caret.Offset % BytesInRow; int groupNumber = byteInRow / Editor.Options.GroupBytes; int groupByte = byteInRow % Editor.Options.GroupBytes; int caretIndex = groupNumber * (Editor.Options.GroupBytes * 2 + 1) + groupByte * 2; if (useSubPositon) { caretIndex += Caret.SubPosition; } LayoutWrapper layout = GetLayout((int)Caret.Line); Pango.Rectangle rectangle = layout.Layout.IndexToPos(caretIndex); if (layout.IsUncached) { layout.Dispose(); } return(XOffset + (int)(rectangle.X / Pango.Scale.PangoScale)); }
internal protected override void Draw(Context ctx, Rectangle area, long line, double x, double y) { ctx.Rectangle(x, y, Width, Editor.LineHeight); ctx.SetColor(Style.HexDigitBg); ctx.Fill(); LayoutWrapper layout = GetLayout(line); char ch; if (!Data.IsSomethingSelected && Caret.InTextEditor && line == Data.Caret.Line) { ctx.Rectangle(CalculateCaretXPos(false, out ch), y, byteWidth, Editor.LineHeight); ctx.SetColor(Style.HighlightOffset); ctx.Fill(); } ctx.SetColor(Style.HexDigit); ctx.DrawTextLayout(layout.Layout, x, y); if (layout.IsUncached) { layout.Dispose(); } }
double CalculateCaretXPos(bool useSubPositon, out char ch) { int byteInRow = (int)Caret.Offset % BytesInRow; int groupNumber = byteInRow / Editor.Options.GroupBytes; int groupByte = byteInRow % Editor.Options.GroupBytes; int caretIndex = groupNumber * (Editor.Options.GroupBytes * 2 + 1) + groupByte * 2; if (useSubPositon) { caretIndex += Caret.SubPosition; } LayoutWrapper layout = GetLayout((int)Caret.Line); var rectangle = layout.Layout.GetCoordinateFromIndex(caretIndex); var text = layout.Layout.Text; ch = caretIndex < text.Length ? text [caretIndex] : ' '; if (layout.IsUncached) { layout.Dispose(); } return(XOffset + rectangle.X); }
protected override LayoutWrapper RenderLine(long line) { var layout = new TextLayout(Editor); layout.Font = Editor.Options.Font; StringBuilder sb = new StringBuilder(); long startOffset = line * Editor.BytesInRow; long endOffset = System.Math.Min(startOffset + Editor.BytesInRow, Data.Length); byte[] lineBytes = Data.GetBytes(startOffset, (int)(endOffset - startOffset)); for (int i = 0; i < lineBytes.Length; i++) { byte b = lineBytes[i]; char ch = (char)b; if (b < 128 && (Char.IsLetterOrDigit(ch) || Char.IsPunctuation(ch))) { sb.Append(ch); } else { sb.Append("."); } } layout.Text = sb.ToString(); Margin.LayoutWrapper result = new LayoutWrapper(layout); if (Data.IsSomethingSelected) { ISegment selection = Data.MainSelection.Segment; HandleSelection(selection.Offset, selection.EndOffset, startOffset, endOffset, null, delegate(long start, long end) { result.Layout.SetForeground(Style.Selection, (int)(start - startOffset), (int)(end - start)); result.Layout.SetBackgound(Style.SelectionBg, (int)(start - startOffset), (int)(end - start)); }); } return(result); }
public LayoutWrapper CreateLinePartLayout (ISyntaxMode mode, LineSegment line, int logicalRulerColumn, int offset, int length, int selectionStart, int selectionEnd) { bool containsPreedit = textEditor.ContainsPreedit (offset, length); LayoutDescriptor descriptor; if (!containsPreedit && layoutDict.TryGetValue (line, out descriptor)) { bool isInvalid; if (descriptor.Equals (line, offset, length, selectionStart, selectionEnd, out isInvalid) && descriptor.Layout != null) { return descriptor.Layout; } descriptor.Dispose (); layoutDict.Remove (line); } var wrapper = new LayoutWrapper (PangoUtil.CreateLayout (textEditor)); wrapper.IsUncached = containsPreedit; if (logicalRulerColumn < 0) logicalRulerColumn = line.GetLogicalColumn (textEditor.GetTextEditorData (), textEditor.Options.RulerColumn); var atts = new FastPangoAttrList (); wrapper.Layout.Alignment = Pango.Alignment.Left; wrapper.Layout.FontDescription = textEditor.Options.Font; wrapper.Layout.Tabs = tabArray; StringBuilder textBuilder = new StringBuilder (); var chunks = GetCachedChunks (mode, Document, textEditor.ColorStyle, line, offset, length); foreach (var chunk in chunks) { try { textBuilder.Append (Document.GetTextAt (chunk)); } catch { Console.WriteLine (chunk); } } var spanStack = line.StartSpan; int lineOffset = line.Offset; string lineText = textBuilder.ToString (); uint preeditLength = 0; if (containsPreedit) { lineText = lineText.Insert (textEditor.preeditOffset - offset, textEditor.preeditString); preeditLength = (uint)textEditor.preeditString.Length; } char[] lineChars = lineText.ToCharArray (); //int startOffset = offset, endOffset = offset + length; uint curIndex = 0, byteIndex = 0; uint curChunkIndex = 0, byteChunkIndex = 0; uint oldEndIndex = 0; foreach (Chunk chunk in chunks) { ChunkStyle chunkStyle = chunk != null ? textEditor.ColorStyle.GetChunkStyle (chunk) : null; spanStack = chunk.SpanStack ?? spanStack; foreach (TextMarker marker in line.Markers) chunkStyle = marker.GetStyle (chunkStyle); if (chunkStyle != null) { //startOffset = chunk.Offset; //endOffset = chunk.EndOffset; uint startIndex = (uint)(oldEndIndex); uint endIndex = (uint)(startIndex + chunk.Length); oldEndIndex = endIndex; HandleSelection (lineOffset, logicalRulerColumn, selectionStart, selectionEnd, chunk.Offset, chunk.EndOffset, delegate(int start, int end) { if (containsPreedit) { if (textEditor.preeditOffset < start) start += (int)preeditLength; if (textEditor.preeditOffset < end) end += (int)preeditLength; } var si = TranslateToUTF8Index (lineChars, (uint)(startIndex + start - chunk.Offset), ref curIndex, ref byteIndex); var ei = TranslateToUTF8Index (lineChars, (uint)(startIndex + end - chunk.Offset), ref curIndex, ref byteIndex); atts.AddForegroundAttribute (chunkStyle.Color, si, ei); if (!chunkStyle.TransparentBackround && GetPixel (ColorStyle.Default.BackgroundColor) != GetPixel (chunkStyle.BackgroundColor)) { wrapper.AddBackground (chunkStyle.CairoBackgroundColor, (int)si, (int)ei); } else if (chunk.SpanStack != null && ColorStyle != null) { foreach (var span in chunk.SpanStack) { if (span == null) continue; var spanStyle = ColorStyle.GetChunkStyle (span.Color); if (!spanStyle.TransparentBackround && GetPixel (ColorStyle.Default.BackgroundColor) != GetPixel (spanStyle.BackgroundColor)) { wrapper.AddBackground (spanStyle.CairoBackgroundColor, (int)si, (int)ei); break; } } } }, delegate(int start, int end) { if (containsPreedit) { if (textEditor.preeditOffset < start) start += (int)preeditLength; if (textEditor.preeditOffset < end) end += (int)preeditLength; } var si = TranslateToUTF8Index (lineChars, (uint)(startIndex + start - chunk.Offset), ref curIndex, ref byteIndex); var ei = TranslateToUTF8Index (lineChars, (uint)(startIndex + end - chunk.Offset), ref curIndex, ref byteIndex); atts.AddForegroundAttribute (SelectionColor.Color, si, ei); if (!wrapper.StartSet) wrapper.SelectionStartIndex = (int)si; wrapper.SelectionEndIndex = (int)ei; }); var translatedStartIndex = TranslateToUTF8Index (lineChars, (uint)startIndex, ref curChunkIndex, ref byteChunkIndex); var translatedEndIndex = TranslateToUTF8Index (lineChars, (uint)endIndex, ref curChunkIndex, ref byteChunkIndex); if (chunkStyle.Bold) atts.AddWeightAttribute (Pango.Weight.Bold, translatedStartIndex, translatedEndIndex); if (chunkStyle.Italic) atts.AddStyleAttribute (Pango.Style.Italic, translatedStartIndex, translatedEndIndex); if (chunkStyle.Underline) atts.AddUnderlineAttribute (Pango.Underline.Single, translatedStartIndex, translatedEndIndex); } } if (containsPreedit) { var si = TranslateToUTF8Index (lineChars, (uint)(textEditor.preeditOffset - offset), ref curIndex, ref byteIndex); var ei = TranslateToUTF8Index (lineChars, (uint)(textEditor.preeditOffset - offset + preeditLength), ref curIndex, ref byteIndex); atts.Splice (textEditor.preeditAttrs, (int)si, (int)(ei - si)); } wrapper.LineChars = lineChars; wrapper.Layout.SetText (lineText); wrapper.EolSpanStack = spanStack; atts.AssignTo (wrapper.Layout); atts.Dispose (); int w, h; wrapper.Layout.GetSize (out w, out h); wrapper.PangoWidth = w; selectionStart = System.Math.Max (line.Offset - 1, selectionStart); selectionEnd = System.Math.Min (line.EndOffsetIncludingDelimiter + 1, selectionEnd); descriptor = new LayoutDescriptor (line, offset, length, wrapper, selectionStart, selectionEnd); if (!containsPreedit) layoutDict[line] = descriptor; return wrapper; }
void DrawLinePart (Cairo.Context cr, LineSegment line, int lineNumber, int logicalRulerColumn, int offset, int length, ref double pangoPosition, ref bool isSelectionDrawn, double y, double maxX) { ISyntaxMode mode = Document.SyntaxMode != null && textEditor.Options.EnableSyntaxHighlighting ? Document.SyntaxMode : new SyntaxMode (Document); int selectionStart; int selectionEnd; if (this.HideSelection) { selectionStart = selectionEnd = -1; } else { GetSelectionOffsets (line, out selectionStart, out selectionEnd); } // ---- new renderer LayoutWrapper layout = CreateLinePartLayout (mode, line, logicalRulerColumn, offset, length, selectionStart, selectionEnd); int lineOffset = line.Offset; double width = layout.PangoWidth / Pango.Scale.PangoScale; double xPos = pangoPosition / Pango.Scale.PangoScale; // if (!(HighlightCaretLine || textEditor.Options.HighlightCaretLine) || Document.GetLine(Caret.Line) != line) { foreach (var bg in layout.BackgroundColors) { int x1, x2; x1 = layout.Layout.IndexToPos (bg.FromIdx).X; x2 = layout.Layout.IndexToPos (bg.ToIdx).X; DrawRectangleWithRuler (cr, xPos + textEditor.HAdjustment.Value - TextStartPosition, new Cairo.Rectangle ((x1 + pangoPosition) / Pango.Scale.PangoScale, y, (x2 - x1) / Pango.Scale.PangoScale + 1, LineHeight), bg.Color, true); } // } bool drawBg = true; bool drawText = true; foreach (TextMarker marker in line.Markers) { IBackgroundMarker bgMarker = marker as IBackgroundMarker; if (bgMarker == null || !marker.IsVisible) continue; isSelectionDrawn |= (marker.Flags & TextMarkerFlags.DrawsSelection) == TextMarkerFlags.DrawsSelection; drawText &= bgMarker.DrawBackground (textEditor, cr, layout, selectionStart, selectionEnd, offset, offset + length, y, xPos, xPos + width, ref drawBg); } if (DecorateLineBg != null) DecorateLineBg (cr, layout, offset, length, xPos, y, selectionStart, selectionEnd); if ((HighlightCaretLine || textEditor.Options.HighlightCaretLine) && Caret.Line == lineNumber) DrawCaretLineMarker (cr, xPos, y, layout.PangoWidth / Pango.Scale.PangoScale); if (!isSelectionDrawn && (layout.StartSet || selectionStart == offset + length)) { double startX; double endX; if (selectionStart != offset + length) { var start = layout.Layout.IndexToPos ((int)layout.SelectionStartIndex); startX = start.X / Pango.Scale.PangoScale; var end = layout.Layout.IndexToPos ((int)layout.SelectionEndIndex); endX = end.X / Pango.Scale.PangoScale; } else { startX = width; endX = startX; } if (textEditor.MainSelection.SelectionMode == SelectionMode.Block && startX == endX) { endX = startX + 2; } DrawRectangleWithRuler (cr, xPos + textEditor.HAdjustment.Value - TextStartPosition, new Cairo.Rectangle (xPos + startX, y, endX - startX, LineHeight), this.SelectionColor.CairoBackgroundColor, true); } // highlight search results TextSegment firstSearch; int o = offset; uint curIndex = 0, byteIndex = 0; if (textEditor.HighlightSearchPattern) { while (!(firstSearch = GetFirstSearchResult (o, offset + length)).IsInvalid) { double x = pangoPosition; HandleSelection (lineOffset, logicalRulerColumn, selectionStart, selectionEnd, System.Math.Max (lineOffset, firstSearch.Offset), System.Math.Min (lineOffset + line.Length, firstSearch.EndOffset), delegate(int start, int end) { uint startIndex = (uint)(start - offset); uint endIndex = (uint)(end - offset); if (startIndex < endIndex && endIndex <= layout.LineChars.Length) { uint startTranslated = TranslateToUTF8Index (layout.LineChars, startIndex, ref curIndex, ref byteIndex); uint endTranslated = TranslateToUTF8Index (layout.LineChars, endIndex, ref curIndex, ref byteIndex); int l, x1, x2; layout.Layout.IndexToLineX ((int)startTranslated, false, out l, out x1); layout.Layout.IndexToLineX ((int)endTranslated, false, out l, out x2); x1 += (int)x; x2 += (int)x; x1 /= (int)Pango.Scale.PangoScale; x2 /= (int)Pango.Scale.PangoScale; cr.Color = MainSearchResult.IsInvalid || MainSearchResult.Offset != firstSearch.Offset ? ColorStyle.SearchTextBg : ColorStyle.SearchTextMainBg; FoldingScreenbackgroundRenderer.DrawRoundRectangle (cr, true, true, x1, y, System.Math.Min (10, width) * textEditor.Options.Zoom, x2 - x1, LineHeight); cr.Fill (); } }, null); o = System.Math.Max (firstSearch.EndOffset, o + 1); } } cr.Save (); cr.Translate (xPos, y); cr.ShowLayout (layout.Layout); cr.Restore (); if (DecorateLineFg != null) DecorateLineFg (cr, layout, offset, length, xPos, y, selectionStart, selectionEnd); if (lineNumber == Caret.Line) { int caretOffset = Caret.Offset; if (offset <= caretOffset && caretOffset <= offset + length) { int index = caretOffset - offset; if (Caret.Column > line.Length + 1) { string virtualSpace = ""; var data = textEditor.GetTextEditorData (); if (data.HasIndentationTracker && line.Length == 0) { virtualSpace = this.textEditor.GetTextEditorData ().GetIndentationString (Caret.Location); } if (Caret.Column > line.Length + 1 + virtualSpace.Length) virtualSpace += new string (' ', Caret.Column - line.Length - 1 - virtualSpace.Length); LayoutWrapper wrapper = new LayoutWrapper (PangoUtil.CreateLayout (textEditor)); wrapper.LineChars = virtualSpace.ToCharArray (); wrapper.Layout.SetText (virtualSpace); wrapper.Layout.Tabs = tabArray; wrapper.Layout.FontDescription = textEditor.Options.Font; int vy, vx; wrapper.Layout.GetSize (out vx, out vy); SetVisibleCaretPosition (((pangoPosition + vx + layout.PangoWidth) / Pango.Scale.PangoScale), y); xPos = (pangoPosition + layout.PangoWidth) / Pango.Scale.PangoScale; if (!isSelectionDrawn && (selectionEnd == lineOffset + line.Length)) { double startX; double endX; startX = xPos; endX = (pangoPosition + vx + layout.PangoWidth) / Pango.Scale.PangoScale; DrawRectangleWithRuler (cr, xPos + textEditor.HAdjustment.Value - TextStartPosition, new Cairo.Rectangle (startX, y, endX - startX, LineHeight), this.SelectionColor.CairoBackgroundColor, true); } if ((HighlightCaretLine || textEditor.Options.HighlightCaretLine) && Caret.Line == lineNumber) DrawCaretLineMarker (cr, pangoPosition / Pango.Scale.PangoScale, y, vx / Pango.Scale.PangoScale); // When drawing virtual space before the selection start paint it as unselected. var virtualSpaceMod = selectionStart < caretOffset ? 0 : virtualSpace.Length; if (DecorateLineBg != null) DecorateLineBg (cr, wrapper, offset, length, xPos, y, selectionStart + virtualSpaceMod, selectionEnd + virtualSpace.Length); if (DecorateLineFg != null) DecorateLineFg (cr, wrapper, offset, length, xPos, y, selectionStart + virtualSpaceMod, selectionEnd + virtualSpace.Length); wrapper.Dispose (); pangoPosition += vx; } else if (index == length && textEditor.preeditString == null) { SetVisibleCaretPosition ((pangoPosition + layout.PangoWidth) / Pango.Scale.PangoScale, y); } else if (index >= 0 && index <= length) { Pango.Rectangle strong_pos, weak_pos; curIndex = byteIndex = 0; int utf8ByteIndex = (int)TranslateToUTF8Index (layout.LineChars, (uint)index, ref curIndex, ref byteIndex); if (textEditor.preeditString != null && textEditor.preeditCursorCharIndex > 0) { curIndex = byteIndex = 0; int preeditUtf8ByteIndex = (int)TranslateToUTF8Index (textEditor.preeditString.ToCharArray (), (uint)textEditor.preeditCursorCharIndex, ref curIndex, ref byteIndex); utf8ByteIndex += preeditUtf8ByteIndex; } layout.Layout.GetCursorPos (utf8ByteIndex, out strong_pos, out weak_pos); SetVisibleCaretPosition (xPos + (strong_pos.X / Pango.Scale.PangoScale), y); } } } foreach (TextMarker marker in line.Markers.Where (m => m.IsVisible)) { if (layout.Layout != null) marker.Draw (textEditor, cr, layout.Layout, false, /*selected*/offset, offset + length, y, xPos, xPos + width); } pangoPosition += layout.PangoWidth; if (layout.IsUncached) layout.Dispose (); }
void DecorateTabsAndSpaces (Cairo.Context ctx, LayoutWrapper layout, int offset, int length, double xPos, double y, int selectionStart, int selectionEnd) { uint curIndex = 0, byteIndex = 0; bool first = true, oldSelected = false; int index, trailing; layout.Layout.XyToIndex ((int)textEditor.HAdjustment.Value, 0, out index, out trailing); for (int i = index; i < layout.LineChars.Length; i++) { char ch = layout.LineChars [i]; if (ch != ' ' && ch != '\t') continue; bool selected = selectionStart <= offset + i && offset + i < selectionEnd; if (first || oldSelected != selected) { ctx.Color = selected ? SelectionColor.CairoColor : ColorStyle.WhitespaceMarker; first = false; oldSelected = selected; } Pango.Rectangle pos = layout.Layout.IndexToPos ((int)TranslateToUTF8Index (layout.LineChars, (uint)i, ref curIndex, ref byteIndex)); double xpos = xPos + pos.X / Pango.Scale.PangoScale; if (xpos > textEditor.Allocation.Width) break; if (ch == '\t') { DrawTabMarker (ctx, selected, xpos, y); } else { DrawSpaceMarker (ctx, selected, xpos, y); } } }
bool ConsumeLayout (LayoutWrapper layoutWrapper, int xp, int yp) { int trailing; bool isInside = layoutWrapper.Layout.XyToIndex (xp, yp, out index, out trailing); if (isInside) { int lineNr; int xp1, xp2; layoutWrapper.Layout.IndexToLineX (index, false, out lineNr, out xp1); layoutWrapper.Layout.IndexToLineX (index + 1, false, out lineNr, out xp2); index = TranslateIndexToUTF8 (layoutWrapper.Layout.Text, index); if (snapCharacters && !IsNearX1 (xp, xp1, xp2)) index++; return true; } index = line.Length; return false; }
protected override LayoutWrapper RenderLine (long line) { var layout = new TextLayout (Editor); layout.Font = Editor.Options.Font; StringBuilder sb = new StringBuilder (); long startOffset = line * Editor.BytesInRow; long endOffset = System.Math.Min (startOffset + Editor.BytesInRow, Data.Length); byte[] lineBytes = Data.GetBytes (startOffset, (int)(endOffset - startOffset)); switch (Editor.Options.StringRepresentationType) { case StringRepresentationTypes.ASCII: for (int i = 0; i < lineBytes.Length; i++) { byte b = lineBytes [i]; char ch = (char)b; if (!char.IsControl (ch)) { sb.Append (ch); } else { sb.Append ("."); } } break; case StringRepresentationTypes.UTF16: for (int i = 0; i < lineBytes.Length - 1; i += 2) { char ch = Encoding.Unicode.GetChars (lineBytes, i, 2) [0]; if (char.IsLetterOrDigit (ch) || char.IsWhiteSpace (ch) || char.IsSymbol (ch) || char.IsPunctuation (ch)) sb.Append (ch); else sb.Append ("."); } break; default: throw new NotImplementedException (Editor.Options.StringRepresentationType.ToString ()); } layout.Text = sb.ToString (); Margin.LayoutWrapper result = new LayoutWrapper (layout); if (Data.IsSomethingSelected) { ISegment selection = Data.MainSelection.Segment; HandleSelection (selection.Offset, selection.EndOffset, startOffset, endOffset, this, new LayoutOffsetPair (startOffset, result.Layout), null, OnSelected); } return result; }
public LayoutDescriptor (DocumentLine line, int offset, int length, LayoutWrapper layout, int selectionStart, int selectionEnd) : base(line, offset, length) { this.Layout = layout; if (selectionEnd >= 0) { this.SelectionStart = selectionStart; this.SelectionEnd = selectionEnd; } }
void DrawIndent (Cairo.Context cr, LayoutWrapper layout, DocumentLine line, double xPos, double y) { if (!textEditor.Options.DrawIndentationMarkers) return; if (line.Length == 0) { var nextLine = line.NextLine; while (nextLine != null && nextLine.Length == 0) nextLine = nextLine.NextLine; if (nextLine != null) layout = GetLayout (nextLine); } if (layout.IndentSize == 0) return; cr.Save (); var dotted = new [] { textEditor.Options.Zoom }; cr.SetDash (dotted, (int)y + textEditor.VAdjustment.Value); var top = y; var bottom = y + LineHeight; if (Caret.Line == line.LineNumber && textEditor.Options.HighlightCaretLine) { top += textEditor.Options.Zoom; bottom -= textEditor.Options.Zoom; } for (int i = 0; i < layout.IndentSize; i += textEditor.Options.IndentationSize) { var x = System.Math.Floor (xPos + i * charWidth); cr.MoveTo (x + 0.5, top); cr.LineTo (x + 0.5, bottom); cr.Color = ColorStyle.IndentationGuide.Color; cr.Stroke (); } cr.Restore (); }
void DecorateTabsAndSpaces (Cairo.Context ctx, LayoutWrapper layout, int offset, int length, double xPos, double y, int selectionStart, int selectionEnd) { uint curIndex = 0, byteIndex = 0; bool first = true, oldSelected = false; int index, trailing; layout.Layout.XyToIndex ((int)textEditor.HAdjustment.Value, 0, out index, out trailing); var curchunk = layout.Chunks != null ? layout.Chunks.FirstOrDefault () : null; for (int i = index; i < layout.LineChars.Length; i++) { char ch = layout.LineChars [i]; if (ch != ' ' && ch != '\t') continue; if (ch == ' ' && !textEditor.Options.IncludeWhitespaces.HasFlag (IncludeWhitespaces.Space)) continue; if (ch == '\t' && !textEditor.Options.IncludeWhitespaces.HasFlag (IncludeWhitespaces.Tab)) continue; bool selected = selectionStart <= offset + i && offset + i < selectionEnd; if (first || oldSelected != selected) { first = false; oldSelected = selected; } if (!selected && textEditor.Options.ShowWhitespaces != ShowWhitespaces.Always) continue; Pango.Rectangle pos = layout.Layout.IndexToPos ((int)TranslateToUTF8Index (layout.LineChars, (uint)i, ref curIndex, ref byteIndex)); double xpos = xPos + pos.X / Pango.Scale.PangoScale; if (xpos > textEditor.Allocation.Width) break; Pango.Rectangle pos2 = layout.Layout.IndexToPos ((int)TranslateToUTF8Index (layout.LineChars, (uint)i + 1, ref curIndex, ref byteIndex)); double xpos2 = xPos + pos2.X / Pango.Scale.PangoScale; Cairo.Color col = new Cairo.Color (0, 0, 0); if (SelectionColor.TransparentForeground) { while (curchunk != null && curchunk.EndOffset < offset + i) curchunk = curchunk.Next; if (curchunk != null && curchunk.SpanStack.Count > 0 && curchunk.SpanStack.Peek ().Color != "Plain Text") { var chunkStyle = ColorStyle.GetChunkStyle (curchunk.SpanStack.Peek ().Color); if (chunkStyle != null) col = ColorStyle.GetForeground (chunkStyle); } else { col = ColorStyle.PlainText.Foreground; } } else { col = selected ? SelectionColor.Foreground : col = ColorStyle.PlainText.Foreground; } ctx.Color = new Cairo.Color (col.R, col.G, col.B, whitespaceMarkerAlpha); if (ch == '\t') { DrawTabMarker (ctx, selected, xpos, xpos2, y); } else { DrawSpaceMarker (ctx, selected, xpos, xpos2, y); } } }
void DecorateTabsAndSpaces (Cairo.Context ctx, LayoutWrapper layout, int offset, double x, double y, int selectionStart, int selectionEnd) { if (textEditor.Options.IncludeWhitespaces.HasFlag (IncludeWhitespaces.Space)) { InnerDecorateTabsAndSpaces (ctx, layout, offset, x, y, selectionStart, selectionEnd, ' '); } if (textEditor.Options.IncludeWhitespaces.HasFlag (IncludeWhitespaces.Tab)) { InnerDecorateTabsAndSpaces (ctx, layout, offset, x, y, selectionStart, selectionEnd, '\t'); } }
protected override LayoutWrapper RenderLine (long line) { var layout = new TextLayout (Editor); layout.Font = Editor.Options.Font; // layout.Tabs = tabArray; StringBuilder sb = new StringBuilder (); long startOffset = line * Editor.BytesInRow; long endOffset = System.Math.Min (startOffset + Editor.BytesInRow, Data.Length); byte[] lineBytes = Data.GetBytes (startOffset, (int)(endOffset - startOffset)); for (int i = 0; i < lineBytes.Length; i++) { sb.Append (string.Format ("{0:X2}", lineBytes[i])); if (i % Editor.Options.GroupBytes == 0) sb.Append (" "); // \t } layout.Text = sb.ToString (); Margin.LayoutWrapper result = new LayoutWrapper (layout); if (Data.IsSomethingSelected) { ISegment selection = Data.MainSelection.Segment; HandleSelection (selection.Offset, selection.EndOffset, startOffset, endOffset, null, delegate(long start, long end) { result.Layout.SetForeground (Style.Selection, (int)(start - startOffset) * 3, (int)(end - start) * 3 - 1); result.Layout.SetBackgound (Style.SelectionBg, (int)(start - startOffset) * 3, (int)(end - start) * 3 - 1); }); } return result; }
void DecorateTabsAndSpaces (Cairo.Context ctx, LayoutWrapper layout, int offset, int length, double xPos, double y, int selectionStart, int selectionEnd) { uint curIndex = 0, byteIndex = 0; bool first = true, oldSelected = false; for (int i = 0; i < layout.LineChars.Length; i++) { char ch = layout.LineChars[i]; if (ch != ' ' && ch != '\t') continue; bool selected = selectionStart <= offset + i && offset + i < selectionEnd; if (first || oldSelected != selected) { ctx.Color = selected ? SelectionColor.CairoColor : ColorStyle.WhitespaceMarker; first = false; oldSelected = selected; } Pango.Rectangle pos = layout.Layout.IndexToPos ((int)TranslateToUTF8Index (layout.LineChars, (uint)i, ref curIndex, ref byteIndex)); int xpos = pos.X; if (ch == '\t') { DrawTabMarker (ctx, selected, xPos + xpos / Pango.Scale.PangoScale, y); } else { DrawSpaceMarker (ctx, selected, xPos + xpos / Pango.Scale.PangoScale, y); } } }
protected override LayoutWrapper RenderLine (long line) { Pango.Layout layout = new Pango.Layout (Editor.PangoContext); layout.FontDescription = Editor.Options.Font; layout.Tabs = tabArray; StringBuilder sb = new StringBuilder (); long startOffset = line * Editor.BytesInRow; long endOffset = System.Math.Min (startOffset + Editor.BytesInRow, Data.Length); byte[] lineBytes = Data.GetBytes (startOffset, (int)(endOffset - startOffset)); for (int i = 0; i < lineBytes.Length; i++) { sb.Append (string.Format ("{0:X2}", lineBytes[i])); if (i % Editor.Options.GroupBytes == 0) sb.Append ("\t"); } layout.SetText (sb.ToString ()); char[] lineChars = sb.ToString ().ToCharArray (); Margin.LayoutWrapper result = new LayoutWrapper (layout); uint curIndex = 0, byteIndex = 0; if (Data.IsSomethingSelected) { ISegment selection = Data.MainSelection.Segment; HandleSelection (selection.Offset, selection.EndOffset, startOffset, endOffset, null, delegate(long start, long end) { Pango.AttrForeground selectedForeground = new Pango.AttrForeground (Style.Selection.Red, Style.Selection.Green, Style.Selection.Blue); selectedForeground.StartIndex = TranslateToUTF8Index (lineChars, TranslateColumn (start - startOffset), ref curIndex, ref byteIndex); selectedForeground.EndIndex = TranslateToUTF8Index (lineChars, TranslateColumn (end - startOffset) - 1, ref curIndex, ref byteIndex); result.Add (selectedForeground); Pango.AttrBackground attrBackground = new Pango.AttrBackground (Style.SelectionBg.Red, Style.SelectionBg.Green, Style.SelectionBg.Blue); attrBackground.StartIndex = selectedForeground.StartIndex; attrBackground.EndIndex = selectedForeground.EndIndex; result.Add (attrBackground); }); } result.SetAttributes (); return result; }
void InnerDecorateTabsAndSpaces (Cairo.Context ctx, LayoutWrapper layout, int offset, double x, double y, int selectionStart, int selectionEnd, char spaceOrTab) { var chars = layout.LineChars; if (Array.IndexOf (chars, spaceOrTab) == -1) return; uint curIndex = 0, byteIndex = 0; bool first = true, oldSelected = false; var curchunk = layout.Chunks != null ? layout.Chunks.FirstOrDefault () : null; var dotThickness = textEditor.Options.Zoom * 2; var textEditorWidth = textEditor.Allocation.Width; //Get 1st visible character index from left based on HAdjustment int index, trailing; layout.Layout.XyToIndex ((int)textEditor.HAdjustment.Value, 0, out index, out trailing); double ypos; if (spaceOrTab == ' ') { ypos = System.Math.Floor (y + (LineHeight - dotThickness) / 2); } else { ypos = 0.5 + System.Math.Floor (y + LineHeight / 2); } var showOnlySelected = textEditor.Options.ShowWhitespaces != ShowWhitespaces.Always; var lastColor = new Cairo.Color (); bool firstDraw = true; var foregroundColor = ColorStyle.PlainText.Foreground; int lastIndex = -1; int lastPosX = 0; for (int i = index; i < chars.Length; i++) { if (spaceOrTab != chars [i]) continue; bool selected = selectionStart <= offset + i && offset + i < selectionEnd; if (first || oldSelected != selected) { first = false; oldSelected = selected; } if (showOnlySelected && !selected) continue; int line, posX; if (lastIndex == i) { posX = lastPosX; } else { layout.Layout.IndexToLineX ((int)TranslateToUTF8Index (chars, (uint)i, ref curIndex, ref byteIndex), false, out line, out posX); } double xpos = x + posX / Pango.Scale.PangoScale; if (xpos > textEditorWidth) break; layout.Layout.IndexToLineX ((int)TranslateToUTF8Index (chars, (uint)i + 1, ref curIndex, ref byteIndex), false, out line, out posX); lastPosX = posX; lastIndex = i + 1; double xpos2 = x + posX / Pango.Scale.PangoScale; var col = new Cairo.Color (0, 0, 0); if (SelectionColor.TransparentForeground) { while (curchunk != null && curchunk.EndOffset < offset + i) curchunk = curchunk.Next; if (curchunk != null && curchunk.SpanStack.Count > 0 && curchunk.SpanStack.Peek ().Color != "Plain Text") { var chunkStyle = ColorStyle.GetChunkStyle (curchunk.SpanStack.Peek ().Color); if (chunkStyle != null) col = ColorStyle.GetForeground (chunkStyle); } else { col = foregroundColor; } } else { col = selected ? SelectionColor.Foreground : foregroundColor; } if (firstDraw || (lastColor.R != col.R && lastColor.G != col.G && lastColor.B != col.B)) { ctx.SetSourceRGBA (col.R, col.G, col.B, whitespaceMarkerAlpha); lastColor = col; firstDraw = false; } if (spaceOrTab == ' ') { ctx.Rectangle (xpos + (xpos2 - xpos - dotThickness) / 2, ypos, dotThickness, dotThickness); } else { ctx.MoveTo (0.5 + xpos, ypos); ctx.LineTo (0.5 + xpos2 - charWidth / 2, ypos); } } if (!firstDraw) {//Atleast one draw was called if (spaceOrTab == ' ') { ctx.Fill (); } else { ctx.Stroke (); } } }
void DecorateTabs (Gdk.Drawable win, LayoutWrapper layout, int offset, int length, int xPos, int y, int selectionStart, int selectionEnd) { uint curIndex = 0, byteIndex = 0; for (int i = 0; i < layout.LineChars.Length; i++) { if (layout.LineChars[i] == '\t') { Pango.Rectangle pos = layout.Layout.IndexToPos ((int)TranslateToUTF8Index (layout.LineChars, (uint)i, ref curIndex, ref byteIndex)); int xpos = pos.X; DrawTabMarker (win, selectionStart <= offset + i && offset + i < selectionEnd, xPos + xpos / 1024, y); } } }
LayoutWrapper GetVirtualSpaceLayout (DocumentLine line, DocumentLocation location) { string virtualSpace = ""; var data = textEditor.GetTextEditorData (); if (data.HasIndentationTracker && line.Length == 0) { virtualSpace = this.textEditor.GetTextEditorData ().GetIndentationString (location); } if (location.Column > line.Length + 1 + virtualSpace.Length) virtualSpace += new string (' ', location.Column - line.Length - 1 - virtualSpace.Length); // predit layout already contains virtual space. if (!string.IsNullOrEmpty (textEditor.preeditString)) virtualSpace = ""; LayoutWrapper wrapper = new LayoutWrapper (textEditor.LayoutCache.RequestLayout ()); wrapper.LineChars = virtualSpace.ToCharArray (); wrapper.Layout.SetText (virtualSpace); wrapper.Layout.Tabs = tabArray; wrapper.Layout.FontDescription = textEditor.Options.Font; int vy, vx; wrapper.Layout.GetSize (out vx, out vy); wrapper.Width = wrapper.LastLineWidth = vx / Pango.Scale.PangoScale; return wrapper; }
void DecorateMatchingBracket (Gdk.Drawable win, LayoutWrapper layout, int offset, int length, int xPos, int y, int selectionStart, int selectionEnd) { uint curIndex = 0, byteIndex = 0; if (offset <= highlightBracketOffset && highlightBracketOffset <= offset + length) { int index = highlightBracketOffset - offset; Pango.Rectangle rect = layout.Layout.IndexToPos ((int)TranslateToUTF8Index (layout.LineChars, (uint)index, ref curIndex, ref byteIndex)); Gdk.Rectangle bracketMatch = new Gdk.Rectangle (xPos + (int)(rect.X / Pango.Scale.PangoScale), y, (int)(rect.Width / Pango.Scale.PangoScale) - 1, (int)(rect.Height / Pango.Scale.PangoScale) - 1); if (BackgroundRenderer == null) win.DrawRectangle (GetGC (this.ColorStyle.BracketHighlightRectangle.BackgroundColor), true, bracketMatch); win.DrawRectangle (GetGC (this.ColorStyle.BracketHighlightRectangle.Color), false, bracketMatch); } }
void DecorateMatchingBracket (Cairo.Context ctx, LayoutWrapper layout, int offset, int length, double xPos, double y, int selectionStart, int selectionEnd) { uint curIndex = 0, byteIndex = 0; if (offset <= highlightBracketOffset && highlightBracketOffset <= offset + length) { int index = highlightBracketOffset - offset; Pango.Rectangle rect = layout.Layout.IndexToPos ((int)TranslateToUTF8Index (layout.LineChars, (uint)index, ref curIndex, ref byteIndex)); var bracketMatch = new Cairo.Rectangle (xPos + rect.X / Pango.Scale.PangoScale + 0.5, y + 0.5, (rect.Width / Pango.Scale.PangoScale) - 1, (rect.Height / Pango.Scale.PangoScale) - 1); if (BackgroundRenderer == null) { ctx.Color = this.ColorStyle.BraceMatchingRectangle.Color; ctx.Rectangle (bracketMatch); ctx.FillPreserve (); ctx.Color = this.ColorStyle.BraceMatchingRectangle.SecondColor; ctx.Stroke (); } } }
void DrawLinePart (Gdk.Drawable win, LineSegment line, int offset, int length, ref int pangoPosition, ref bool isSelectionDrawn, int y, int maxX) { SyntaxMode mode = Document.SyntaxMode != null && textEditor.Options.EnableSyntaxHighlighting ? Document.SyntaxMode : SyntaxMode.Default; int selectionStart; int selectionEnd; if (BackgroundRenderer != null || this.HideSelection) { selectionStart = selectionEnd = -1; } else { GetSelectionOffsets (line, out selectionStart, out selectionEnd); } // ---- new renderer LayoutWrapper layout = CreateLinePartLayout (mode, line, offset, length, selectionStart, selectionEnd); int width = (int)(layout.PangoWidth / Pango.Scale.PangoScale); int xPos = (int)(pangoPosition / Pango.Scale.PangoScale); bool drawBg = true; bool drawText = true; foreach (TextMarker marker in line.Markers) { IBackgroundMarker bgMarker = marker as IBackgroundMarker; if (bgMarker == null || !marker.IsVisible) continue; isSelectionDrawn |= (marker.Flags & TextMarkerFlags.DrawsSelection) == TextMarkerFlags.DrawsSelection; drawText &= bgMarker.DrawBackground (textEditor, win, layout, selectionStart, selectionEnd, offset, offset + length, y, xPos, xPos + width, ref drawBg); } if (DecorateLineBg != null) DecorateLineBg (win, layout, offset, length, xPos, y, selectionStart, selectionEnd); if (!isSelectionDrawn && (layout.StartSet || selectionStart == offset + length)) { int startX; int endX; if (selectionStart != offset + length) { var start = layout.Layout.IndexToPos ((int)layout.SelectionStartIndex); startX = (int)(start.X / Pango.Scale.PangoScale); var end = layout.Layout.IndexToPos ((int)layout.SelectionEndIndex); endX = (int)(end.X / Pango.Scale.PangoScale); } else { startX = width; endX = startX; } if (textEditor.MainSelection.SelectionMode == SelectionMode.Block && startX == endX) { endX = startX + 2; } DrawRectangleWithRuler (win, xPos + (int)textEditor.HAdjustment.Value - TextStartPosition, new Rectangle (xPos + startX, y, endX - startX, textEditor.LineHeight), this.SelectionColor.BackgroundColor, true); } // highlight search results ISegment firstSearch; int o = offset; uint curIndex = 0, byteIndex = 0; while ((firstSearch = GetFirstSearchResult (o, offset + length)) != null) { int x = pangoPosition; HandleSelection (line, selectionStart, selectionEnd, firstSearch.Offset, firstSearch.EndOffset, delegate(int start, int end) { uint startIndex = (uint)(start - offset); uint endIndex = (uint)(end - offset); if (startIndex < endIndex && endIndex <= layout.LineChars.Length) { uint startTranslated = TranslateToUTF8Index (layout.LineChars, startIndex, ref curIndex, ref byteIndex); uint endTranslated = TranslateToUTF8Index (layout.LineChars, endIndex, ref curIndex, ref byteIndex); using (Cairo.Context cr = Gdk.CairoHelper.Create (win)) { cr.Rectangle (XOffset, 0, textEditor.Allocation.Width - XOffset, textEditor.Allocation.Height); cr.Clip (); int l, x1, x2; layout.Layout.IndexToLineX ((int)startTranslated, false, out l, out x1); layout.Layout.IndexToLineX ((int)endTranslated, false, out l, out x2); x1 += x; x2 += x; x1 /= (int)Pango.Scale.PangoScale; x2 /= (int)Pango.Scale.PangoScale; cr.Color = Mono.TextEditor.Highlighting.Style.ToCairoColor (MainSearchResult == null || MainSearchResult.Offset != firstSearch.Offset ? ColorStyle.SearchTextBg : ColorStyle.SearchTextMainBg, AlphaBlendSearchResults ? 0.6 : 1.0); FoldingScreenbackgroundRenderer.DrawRoundRectangle (cr, true, true, x1, y, (int)(System.Math.Min (10, width) * textEditor.Options.Zoom), x2 - x1, textEditor.LineHeight); cr.Fill (); } } }, null); o = System.Math.Max (firstSearch.EndOffset, o + 1); } win.DrawLayout (GetGC (ColorStyle.Default.Color), xPos, y, layout.Layout); if (DecorateLineFg != null) DecorateLineFg (win, layout, offset, length, xPos, y, selectionStart, selectionEnd); if (Document.GetLine (Caret.Line) == line) { int caretOffset = Caret.Offset; if (offset <= caretOffset && caretOffset <= offset + length) { Pango.Rectangle strong_pos, weak_pos; int index = caretOffset- offset; if (offset <= textEditor.preeditOffset && textEditor.preeditOffset < offset + length) { index += textEditor.preeditString.Length; } if (Caret.Column > line.EditableLength) { string virtualSpace = this.textEditor.GetTextEditorData ().GetVirtualSpaces (Caret.Line, Caret.Column); LayoutWrapper wrapper = new LayoutWrapper (PangoUtil.CreateLayout (textEditor)); wrapper.LineChars = virtualSpace.ToCharArray (); wrapper.Layout.SetText (virtualSpace); wrapper.Layout.Tabs = tabArray; int vy, vx; wrapper.Layout.GetSize (out vx, out vy); SetVisibleCaretPosition (win, ' ', (int)((pangoPosition + vx + layout.PangoWidth) / Pango.Scale.PangoScale), y); xPos = (int)((pangoPosition + layout.PangoWidth) / Pango.Scale.PangoScale); if (!isSelectionDrawn && (selectionEnd == line.Offset + line.EditableLength)) { int startX; int endX; startX = xPos; endX = (int)((pangoPosition + vx + layout.PangoWidth) / Pango.Scale.PangoScale); DrawRectangleWithRuler (win, xPos + (int)textEditor.HAdjustment.Value - TextStartPosition, new Rectangle (startX, y, endX - startX, textEditor.LineHeight), this.SelectionColor.BackgroundColor, true); } if (DecorateLineBg != null) DecorateLineBg (win, wrapper, offset, length, xPos, y, selectionStart, selectionEnd + virtualSpace.Length); if (DecorateLineFg != null) DecorateLineFg (win, wrapper, offset, length, xPos, y, selectionStart, selectionEnd + virtualSpace.Length); wrapper.Dispose (); pangoPosition += vx; } else if (index >= 0 && index < length) { curIndex = byteIndex = 0; layout.Layout.GetCursorPos ((int)TranslateToUTF8Index (layout.LineChars, (uint)index, ref curIndex, ref byteIndex), out strong_pos, out weak_pos); char caretChar = Document.GetCharAt (caretOffset); if (textEditor.Options.ShowSpaces && caretChar == ' ') caretChar = spaceMarkerChar; if (textEditor.Options.ShowTabs && caretChar == '\t') caretChar = tabMarkerChar; SetVisibleCaretPosition (win, caretChar, xPos + (int)(strong_pos.X / Pango.Scale.PangoScale), y); } else if (index == length) { SetVisibleCaretPosition (win, textEditor.Options.ShowEolMarkers ? eolMarkerChar : ' ', (int)((pangoPosition + layout.PangoWidth) / Pango.Scale.PangoScale), y); } } } foreach (TextMarker marker in line.Markers) { marker.Draw (textEditor, win, layout.Layout, false, /*selected*/offset, offset + length, y, xPos, xPos + width); } pangoPosition += layout.PangoWidth; if (layout.IsUncached) layout.Dispose (); }
void DrawLinePart (Cairo.Context cr, DocumentLine line, int lineNumber, int logicalRulerColumn, int offset, int length, ref double pangoPosition, ref bool isSelectionDrawn, double y, double maxX, double _lineHeight) { ISyntaxMode mode = Document.SyntaxMode != null && textEditor.Options.EnableSyntaxHighlighting ? Document.SyntaxMode : new SyntaxMode (Document); int selectionStart; int selectionEnd; if (this.HideSelection) { selectionStart = selectionEnd = -1; } else { GetSelectionOffsets (line, out selectionStart, out selectionEnd); } // ---- new renderer LayoutWrapper layout = CreateLinePartLayout (mode, line, logicalRulerColumn, offset, length, selectionStart, selectionEnd); int lineOffset = line.Offset; double width = layout.PangoWidth / Pango.Scale.PangoScale; double xPos = pangoPosition / Pango.Scale.PangoScale; // The caret line marker must be drawn below the text markers otherwise the're invisible if ((HighlightCaretLine || textEditor.Options.HighlightCaretLine) && Caret.Line == lineNumber) DrawCaretLineMarker (cr, xPos, y, layout.PangoWidth / Pango.Scale.PangoScale, _lineHeight); // if (!(HighlightCaretLine || textEditor.Options.HighlightCaretLine) || Document.GetLine(Caret.Line) != line) { if (BackgroundRenderer == null) { foreach (var bg in layout.BackgroundColors) { int x1, x2; x1 = layout.Layout.IndexToPos (bg.FromIdx).X; x2 = layout.Layout.IndexToPos (bg.ToIdx).X; DrawRectangleWithRuler ( cr, xPos + textEditor.HAdjustment.Value - TextStartPosition, new Cairo.Rectangle ((x1 + pangoPosition) / Pango.Scale.PangoScale, y, (x2 - x1) / Pango.Scale.PangoScale + 1, _lineHeight), bg.Color, true); } } bool drawBg = true; bool drawText = true; LineMetrics metrics = new LineMetrics { LineSegment = line, Layout = layout, SelectionStart = selectionStart, SelectionEnd = selectionEnd, TextStartOffset = offset, TextEndOffset = offset + length, TextRenderStartPosition = xPos, TextRenderEndPosition = xPos + width, LineHeight = _lineHeight, WholeLineWidth = textEditor.Allocation.Width - xPos }; foreach (TextLineMarker marker in line.Markers) { if (!marker.IsVisible) continue; if (marker.DrawBackground (textEditor, cr, y, metrics)) { isSelectionDrawn |= (marker.Flags & TextLineMarkerFlags.DrawsSelection) == TextLineMarkerFlags.DrawsSelection; } var bgMarker = marker as IBackgroundMarker; if (bgMarker != null) { isSelectionDrawn |= (marker.Flags & TextLineMarkerFlags.DrawsSelection) == TextLineMarkerFlags.DrawsSelection; drawText &= bgMarker.DrawBackground (textEditor, cr, metrics.Layout, metrics.SelectionStart, metrics.SelectionEnd, metrics.TextStartOffset, metrics.TextEndOffset, y, metrics.TextRenderStartPosition, metrics.TextRenderEndPosition, ref drawBg); continue; } } if (DecorateLineBg != null) DecorateLineBg (cr, layout, offset, length, xPos, y, selectionStart, selectionEnd); if (!isSelectionDrawn && (layout.StartSet || selectionStart == offset + length) && BackgroundRenderer == null) { double startX; double endX; if (selectionStart != offset + length) { var start = layout.Layout.IndexToPos ((int)layout.SelectionStartIndex); startX = System.Math.Floor (start.X / Pango.Scale.PangoScale); var end = layout.Layout.IndexToPos ((int)layout.SelectionEndIndex); endX = System.Math.Ceiling (end.X / Pango.Scale.PangoScale); } else { startX = width; endX = startX; } if (textEditor.MainSelection.SelectionMode == SelectionMode.Block && startX == endX) { endX = startX + 2; } DrawRectangleWithRuler (cr, xPos + textEditor.HAdjustment.Value - TextStartPosition, new Cairo.Rectangle (xPos + startX, y, endX - startX, _lineHeight), this.SelectionColor.Background, true); } // highlight search results TextSegment firstSearch; int o = offset; uint curIndex = 0, byteIndex = 0; if (textEditor.HighlightSearchPattern) { while (!(firstSearch = GetFirstSearchResult (o, offset + length)).IsInvalid) { double x = pangoPosition; HandleSelection (lineOffset, logicalRulerColumn, selectionStart, selectionEnd, System.Math.Max (lineOffset, firstSearch.Offset), System.Math.Min (lineOffset + line.Length, firstSearch.EndOffset), delegate(int start, int end) { uint startIndex = (uint)(start - offset); uint endIndex = (uint)(end - offset); if (startIndex < endIndex && endIndex <= layout.LineChars.Length) { uint startTranslated = TranslateToUTF8Index (layout.LineChars, startIndex, ref curIndex, ref byteIndex); uint endTranslated = TranslateToUTF8Index (layout.LineChars, endIndex, ref curIndex, ref byteIndex); int l, x1, x2; layout.Layout.IndexToLineX ((int)startTranslated, false, out l, out x1); layout.Layout.IndexToLineX ((int)endTranslated, false, out l, out x2); int w = (int) System.Math.Ceiling ((x2 - x1) / Pango.Scale.PangoScale); int s = (int) System.Math.Floor ((x1 + x) / Pango.Scale.PangoScale); double corner = System.Math.Min (4, width) * textEditor.Options.Zoom; cr.Color = MainSearchResult.IsInvalid || MainSearchResult.Offset != firstSearch.Offset ? ColorStyle.SearchResult.Color : ColorStyle.SearchResultMain.Color; FoldingScreenbackgroundRenderer.DrawRoundRectangle (cr, true, true, s, y, corner, w + 1, LineHeight); cr.Fill (); } }, null); o = System.Math.Max (firstSearch.EndOffset, o + 1); } } cr.Save (); cr.Translate (xPos, y); cr.ShowLayout (layout.Layout); cr.Restore (); if (offset == line.Offset) { DrawIndent (cr, layout, line, xPos, y); } if (textEditor.Options.ShowWhitespaces != ShowWhitespaces.Never && !(BackgroundRenderer != null && textEditor.Options.ShowWhitespaces == ShowWhitespaces.Selection)) DecorateTabsAndSpaces (cr, layout, offset, length, xPos, y, selectionStart, selectionEnd); if (lineNumber == Caret.Line) { int caretOffset = Caret.Offset; if (offset <= caretOffset && caretOffset <= offset + length) { int index = caretOffset - offset; if (Caret.Column > line.Length + 1) { string virtualSpace = ""; var data = textEditor.GetTextEditorData (); if (data.HasIndentationTracker && line.Length == 0) { virtualSpace = this.textEditor.GetTextEditorData ().GetIndentationString (Caret.Location); } if (Caret.Column > line.Length + 1 + virtualSpace.Length) virtualSpace += new string (' ', Caret.Column - line.Length - 1 - virtualSpace.Length); // predit layout already contains virtual space. if (!string.IsNullOrEmpty (textEditor.preeditString)) virtualSpace = ""; LayoutWrapper wrapper = new LayoutWrapper (PangoUtil.CreateLayout (textEditor)); wrapper.LineChars = virtualSpace.ToCharArray (); wrapper.Layout.SetText (virtualSpace); wrapper.Layout.Tabs = tabArray; wrapper.Layout.FontDescription = textEditor.Options.Font; int vy, vx; wrapper.Layout.GetSize (out vx, out vy); var x = ((pangoPosition + vx + layout.PangoWidth) / Pango.Scale.PangoScale); SetVisibleCaretPosition (x, y, x, y); xPos = (pangoPosition + layout.PangoWidth) / Pango.Scale.PangoScale; if (!isSelectionDrawn && (selectionEnd == lineOffset + line.Length) && BackgroundRenderer == null) { double startX; double endX; startX = xPos; endX = (pangoPosition + vx + layout.PangoWidth) / Pango.Scale.PangoScale; DrawRectangleWithRuler (cr, xPos + textEditor.HAdjustment.Value - TextStartPosition, new Cairo.Rectangle (startX, y, endX - startX, _lineHeight), this.SelectionColor.Background, true); } // When drawing virtual space before the selection start paint it as unselected. var virtualSpaceMod = selectionStart < caretOffset ? 0 : virtualSpace.Length; if ((!textEditor.IsSomethingSelected || (selectionStart >= offset && selectionStart != selectionEnd)) && (HighlightCaretLine || textEditor.Options.HighlightCaretLine) && Caret.Line == lineNumber) DrawCaretLineMarker (cr, pangoPosition / Pango.Scale.PangoScale, y, vx / Pango.Scale.PangoScale, _lineHeight); if (DecorateLineBg != null) DecorateLineBg (cr, wrapper, offset, length, xPos, y, selectionStart + virtualSpaceMod, selectionEnd + virtualSpace.Length); switch (textEditor.Options.ShowWhitespaces) { case ShowWhitespaces.Selection: if (textEditor.IsSomethingSelected && (selectionStart < offset || selectionStart == selectionEnd) && BackgroundRenderer == null) DecorateTabsAndSpaces (cr, wrapper, offset, length, xPos, y, selectionStart, selectionEnd + virtualSpace.Length); break; case ShowWhitespaces.Always: DecorateTabsAndSpaces (cr, wrapper, offset, length, xPos, y, selectionStart, selectionEnd + virtualSpace.Length); break; } wrapper.Dispose (); pangoPosition += vx; } else if (index == length && string.IsNullOrEmpty (textEditor.preeditString)) { var x = (pangoPosition + layout.PangoWidth) / Pango.Scale.PangoScale; SetVisibleCaretPosition (x, y, x, y); } else if (index >= 0 && index <= length) { Pango.Rectangle strong_pos, weak_pos; curIndex = byteIndex = 0; int utf8ByteIndex = (int)TranslateToUTF8Index (layout.LineChars, (uint)index, ref curIndex, ref byteIndex); layout.Layout.GetCursorPos (utf8ByteIndex, out strong_pos, out weak_pos); var cx = xPos + (strong_pos.X / Pango.Scale.PangoScale); var cy = y + (strong_pos.Y / Pango.Scale.PangoScale); if (textEditor.preeditCursorCharIndex == 0) { SetVisibleCaretPosition (cx, cy, cx, cy); } else { var preeditIndex = (uint)(index + textEditor.preeditCursorCharIndex); utf8ByteIndex = (int)TranslateToUTF8Index (layout.LineChars, preeditIndex, ref curIndex, ref byteIndex); layout.Layout.GetCursorPos (utf8ByteIndex, out strong_pos, out weak_pos); var pcx = xPos + (strong_pos.X / Pango.Scale.PangoScale); var pcy = y + (strong_pos.Y / Pango.Scale.PangoScale); SetVisibleCaretPosition (pcx, pcy, cx, cy); } } } } foreach (TextLineMarker marker in line.Markers.Where (m => m.IsVisible)) { if (layout.Layout != null) marker.Draw (textEditor, cr, y, metrics); } foreach (var marker in Document.GetTextSegmentMarkersAt (line).Where (m => m.IsVisible)) { if (layout.Layout != null) marker.Draw (textEditor, cr, layout.Layout, false, /*selected*/offset, offset + length, y, xPos, xPos + width); } pangoPosition += layout.PangoWidth; int scaledDown = (int)(pangoPosition / Pango.Scale.PangoScale); pangoPosition = scaledDown * Pango.Scale.PangoScale; if (layout.IsUncached) layout.Dispose (); }
public LayoutDescriptor (LineSegment line, int offset, int length, LayoutWrapper layout, int selectionStart, int selectionEnd) : base(line, offset, length) { this.Layout = layout; this.SelectionStart = selectionStart; this.SelectionEnd = selectionEnd; }
public LayoutWrapper CreateLinePartLayout (ISyntaxMode mode, DocumentLine line, int logicalRulerColumn, int offset, int length, int selectionStart, int selectionEnd) { bool containsPreedit = textEditor.ContainsPreedit (offset, length); LayoutDescriptor descriptor; if (!containsPreedit && layoutDict.TryGetValue (line, out descriptor)) { bool isInvalid; if (descriptor.Equals (line, offset, length, selectionStart, selectionEnd, out isInvalid) && descriptor.Layout != null) { return descriptor.Layout; } descriptor.Dispose (); layoutDict.Remove (line); } var wrapper = new LayoutWrapper (PangoUtil.CreateLayout (textEditor)); wrapper.IsUncached = containsPreedit; if (logicalRulerColumn < 0) logicalRulerColumn = line.GetLogicalColumn (textEditor.GetTextEditorData (), textEditor.Options.RulerColumn); var atts = new FastPangoAttrList (); wrapper.Layout.Alignment = Pango.Alignment.Left; wrapper.Layout.FontDescription = textEditor.Options.Font; wrapper.Layout.Tabs = tabArray; if (textEditor.Options.WrapLines) { wrapper.Layout.Wrap = Pango.WrapMode.WordChar; wrapper.Layout.Width = (int)((textEditor.Allocation.Width - XOffset - TextStartPosition) * Pango.Scale.PangoScale); } StringBuilder textBuilder = new StringBuilder (); var chunks = GetCachedChunks (mode, Document, textEditor.ColorStyle, line, offset, length); wrapper.Chunks = chunks; foreach (var chunk in chunks) { try { textBuilder.Append (Document.GetTextAt (chunk)); } catch { Console.WriteLine (chunk); } } int lineOffset = line.Offset; string lineText = textBuilder.ToString (); uint preeditLength = 0; if (containsPreedit) { if (textEditor.GetTextEditorData ().IsCaretInVirtualLocation) { lineText = textEditor.GetTextEditorData ().GetIndentationString (textEditor.Caret.Location) + textEditor.preeditString; } else { lineText = lineText.Insert (textEditor.preeditOffset - offset, textEditor.preeditString); } preeditLength = (uint)textEditor.preeditString.Length; } char[] lineChars = lineText.ToCharArray (); //int startOffset = offset, endOffset = offset + length; uint curIndex = 0, byteIndex = 0; uint curChunkIndex = 0, byteChunkIndex = 0; uint oldEndIndex = 0; foreach (Chunk chunk in chunks) { ChunkStyle chunkStyle = chunk != null ? textEditor.ColorStyle.GetChunkStyle (chunk) : null; foreach (TextLineMarker marker in line.Markers) chunkStyle = marker.GetStyle (chunkStyle); if (chunkStyle != null) { //startOffset = chunk.Offset; //endOffset = chunk.EndOffset; uint startIndex = (uint)(oldEndIndex); uint endIndex = (uint)(startIndex + chunk.Length); oldEndIndex = endIndex; var markers = Document.GetTextSegmentMarkersAt (line).Where (m => m.IsVisible).ToArray (); HandleSelection (lineOffset, logicalRulerColumn, selectionStart, selectionEnd, chunk.Offset, chunk.EndOffset, delegate(int start, int end) { if (containsPreedit) { if (textEditor.preeditOffset < start) start += (int)preeditLength; if (textEditor.preeditOffset < end) end += (int)preeditLength; } var si = TranslateToUTF8Index (lineChars, (uint)(startIndex + start - chunk.Offset), ref curIndex, ref byteIndex); var ei = TranslateToUTF8Index (lineChars, (uint)(startIndex + end - chunk.Offset), ref curIndex, ref byteIndex); var color = ColorStyle.GetForeground (chunkStyle); foreach (var marker in markers) { var chunkMarker = marker as IChunkMarker; if (chunkMarker == null) continue; chunkMarker.ChangeForeColor (textEditor, chunk, ref color); } atts.AddForegroundAttribute ((HslColor)color, si, ei); if (!chunkStyle.TransparentBackground && GetPixel (ColorStyle.PlainText.Background) != GetPixel (chunkStyle.Background)) { wrapper.AddBackground (chunkStyle.Background, (int)si, (int)ei); } else if (chunk.SpanStack != null && ColorStyle != null) { foreach (var span in chunk.SpanStack) { if (span == null || string.IsNullOrEmpty (span.Color)) continue; var spanStyle = ColorStyle.GetChunkStyle (span.Color); if (spanStyle != null && !spanStyle.TransparentBackground && GetPixel (ColorStyle.PlainText.Background) != GetPixel (spanStyle.Background)) { wrapper.AddBackground (spanStyle.Background, (int)si, (int)ei); break; } } } }, delegate(int start, int end) { if (containsPreedit) { if (textEditor.preeditOffset < start) start += (int)preeditLength; if (textEditor.preeditOffset < end) end += (int)preeditLength; } var si = TranslateToUTF8Index (lineChars, (uint)(startIndex + start - chunk.Offset), ref curIndex, ref byteIndex); var ei = TranslateToUTF8Index (lineChars, (uint)(startIndex + end - chunk.Offset), ref curIndex, ref byteIndex); var color = !SelectionColor.TransparentForeground ? SelectionColor.Foreground : ColorStyle.GetForeground (chunkStyle); foreach (var marker in markers) { var chunkMarker = marker as IChunkMarker; if (chunkMarker == null) continue; chunkMarker.ChangeForeColor (textEditor, chunk, ref color); } atts.AddForegroundAttribute ((HslColor)color, si, ei); if (!wrapper.StartSet) wrapper.SelectionStartIndex = (int)si; wrapper.SelectionEndIndex = (int)ei; }); var translatedStartIndex = TranslateToUTF8Index (lineChars, (uint)startIndex, ref curChunkIndex, ref byteChunkIndex); var translatedEndIndex = TranslateToUTF8Index (lineChars, (uint)endIndex, ref curChunkIndex, ref byteChunkIndex); if (chunkStyle.FontWeight != Xwt.Drawing.FontWeight.Normal) atts.AddWeightAttribute ((Pango.Weight)chunkStyle.FontWeight, translatedStartIndex, translatedEndIndex); if (chunkStyle.FontStyle != Xwt.Drawing.FontStyle.Normal) atts.AddStyleAttribute ((Pango.Style)chunkStyle.FontStyle, translatedStartIndex, translatedEndIndex); if (chunkStyle.Underline) atts.AddUnderlineAttribute (Pango.Underline.Single, translatedStartIndex, translatedEndIndex); } } if (containsPreedit) { var si = TranslateToUTF8Index (lineChars, (uint)(textEditor.preeditOffset - offset), ref curIndex, ref byteIndex); var ei = TranslateToUTF8Index (lineChars, (uint)(textEditor.preeditOffset - offset + preeditLength), ref curIndex, ref byteIndex); if (textEditor.GetTextEditorData ().IsCaretInVirtualLocation) { uint len = (uint)textEditor.GetTextEditorData ().GetIndentationString (textEditor.Caret.Location).Length; si += len; ei += len; } atts.AddForegroundAttribute ((HslColor)ColorStyle.PlainText.Foreground, si, ei); var hasBackground = wrapper.BackgroundColors.Any (bg => bg.FromIdx <= si && bg.ToIdx >= ei); if (hasBackground) atts.AddBackgroundAttribute ((HslColor)ColorStyle.PlainText.Background, si, ei); atts.InsertOffsetList (textEditor.preeditAttrs, si, ei); } wrapper.LineChars = lineChars; wrapper.Layout.SetText (lineText); wrapper.IndentSize = 0; for (int i = 0; i < lineChars.Length; i++) { char ch = lineChars [i]; if (ch == ' ') { wrapper.IndentSize ++; } else if (ch == '\t') { wrapper.IndentSize = GetNextTabstop (textEditor.GetTextEditorData (), wrapper.IndentSize); } else { break; } } var nextLine = line.NextLine; wrapper.EolSpanStack = nextLine != null ? nextLine.StartSpan : null; atts.AssignTo (wrapper.Layout); atts.Dispose (); int w, h; wrapper.Layout.GetSize (out w, out h); wrapper.PangoWidth = w; selectionStart = System.Math.Max (line.Offset - 1, selectionStart); selectionEnd = System.Math.Min (line.EndOffsetIncludingDelimiter + 1, selectionEnd); descriptor = new LayoutDescriptor (line, offset, length, wrapper, selectionStart, selectionEnd); if (!containsPreedit) layoutDict [line] = descriptor; //textEditor.GetTextEditorData ().HeightTree.SetLineHeight (line.LineNumber, System.Math.Max (LineHeight, System.Math.Floor (h / Pango.Scale.PangoScale))); return wrapper; }
LayoutWrapper GetCachedLayout (LineSegment line, int offset, int length, int selectionStart, int selectionEnd, Action<LayoutWrapper> createNew) { bool containsPreedit = offset <= textEditor.preeditOffset && textEditor.preeditOffset <= offset + length; LayoutDescriptor descriptor; if (!containsPreedit && layoutDict.TryGetValue (line, out descriptor)) { bool isInvalid; if (descriptor.Equals (line, offset, length, selectionStart, selectionEnd, out isInvalid)) { return descriptor.Layout; } descriptor.Dispose (); layoutDict.Remove (line); } var wrapper = new LayoutWrapper (PangoUtil.CreateLayout (textEditor)); wrapper.IsUncached = containsPreedit; createNew (wrapper); selectionStart = System.Math.Max (line.Offset - 1, selectionStart); selectionEnd = System.Math.Min (line.EndOffset + 1, selectionEnd); descriptor = new LayoutDescriptor (line, offset, length, wrapper, selectionStart, selectionEnd); if (!containsPreedit) layoutDict[line] = descriptor; return wrapper; }