void DrawTextLine (Cairo.Context g, IReadonlyTextDocument document, int lineNumber, ref int y)
		{
			using (var drawingLayout = new Pango.Layout (this.PangoContext)) {
				drawingLayout.FontDescription = fontDescription;
				var line = document.GetLine (lineNumber);
				var correctedIndentLength = CorrectIndent (document, line, indentLength);
				drawingLayout.SetText (document.GetTextAt (line.Offset + Math.Min (correctedIndentLength, line.Length), Math.Max (0, line.Length - correctedIndentLength)));
				g.Save ();
				g.Translate (textBorder, y);
				g.ShowLayout (drawingLayout);
				g.Restore ();
				y += lineHeight;
			}
		}
		protected internal override void Draw (Cairo.Context cr, Cairo.Rectangle area, DocumentLine line, int lineNr, double x, double y, double _lineHeight)
		{
//			double xStart = System.Math.Max (area.X, XOffset);
//			xStart = System.Math.Max (0, xStart);
			var correctedXOffset = System.Math.Floor (XOffset) - 1;
			var lineArea = new Cairo.Rectangle (correctedXOffset, y, textEditor.Allocation.Width - correctedXOffset, _lineHeight);
			int width, height;
			double pangoPosition = (x - textEditor.HAdjustment.Value + TextStartPosition) * Pango.Scale.PangoScale;

			defaultBgColor = Document.ReadOnly ? ColorStyle.BackgroundReadOnly.Color : ColorStyle.PlainText.Background;

			// Draw the default back color for the whole line. Colors other than the default
			// background will be drawn when rendering the text chunks.
			if (BackgroundRenderer == null)
				DrawRectangleWithRuler (cr, x, lineArea, defaultBgColor, true);
			bool isSelectionDrawn = false;

			// Check if line is beyond the document length
			if (line == null) {
				var marker = Document.GetExtendingTextMarker (lineNr);
				if (marker != null)
					marker.Draw (textEditor, cr, lineNr, lineArea);
				return;
			}
			
			IEnumerable<FoldSegment> foldings = Document.GetStartFoldings (line);
			int offset = line.Offset;
			int caretOffset = Caret.Offset;
			bool isEolFolded = false;
			restart:
			int logicalRulerColumn = line.GetLogicalColumn (textEditor.GetTextEditorData (), textEditor.Options.RulerColumn);

			if ((HighlightCaretLine || textEditor.Options.HighlightCaretLine) && Caret.Line == lineNr)
				DrawCaretLineMarker (cr, x, y, TextStartPosition, _lineHeight);

			foreach (FoldSegment folding in foldings) {
				int foldOffset = folding.StartLine.Offset + folding.Column - 1;
				if (foldOffset < offset)
					continue;

				if (folding.IsFolded) {
					
					DrawLinePart (cr, line, lineNr, logicalRulerColumn, offset, foldOffset - offset, ref pangoPosition, ref isSelectionDrawn, y, area.X + area.Width, _lineHeight);
					
					offset = folding.EndLine.Offset + folding.EndColumn - 1;
					markerLayout.SetText (folding.Description);
					markerLayout.GetSize (out width, out height);
					
					bool isFoldingSelected = !this.HideSelection && textEditor.IsSomethingSelected && textEditor.SelectionRange.Contains (folding.Segment);
					double pixelX = 0.5 + System.Math.Floor (pangoPosition / Pango.Scale.PangoScale);
					double foldXMargin = foldMarkerXMargin * textEditor.Options.Zoom;
					double pixelWidth = System.Math.Floor ((pangoPosition + width) / Pango.Scale.PangoScale - pixelX + foldXMargin * 2);
					var foldingRectangle = new Cairo.Rectangle (
						pixelX, 
						y, 
						pixelWidth, 
						this.LineHeight);

					if (BackgroundRenderer == null && isFoldingSelected) {
						cr.Color = SelectionColor.Background;
						cr.Rectangle (foldingRectangle);
						cr.Fill ();
					}

					if (isFoldingSelected && SelectionColor.TransparentForeground) {
						cr.Color = ColorStyle.CollapsedText.Foreground;
					} else {
						cr.Color = isFoldingSelected ? SelectionColor.Foreground : ColorStyle.CollapsedText.Foreground;
					}
					var boundingRectangleHeight = foldingRectangle.Height - 1;
					var boundingRectangleY = System.Math.Floor (foldingRectangle.Y + (foldingRectangle.Height - boundingRectangleHeight) / 2);
					RoundedRectangle (cr,
					                 System.Math.Floor (foldingRectangle.X) + 0.5,
					                 boundingRectangleY + 0.5,
					                 System.Math.Floor (foldingRectangle.Width - cr.LineWidth),
					                 System.Math.Floor (boundingRectangleHeight - cr.LineWidth),
					                 LineHeight / 8, CairoCorners.All, false);
					cr.Stroke ();
					
					cr.Save ();
					cr.Translate (
						pangoPosition / Pango.Scale.PangoScale + foldXMargin,
						System.Math.Floor (boundingRectangleY + (boundingRectangleHeight - System.Math.Floor (height / Pango.Scale.PangoScale)) / 2));
					cr.ShowLayout (markerLayout);
					cr.Restore ();

					if (caretOffset == foldOffset && !string.IsNullOrEmpty (folding.Description)) {
						var cx = (int)(pangoPosition / Pango.Scale.PangoScale);
						SetVisibleCaretPosition (cx, y, cx, y);
					}
					pangoPosition += foldingRectangle.Width * Pango.Scale.PangoScale;
					if (caretOffset == foldOffset + folding.Length && !string.IsNullOrEmpty (folding.Description)) {
						var cx = (int)(pangoPosition / Pango.Scale.PangoScale);
						SetVisibleCaretPosition (cx, y, cx, y);
					}

					if (folding.EndLine != line) {
						line = folding.EndLine;
						lineNr = line.LineNumber;
						foldings = Document.GetStartFoldings (line);
						isEolFolded = line.Length <= folding.EndColumn;
						goto restart;
					}
					isEolFolded = line.Length <= folding.EndColumn;
				}
			}
			
			// Draw remaining line - must be called for empty line parts as well because the caret may be at this positon
			// and the caret position is calculated in DrawLinePart.
			if (line.EndOffsetIncludingDelimiter - offset >= 0) {
				DrawLinePart (cr, line, lineNr, logicalRulerColumn, offset, line.Offset + line.Length - offset, ref pangoPosition, ref isSelectionDrawn, y, area.X + area.Width, _lineHeight);
			}

			bool isEolSelected = !this.HideSelection && textEditor.IsSomethingSelected && textEditor.SelectionMode == SelectionMode.Normal && textEditor.SelectionRange.Contains (line.Offset + line.Length);
			var lx = (int)(pangoPosition / Pango.Scale.PangoScale);
			lineArea = new Cairo.Rectangle (lx,
				lineArea.Y,
				textEditor.Allocation.Width - lx,
				lineArea.Height);

			if (textEditor.SelectionMode == SelectionMode.Block && textEditor.IsSomethingSelected && textEditor.SelectionRange.Contains (line.Offset + line.Length)) {
				DocumentLocation start = textEditor.MainSelection.Anchor;
				DocumentLocation end = textEditor.MainSelection.Lead;
				DocumentLocation visStart = textEditor.LogicalToVisualLocation (start);
				DocumentLocation visEnd = textEditor.LogicalToVisualLocation (end);
				
				double x1 = this.ColumnToX (line, visStart.Column);
				double x2 = this.ColumnToX (line, visEnd.Column);
				if (x1 > x2) {
					var tmp = x1;
					x1 = x2;
					x2 = tmp;
				}
				x1 += correctedXOffset - textEditor.HAdjustment.Value;
				x2 += correctedXOffset - textEditor.HAdjustment.Value;

				if (x2 > lineArea.X && BackgroundRenderer == null)  {
					if (x1 - lineArea.X > 0) {
						DrawRectangleWithRuler (cr, x, new Cairo.Rectangle (lineArea.X, lineArea.Y, x1 - lineArea.X, lineArea.Height), defaultBgColor, false);
						lineArea = new Cairo.Rectangle (x1, lineArea.Y, lineArea.Width, lineArea.Height);
					}
					DrawRectangleWithRuler (cr, x, new Cairo.Rectangle (lineArea.X, lineArea.Y, x2 - lineArea.X, lineArea.Height), this.SelectionColor.Background, false);
					lineArea = new Cairo.Rectangle (x2, lineArea.Y, textEditor.Allocation.Width - lineArea.X, lineArea.Height);
				}
			}

			if (!isSelectionDrawn && BackgroundRenderer == null) {
				if (isEolSelected) {
					// prevent "gaps" in the selection drawing ('fuzzy' lines problem)
					var eolStartX = System.Math.Floor (pangoPosition / Pango.Scale.PangoScale);
					lineArea = new Cairo.Rectangle (
						eolStartX,
						lineArea.Y,
						textEditor.Allocation.Width - eolStartX,
						lineArea.Height);
					DrawRectangleWithRuler (cr, x, lineArea, this.SelectionColor.Background, false);
					if (line.Length == 0)
						DrawIndent (cr, GetLayout (line), line, lx, y);
				} else if (!(HighlightCaretLine || textEditor.Options.HighlightCaretLine) || Caret.Line != lineNr) {
					LayoutWrapper wrapper = GetLayout (line);
					if (wrapper.EolSpanStack != null) {
						foreach (var span in wrapper.EolSpanStack) {
							var spanStyle = textEditor.ColorStyle.GetChunkStyle (span.Color);
							if (spanStyle == null)
								continue;
							if (!spanStyle.TransparentBackground && GetPixel (ColorStyle.PlainText.Background) != GetPixel (spanStyle.Background)) {
								DrawRectangleWithRuler (cr, x, lineArea, spanStyle.Background, false);
								break;
							}
						}
					}
				} else {
					double xPos = pangoPosition / Pango.Scale.PangoScale;
					DrawCaretLineMarker (cr, xPos, y, lineArea.X + lineArea.Width - xPos, _lineHeight);
				}
			}
			
			if (textEditor.Options.ShowWhitespaces != ShowWhitespaces.Never) {
				if (!isEolFolded && isEolSelected || textEditor.Options.ShowWhitespaces == ShowWhitespaces.Always)
					if (!(BackgroundRenderer != null && textEditor.Options.ShowWhitespaces == ShowWhitespaces.Selection))
						DrawEolMarker (cr, line, isEolSelected, pangoPosition / Pango.Scale.PangoScale, y);
			}

			var extendingMarker = Document.GetExtendingTextMarker (lineNr);
			if (extendingMarker != null)
				extendingMarker.Draw (textEditor, cr, lineNr, lineArea);

			if (BackgroundRenderer == null) {
				var metrics = new EndOfLineMetrics {
					LineSegment = line,
					TextRenderEndPosition = TextStartPosition + pangoPosition / Pango.Scale.PangoScale,
					LineHeight = _lineHeight
				};
				foreach (var marker in line.Markers) {
					marker.DrawAfterEol (textEditor, cr, y, metrics);
				}
			}

			lastLineRenderWidth = pangoPosition / Pango.Scale.PangoScale;
			if (textEditor.HAdjustment.Value > 0) {
				cr.LineWidth = textEditor.Options.Zoom;
				for (int i = 0; i < verticalShadowAlphaTable.Length; i++) {
					cr.Color = new Cairo.Color (0, 0, 0, 1 - verticalShadowAlphaTable[i]);
					cr.MoveTo (x + i * cr.LineWidth + 0.5, y);
					cr.LineTo (x + i * cr.LineWidth + 0.5, y + 1 + _lineHeight);
					cr.Stroke ();
				}
			}
		}
		public override void DrawAfterEol (TextEditor textEditor, Cairo.Context g, double y, EndOfLineMetrics metrics)
		{
			if (!IsVisible)
				return;
			EnsureLayoutCreated (editor);
			int errorCounterWidth = 0, eh = 0;
			if (errorCountLayout != null) {
				errorCountLayout.GetPixelSize (out errorCounterWidth, out eh);
				errorCounterWidth = Math.Max (15, Math.Max (errorCounterWidth + 3, (int)(editor.LineHeight * 3 / 4)));
			}

			var sx = metrics.TextRenderEndPosition;
			var width = LayoutWidth + errorCounterWidth + editor.LineHeight;
			var drawLayout = layouts[0].Layout;
			int ex = 0 , ey = 0;
			bool customLayout = true; //sx + width > editor.Allocation.Width;
			bool hideText = false;
			bubbleIsReduced = customLayout;
			var showErrorCount = errorCounterWidth > 0 && errorCountLayout != null;
			if (customLayout) {
				width = editor.Allocation.Width - sx;
				string text = layouts[0].Layout.Text;
				drawLayout = new Pango.Layout (editor.PangoContext);
				drawLayout.FontDescription = cache.fontDescription;
				var paintWidth = (width - errorCounterWidth - editor.LineHeight + 4);
				var minWidth = Math.Max (17, errorCounterWidth) + editor.LineHeight;
				if (paintWidth < minWidth) {
					hideText = true;
					drawLayout.SetMarkup ("<span weight='heavy'>···</span>");
					width = minWidth;
					showErrorCount = false;
					sx = Math.Min (sx, editor.Allocation.Width - width);
				} else {
					drawLayout.Ellipsize = Pango.EllipsizeMode.End;
					drawLayout.Width = (int)(paintWidth * Pango.Scale.PangoScale);
					drawLayout.SetText (text);
					int w2, h2;
					drawLayout.GetPixelSize (out w2, out h2);
					width = w2 + errorCounterWidth + editor.LineHeight;
				}
			}
			bubbleDrawX = sx - editor.TextViewMargin.XOffset;
			bubbleDrawY = y;
			bubbleWidth = width;

			var bubbleHeight = editor.LineHeight - 1;
			g.RoundedRectangle (sx, y + 1, width, bubbleHeight, editor.LineHeight / 2 - 1);
			g.SetSourceColor (TagColor.Color);
			g.Fill ();

			// Draw error count icon
			if (showErrorCount) {
				var errorCounterHeight = bubbleHeight - 2;
				var errorCounterX = sx + width - errorCounterWidth - 3;
				var errorCounterY = y + 1 + (bubbleHeight - errorCounterHeight) / 2;

				g.RoundedRectangle (
					errorCounterX - 1, 
					errorCounterY - 1, 
					errorCounterWidth + 2, 
					errorCounterHeight + 2, 
					editor.LineHeight / 2 - 3
				);

				g.SetSourceColor (new Cairo.Color (0, 0, 0, 0.081));
				g.Fill ();

				g.RoundedRectangle (
					errorCounterX, 
					errorCounterY, 
					errorCounterWidth, 
					errorCounterHeight, 
					editor.LineHeight / 2 - 3
				);
				using (var lg = new Cairo.LinearGradient (errorCounterX, errorCounterY, errorCounterX, errorCounterY + errorCounterHeight)) {
					lg.AddColorStop (0, CounterColor.Color);
					lg.AddColorStop (1, CounterColor.Color.AddLight (-0.1));
					g.Pattern = lg;
					g.Fill ();
				}

				g.Save ();

				int ew;
				errorCountLayout.GetPixelSize (out ew, out eh);

				g.Translate (
					errorCounterX + (errorCounterWidth - ew) / 2,
					errorCounterY + (errorCounterHeight - eh) / 2
				);
				g.SetSourceColor (CounterColor.SecondColor);
				g.ShowLayout (errorCountLayout);
				g.Restore ();
			}

			// Draw label text
			if (!showErrorCount || !hideText) {
				g.Save ();
				g.Translate (sx + editor.LineHeight / 2, y + (editor.LineHeight - layouts [0].Height) / 2 + 1);

				// draw shadow
				g.SetSourceColor (MessageBubbleCache.ShadowColor);
				g.ShowLayout (drawLayout);
				g.Translate (0, -1);

				g.SetSourceColor (TagColor.SecondColor);
				g.ShowLayout (drawLayout);
				g.Restore ();
			}

			if (customLayout)
				drawLayout.Dispose ();

		}
		void DrawLinePart (Cairo.Context cr, DocumentLine line, int lineNumber, int logicalRulerColumn, int offset, int length, ref double position, ref bool isSelectionDrawn, double y, double maxX, double _lineHeight)
		{
			ISyntaxMode mode = Document.SyntaxMode != null && textEditor.Options.EnableSyntaxHighlighting ? Document.SyntaxMode : new SyntaxMode (Document);
			int selectionStartOffset;
			int selectionEndOffset;
			if (this.HideSelection) {
				selectionStartOffset = selectionEndOffset = -1;
			} else {
				GetSelectionOffsets (line, out selectionStartOffset, out selectionEndOffset);
			}

			// ---- new renderer
			LayoutWrapper layout = CreateLinePartLayout (mode, line, logicalRulerColumn, offset, length, selectionStartOffset, selectionEndOffset);
			int lineOffset = line.Offset;
			double width = layout.Width;
			double xPos = position;

			// The caret line marker must be drawn below the text markers otherwise the're invisible
			if ((HighlightCaretLine || textEditor.GetTextEditorData ().HighlightCaretLine) && Caret.Line == lineNumber)
				DrawCaretLineMarker (cr, xPos, y, layout.Width, _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 / Pango.Scale.PangoScale + position, y, (x2 - x1) / Pango.Scale.PangoScale + 1, _lineHeight),
						bg.Color, true);
				}
			}

			var metrics  = new LineMetrics {
				LineSegment = line,
				Layout = layout,

				SelectionStart = selectionStartOffset,
				SelectionEnd = selectionEndOffset,

				TextStartOffset = offset,
				TextEndOffset = offset + length,

				TextRenderStartPosition = xPos,
				TextRenderEndPosition = xPos + width,

				LineHeight = _lineHeight,
				WholeLineWidth = textEditor.Allocation.Width - xPos,

				LineYRenderStartPosition = y
			};

			foreach (TextLineMarker marker in line.Markers) {
				if (!marker.IsVisible)
					continue;

				if (marker.DrawBackground (textEditor, cr, metrics)) {
					isSelectionDrawn |= (marker.Flags & TextLineMarkerFlags.DrawsSelection) == TextLineMarkerFlags.DrawsSelection;
				}
			}

			var textSegmentMarkers = TextDocument.OrderTextSegmentMarkersByInsertion (Document.GetTextSegmentMarkersAt (line).Where (m => m.IsVisible)).ToArray ();
			foreach (var marker in textSegmentMarkers) {
				if (layout.Layout != null)
					marker.DrawBackground (textEditor, cr, metrics, offset, offset + length);
			}


			if (DecorateLineBg != null)
				DecorateLineBg (cr, layout, offset, length, xPos, y, selectionStartOffset, selectionEndOffset);
			

			if (!isSelectionDrawn && (layout.StartSet || selectionStartOffset == offset + length) && BackgroundRenderer == null) {
				double startX;
				int startY;
				double endX;
				int endY;
				if (selectionStartOffset != offset + length) {
					var start = layout.Layout.IndexToPos (layout.SelectionStartIndex);
					startX = System.Math.Floor (start.X / Pango.Scale.PangoScale);
					startY = (int)(y + System.Math.Floor (start.Y / Pango.Scale.PangoScale));

					var end = layout.Layout.IndexToPos (layout.SelectionEndIndex);
					endX = System.Math.Ceiling (end.X / Pango.Scale.PangoScale);
					endY = (int)(y + System.Math.Ceiling (end.Y / Pango.Scale.PangoScale));
				} else {
					startY = endY = (int)y;
					startX = width;
					endX = startX;
				}

				if (textEditor.MainSelection.SelectionMode == SelectionMode.Block && startX == endX) {
					endX = startX + 2;
				}
				if (startY == endY) {
					DrawRectangleWithRuler (
						cr,
						xPos + textEditor.HAdjustment.Value - TextStartPosition,
						new Cairo.Rectangle (xPos + startX, startY, endX - startX, LineHeight),
						this.SelectionColor.Background,
						true
						);
				} else {
					DrawRectangleWithRuler (
						cr,
						xPos + textEditor.HAdjustment.Value - TextStartPosition,
						new Cairo.Rectangle (xPos + startX, startY, textEditor.Allocation.Width - xPos - startX, LineHeight),
						this.SelectionColor.Background,
						true
					);

					if (endY - startY > LineHeight) {
						DrawRectangleWithRuler (
							cr,
							xPos,
							new Cairo.Rectangle (xPos, startY + LineHeight, textEditor.Allocation.Width - xPos, endY - startY - LineHeight),
							this.SelectionColor.Background,
							true
						);
					}

					DrawRectangleWithRuler (
						cr,
						xPos,
						new Cairo.Rectangle (xPos, endY, endX, 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 = position;
					HandleSelection (lineOffset, logicalRulerColumn, selectionStartOffset, selectionEndOffset, 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 / Pango.Scale.PangoScale + x);
							double corner = System.Math.Min (4, width) * textEditor.Options.Zoom;

							cr.SetSourceColor (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, xPos, y, selectionStartOffset, selectionEndOffset);


			if (textEditor.IsSomethingSelected && !isSelectionDrawn && BackgroundRenderer == null) {
				if (lineNumber == textEditor.MainSelection.End.Line && textEditor.MainSelection.End.Column > line.Length + 1) {
					using (var wrapper = GetVirtualSpaceLayout (line, textEditor.MainSelection.End)) {
						double startX;
						double endX;
						startX = xPos;
						endX = position + wrapper.Width + layout.Width;
						DrawRectangleWithRuler (cr, xPos + textEditor.HAdjustment.Value - TextStartPosition, new Cairo.Rectangle (startX, y, endX - startX, _lineHeight), this.SelectionColor.Background, true);

						if (lineNumber == Caret.Line &&
						    textEditor.Options.ShowWhitespaces == ShowWhitespaces.Selection &&
						    textEditor.IsSomethingSelected &&
						    (selectionStartOffset < offset || selectionStartOffset == selectionEndOffset) &&
						    BackgroundRenderer == null) {
							DecorateTabsAndSpaces (cr, wrapper, offset, xPos, y, selectionStartOffset, selectionEndOffset + wrapper.LineChars.Length);
						}
					}
				}
				
			}

			if (lineNumber == Caret.Line) {
				int caretOffset = Caret.Offset;
				if (offset <= caretOffset && caretOffset <= offset + length) {
					int index = caretOffset - offset;
					//This if means we have temporary indent
					if (Caret.Column > line.Length + 1) {
						using (var wrapper = GetVirtualSpaceLayout (line, Caret.Location)) {
							var x = (position + wrapper.Width) + layout.Width;
							SetVisibleCaretPosition (x, y, x, y);
							xPos = position + layout.Width;


							// When drawing virtual space before the selection start paint it as unselected.
							var virtualSpaceMod = selectionStartOffset < caretOffset ? 0 : wrapper.LineChars.Length;

							if ((!textEditor.IsSomethingSelected || (selectionStartOffset >= offset && selectionStartOffset != selectionEndOffset)) && (HighlightCaretLine || textEditor.Options.HighlightCaretLine) && Caret.Line == lineNumber)
								DrawCaretLineMarker (cr, position, y, wrapper.Width, _lineHeight);

							if (DecorateLineBg != null)
								DecorateLineBg (cr, wrapper, offset, length, xPos, y, selectionStartOffset + virtualSpaceMod, selectionEndOffset + wrapper.LineChars.Length);

							if (textEditor.Options.ShowWhitespaces == ShowWhitespaces.Always) {
								DecorateTabsAndSpaces (cr, wrapper, offset, xPos, y, selectionStartOffset, selectionEndOffset + wrapper.LineChars.Length);
							}
						}
					} else if (index == length && string.IsNullOrEmpty (textEditor.preeditString)) {
						var x = position + layout.Width;
						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, metrics);
			}

			foreach (var marker in textSegmentMarkers) {
				if (layout.Layout != null)
					marker.Draw (textEditor, cr, metrics, offset, offset + length);
			}
			position += System.Math.Floor (layout.LastLineWidth);

			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 ();
		}
Example #6
0
		protected internal override void Draw (Cairo.Context cr, Cairo.Rectangle area, LineSegment line, int lineNr, double x, double y, double _lineHeight)
		{
//			double xStart = System.Math.Max (area.X, XOffset);
//			xStart = System.Math.Max (0, xStart);
			var lineArea = new Cairo.Rectangle (XOffset - 1, y, textEditor.Allocation.Width - XOffset + 1, _lineHeight);
			int width, height;
			double pangoPosition = (x - textEditor.HAdjustment.Value + TextStartPosition) * Pango.Scale.PangoScale;

			defaultBgColor = Document.ReadOnly ? ColorStyle.ReadOnlyTextBg : ColorStyle.Default.CairoBackgroundColor;

			// Draw the default back color for the whole line. Colors other than the default
			// background will be drawn when rendering the text chunks.
			DrawRectangleWithRuler (cr, x, lineArea, defaultBgColor, true);
			bool isSelectionDrawn = false;

			if (BackgroundRenderer != null)
				BackgroundRenderer.Draw (cr, area, line, x, y, _lineHeight);

			// Check if line is beyond the document length
			if (line == null) {
				if (textEditor.Options.ShowInvalidLines)
					DrawInvalidLineMarker (cr, pangoPosition / Pango.Scale.PangoScale, y);
				var marker = Document.GetExtendingTextMarker (lineNr);
				if (marker != null)
					marker.Draw (textEditor, cr, lineNr, lineArea);
				return;
			}
			
			IEnumerable<FoldSegment> foldings = Document.GetStartFoldings (line);
			int offset = line.Offset;
			int caretOffset = Caret.Offset;
			bool isEolFolded = false;
			restart:
			int logicalRulerColumn = line.GetLogicalColumn (textEditor.GetTextEditorData (), textEditor.Options.RulerColumn);
			
			foreach (FoldSegment folding in foldings) {
				int foldOffset = folding.StartLine.Offset + folding.Column - 1;
				if (foldOffset < offset)
					continue;

				if (folding.IsFolded) {
					
					DrawLinePart (cr, line, lineNr, logicalRulerColumn, offset, foldOffset - offset, ref pangoPosition, ref isSelectionDrawn, y, area.X + area.Width);
					
					offset = folding.EndLine.Offset + folding.EndColumn;
					markerLayout.SetText (folding.Description);
					markerLayout.GetSize (out width, out height);
					
					bool isFoldingSelected = !this.HideSelection && textEditor.IsSomethingSelected && textEditor.SelectionRange.Contains (folding.Segment);
					double pixelX = pangoPosition / Pango.Scale.PangoScale;
					double pixelWidth = (pangoPosition + width) / Pango.Scale.PangoScale - pixelX;
					var foldingRectangle = new Cairo.Rectangle (pixelX + 0.5, y + 0.5, pixelWidth - cr.LineWidth, this.LineHeight - cr.LineWidth);
					if (BackgroundRenderer == null) {
						cr.Color = isFoldingSelected ? SelectionColor.CairoBackgroundColor : defaultBgColor;
						cr.Rectangle (foldingRectangle);
						cr.Fill ();
					}
					
					cr.Color = isFoldingSelected ? SelectionColor.CairoColor : ColorStyle.FoldLine.CairoColor;
					cr.Rectangle (foldingRectangle);
					cr.Stroke ();
					
					cr.Save ();
					cr.Translate (pangoPosition / Pango.Scale.PangoScale, y);
					cr.Color = isFoldingSelected ? SelectionColor.CairoColor : ColorStyle.FoldLine.CairoColor;
					cr.ShowLayout (markerLayout);
					cr.Restore ();
					

					if (caretOffset == foldOffset && !string.IsNullOrEmpty (folding.Description))
						SetVisibleCaretPosition ((int)(pangoPosition / Pango.Scale.PangoScale), y);
					pangoPosition += width;
					if (caretOffset == foldOffset + folding.Length && !string.IsNullOrEmpty (folding.Description))
						SetVisibleCaretPosition ((int)(pangoPosition / Pango.Scale.PangoScale), y);

					if (folding.EndLine != line) {
						line = folding.EndLine;
						lineNr = Document.OffsetToLineNumber (line.Offset);
						foldings = Document.GetStartFoldings (line);
						isEolFolded = line.Length <= folding.EndColumn;
						goto restart;
					}
					isEolFolded = line.Length <= folding.EndColumn;
				}
			}
			
			// Draw remaining line - must be called for empty line parts as well because the caret may be at this positon
			// and the caret position is calculated in DrawLinePart.
			if (line.EndOffsetIncludingDelimiter - offset >= 0)
				DrawLinePart (cr, line, lineNr, logicalRulerColumn, offset, line.Offset + line.Length - offset, ref pangoPosition, ref isSelectionDrawn, y, area.X + area.Width);
			
			bool isEolSelected = !this.HideSelection && textEditor.IsSomethingSelected && textEditor.SelectionMode == SelectionMode.Normal && textEditor.SelectionRange.Contains (line.Offset + line.Length);
			lineArea = new Cairo.Rectangle (pangoPosition / Pango.Scale.PangoScale,
				lineArea.Y,
				textEditor.Allocation.Width - pangoPosition / Pango.Scale.PangoScale,
				lineArea.Height);

			if (textEditor.SelectionMode == SelectionMode.Block && textEditor.IsSomethingSelected && textEditor.SelectionRange.Contains (line.Offset + line.Length)) {
				DocumentLocation start = textEditor.MainSelection.Anchor;
				DocumentLocation end = textEditor.MainSelection.Lead;
				DocumentLocation visStart = textEditor.LogicalToVisualLocation (start);
				DocumentLocation visEnd = textEditor.LogicalToVisualLocation (end);
				
				double x1 = this.ColumnToX (line, visStart.Column);
				double x2 = this.ColumnToX (line, visEnd.Column);
				if (x1 > x2) {
					var tmp = x1;
					x1 = x2;
					x2 = tmp;
				}
				x1 += XOffset - textEditor.HAdjustment.Value;
				x2 += XOffset - textEditor.HAdjustment.Value;

				if (x2 > lineArea.X) {
					if (x1 - lineArea.X > 0) {
						DrawRectangleWithRuler (cr, x, new Cairo.Rectangle (lineArea.X, lineArea.Y, x1 - lineArea.X, lineArea.Height), defaultBgColor, false);
						lineArea = new Cairo.Rectangle (x1, lineArea.Y, lineArea.Width, lineArea.Height);
					}
					DrawRectangleWithRuler (cr, x, new Cairo.Rectangle (lineArea.X, lineArea.Y, x2 - lineArea.X, lineArea.Height), this.SelectionColor.CairoBackgroundColor, false);
					lineArea = new Cairo.Rectangle (x2, lineArea.Y, textEditor.Allocation.Width - lineArea.X, lineArea.Height);
				}
			}

			if (!isSelectionDrawn) {
				if (isEolSelected) {
					if (!Platform.IsMac) {
						// prevent "gaps" in the selection drawing ('fuzzy' lines problem)
						lineArea = new Cairo.Rectangle (pangoPosition / Pango.Scale.PangoScale,
						lineArea.Y,
						textEditor.Allocation.Width - pangoPosition / Pango.Scale.PangoScale + 1,
						lineArea.Height);
					} else {
						// prevent "gaps" in the selection drawing ('fuzzy' lines problem)
						lineArea = new Cairo.Rectangle (pangoPosition / Pango.Scale.PangoScale - 1,
						lineArea.Y,
						textEditor.Allocation.Width - pangoPosition / Pango.Scale.PangoScale + 1,
						lineArea.Height);
					}
					
					DrawRectangleWithRuler (cr, x, lineArea, this.SelectionColor.CairoBackgroundColor, false);
				} else if (!(HighlightCaretLine || textEditor.Options.HighlightCaretLine) || Caret.Line != lineNr) {
					LayoutWrapper wrapper = GetLayout (line);
					if (wrapper.EolSpanStack != null) {
						foreach (var span in wrapper.EolSpanStack) {
							var spanStyle = textEditor.ColorStyle.GetChunkStyle (span.Color);
							if (!spanStyle.TransparentBackround && GetPixel (ColorStyle.Default.BackgroundColor) != GetPixel (spanStyle.BackgroundColor)) {
								DrawRectangleWithRuler (cr, x, lineArea, spanStyle.CairoBackgroundColor, false);
								break;
							}
						}
					}
				} else {
					double xPos = pangoPosition / Pango.Scale.PangoScale;
					DrawCaretLineMarker (cr, xPos, y, lineArea.X + lineArea.Width - xPos);
				}
			}
			
			if (!isEolFolded && textEditor.Options.ShowEolMarkers)
				DrawEolMarker (cr, line, isEolSelected, pangoPosition / Pango.Scale.PangoScale, y);
			var extendingMarker = Document.GetExtendingTextMarker (lineNr);
			if (extendingMarker != null)
				extendingMarker.Draw (textEditor, cr, lineNr, lineArea);
			
			lastLineRenderWidth = pangoPosition / Pango.Scale.PangoScale;
		}
		public bool DrawBackground (TextEditor editor, Cairo.Context g, TextViewMargin.LayoutWrapper layout2, int selectionStart, int selectionEnd, int startOffset, int endOffset, double y, double startXPos, double endXPos, ref bool drawBg)
		{
			if (!IsVisible || DebuggingService.IsDebugging)
				return true;
			EnsureLayoutCreated (editor);
			double x = editor.TextViewMargin.XOffset;
			int right = editor.Allocation.Width;
			int errorCounterWidth = 0;
			bool isCaretInLine = startOffset <= editor.Caret.Offset && editor.Caret.Offset <= endOffset;
			int ew = 0, eh = 0;
			if (errors.Count > 1 && errorCountLayout != null) {
				errorCountLayout.GetPixelSize (out ew, out eh);
				errorCounterWidth = ew + 10;
			}
			
			double x2 = System.Math.Max (right - LayoutWidth - border - (ShowIconsInBubble ? errorPixbuf.Width : 0) - errorCounterWidth, fitsInSameLine ? editor.TextViewMargin.XOffset + editor.LineHeight / 2 : editor.TextViewMargin.XOffset);
			bool isEolSelected = editor.IsSomethingSelected && editor.SelectionMode != SelectionMode.Block ? editor.SelectionRange.Contains (lineSegment.Offset + lineSegment.EditableLength) : false;
			
			int active = editor.Document.GetTextAt (lineSegment) == initialText ? 0 : 1;
			int highlighted = active == 0 && isCaretInLine ? 1 : 0;
			int selected = 0;
			
			double topSize = editor.LineHeight / 2;
			double bottomSize = editor.LineHeight / 2 + editor.LineHeight % 2;
		
			if (!fitsInSameLine) {
				if (isEolSelected) {
					x -= (int)editor.HAdjustment.Value;
					editor.TextViewMargin.DrawRectangleWithRuler (g, x, new Cairo.Rectangle (x, y + editor.LineHeight, editor.TextViewMargin.TextStartPosition, editor.LineHeight), editor.ColorStyle.Default.CairoBackgroundColor, true);
					editor.TextViewMargin.DrawRectangleWithRuler (g, x + editor.TextViewMargin.TextStartPosition, new Cairo.Rectangle (x + editor.TextViewMargin.TextStartPosition, y + editor.LineHeight, editor.Allocation.Width + (int)editor.HAdjustment.Value, editor.LineHeight), editor.ColorStyle.Selection.CairoBackgroundColor, true);
					x += (int)editor.HAdjustment.Value;
				} else {
					editor.TextViewMargin.DrawRectangleWithRuler (g, x, new Cairo.Rectangle (x, y + editor.LineHeight, x2, editor.LineHeight), editor.ColorStyle.Default.CairoBackgroundColor, true);
				}
			}
			DrawRectangle (g, x, y, right, topSize);
			g.Color = colorMatrix[active, TOP, LIGHT, highlighted, selected];
			g.Fill ();
			DrawRectangle (g, x, y + topSize, right, bottomSize);
			g.Color = colorMatrix[active, BOTTOM, LIGHT, highlighted, selected];
			g.Fill ();
			
			g.MoveTo (new Cairo.PointD (x, y + 0.5));
			g.LineTo (new Cairo.PointD (x + right, y + 0.5));
			g.Color = colorMatrix[active, TOP, LINE, highlighted, selected];
			g.Stroke ();
			
			g.MoveTo (new Cairo.PointD (x, y + editor.LineHeight - 0.5));
			g.LineTo (new Cairo.PointD ((fitsInSameLine ? x + right : x2 + 1), y + editor.LineHeight - 0.5));
			g.Color = colorMatrix[active, BOTTOM, LINE, highlighted, selected];
			g.Stroke ();
			if (editor.Options.ShowRuler) {
				double divider = Math.Max (editor.TextViewMargin.XOffset, x + editor.TextViewMargin.RulerX);
				g.MoveTo (new Cairo.PointD (divider + 0.5, y));
				g.LineTo (new Cairo.PointD (divider + 0.5, y + editor.LineHeight));
				g.Color = colorMatrix[active, BOTTOM, LINE, highlighted, selected];
				g.Stroke ();
			}
			
			// draw background
			if (layout2.StartSet || selectionStart == endOffset) {
				double startX;
				double endX;
				
				if (selectionStart != endOffset) {
					var start = layout2.Layout.IndexToPos ((int)layout2.SelectionStartIndex);
					startX = (int)(start.X / Pango.Scale.PangoScale);
					var end = layout2.Layout.IndexToPos ((int)layout2.SelectionEndIndex);
					endX = (int)(end.X / Pango.Scale.PangoScale);
				} else {
					startX = x2;
					endX = startX;
				}
				
				if (editor.MainSelection.SelectionMode == SelectionMode.Block && startX == endX)
					endX = startX + 2;
				startX += startXPos;
				endX += startXPos;
				startX = Math.Max (editor.TextViewMargin.XOffset, startX);
				// clip region to textviewmargin start
				if (isEolSelected)
					endX = editor.Allocation.Width + (int)editor.HAdjustment.Value;
				if (startX < endX) {
					DrawRectangle (g, startX, y, endX - startX, topSize);
					g.Color = colorMatrix[active, TOP, LIGHT, highlighted, 1];
					g.Fill ();
					DrawRectangle (g, startX, y + topSize, endX - startX, bottomSize);
					g.Color = colorMatrix[active, BOTTOM, LIGHT, highlighted, 1];
					g.Fill ();
					
					g.MoveTo (new Cairo.PointD (startX, y + 0.5));
					g.LineTo (new Cairo.PointD (endX, y + 0.5));
					g.Color = colorMatrix[active, TOP, LINE, highlighted, 1];
					g.Stroke ();
					
					if (startX < x2) {
						g.MoveTo (new Cairo.PointD (startX, y + editor.LineHeight - 0.5));
						g.LineTo (new Cairo.PointD (System.Math.Min (endX, x2 + 1), y + editor.LineHeight - 0.5));
						g.Color = colorMatrix[active, BOTTOM, LINE, highlighted, 1];
						g.Stroke ();
						if (x2 + 1 < endX) {
							g.MoveTo (new Cairo.PointD (x2 + 1, y + editor.LineHeight - 0.5));
							g.LineTo (new Cairo.PointD (endX, y + editor.LineHeight - 0.5));
							g.Color = colorMatrix[active, BOTTOM, LIGHT, highlighted, 1];
							g.Stroke ();
						}
					}
					
					if (editor.Options.ShowRuler) {
						double divider = Math.Max (editor.TextViewMargin.XOffset, x + editor.TextViewMargin.RulerX);
						g.MoveTo (new Cairo.PointD (divider + 0.5, y));
						g.LineTo (new Cairo.PointD (divider + 0.5, y + editor.LineHeight));
						g.Color = colorMatrix[active, BOTTOM, LINE, highlighted, 1];
						g.Stroke ();
					}
				}
			}
			
			if (!fitsInSameLine)
				y += editor.LineHeight;
			double y2 = y + 0.5;
			double y2Bottom = y2 + editor.LineHeight - 1;
			selected = isEolSelected && (CollapseExtendedErrors || errors.Count == 1) ? 1 : 0;
			
			// draw message text background
			if (CollapseExtendedErrors || errors.Count == 1) {
				if (!fitsInSameLine) {
					// draw box below line 
					g.MoveTo (new Cairo.PointD (x2 + 0.5, y2 - 1));
					g.LineTo (new Cairo.PointD (x2 + 0.5, y2Bottom));
					g.LineTo (new Cairo.PointD (right, y2Bottom));
					g.LineTo (new Cairo.PointD (right, y2 - 1));
					g.ClosePath ();
					g.Color = colorMatrix[active, BOTTOM, LIGHT, highlighted, selected];
					g.Fill ();
					
					g.MoveTo (new Cairo.PointD (x2 + 0.5, y2 - 1));
					g.LineTo (new Cairo.PointD (x2 + 0.5, y2Bottom));
					g.LineTo (new Cairo.PointD (right, y2Bottom));
					g.Color = colorMatrix[active, BOTTOM, LINE, highlighted, selected];
					g.Stroke ();
				} else {
					// draw 'arrow marker' in the same line
					g.MoveTo (new Cairo.PointD (x2 + 0.5, y2));
					double mid = y2 + topSize;
					g.LineTo (new Cairo.PointD (x2 - editor.LineHeight / 2 + 0.5, mid));
					
					g.LineTo (new Cairo.PointD (right, mid));
					g.LineTo (new Cairo.PointD (right, y2));
					g.ClosePath ();
					g.Color = colorMatrix[active, TOP, DARK, highlighted, selected];
					g.Fill ();
					g.MoveTo (new Cairo.PointD (x2 + 0.5, y2Bottom));
					g.LineTo (new Cairo.PointD (x2 - editor.LineHeight / 2 + 0.5, mid));
					
					g.LineTo (new Cairo.PointD (right, mid));
					g.LineTo (new Cairo.PointD (right, y2Bottom));
					g.ClosePath ();
					
					g.Color = colorMatrix[active, BOTTOM, DARK, highlighted, selected];
					g.Fill ();
					
					// draw border
					g.MoveTo (new Cairo.PointD (x2 + 0.5, y2));
					g.LineTo (new Cairo.PointD (x2 - editor.LineHeight / 2 + 0.5, y2 + editor.LineHeight / 2));
					
					g.LineTo (new Cairo.PointD (x2 + 0.5, y2Bottom));
					g.LineTo (new Cairo.PointD (right, y2Bottom));
					g.LineTo (new Cairo.PointD (right, y2));
					g.ClosePath ();
					
					g.Color = colorMatrix[active, BOTTOM, LINE, highlighted, selected];
					g.Stroke ();
				}
			} else {
				if (!fitsInSameLine) {
					// draw box below line
					g.MoveTo (new Cairo.PointD (x2 + 0.5, y2 - 1));
					g.LineTo (new Cairo.PointD (x2 + 0.5, y2Bottom));
					g.LineTo (new Cairo.PointD (right, y2Bottom));
					g.LineTo (new Cairo.PointD (right, y2 - 1));
					g.ClosePath ();
				} else {
					// draw filled arrow box
					g.MoveTo (new Cairo.PointD (x2 + 0.5, y2));
					g.LineTo (new Cairo.PointD (x2 - editor.LineHeight / 2 + 0.5, y2 + editor.LineHeight / 2));
					g.LineTo (new Cairo.PointD (x2 + 0.5, y2Bottom));
					g.LineTo (new Cairo.PointD (right, y2Bottom));
					g.LineTo (new Cairo.PointD (right, y2));
					g.ClosePath ();
				}
				g.Color = colorMatrix[active, BOTTOM, LIGHT, highlighted, selected];
				g.Fill ();
				
				// draw light bottom line
				g.MoveTo (new Cairo.PointD (right, y2Bottom));
				g.LineTo (new Cairo.PointD (x2 + 0.5, y2Bottom));
				g.Stroke ();
				
				// stroke left line
				if (fitsInSameLine) {
					g.MoveTo (new Cairo.PointD (x2 + 0.5, y2));
					g.LineTo (new Cairo.PointD (x2 - editor.LineHeight / 2 + 0.5, y2 + editor.LineHeight / 2));
					g.LineTo (new Cairo.PointD (x2 + 0.5, y2Bottom));
				} else {
					g.MoveTo (new Cairo.PointD (x2 + 0.5, y2 - 1));
					g.LineTo (new Cairo.PointD (x2 + 0.5, y2Bottom + 1));
				}
				
				g.Color = colorMatrix[active, BOTTOM, LINE, highlighted, selected];
				g.Stroke ();
				
				// stroke top line
				if (fitsInSameLine) {
					g.Color = colorMatrix[active, BOTTOM, LINE, highlighted, selected];
					g.MoveTo (new Cairo.PointD (right, y2));
					g.LineTo (new Cairo.PointD (x2 + 0.5, y2));
					g.Stroke ();
				}
			}
			
			if (editor.Options.ShowRuler) {
				double divider = Math.Max (editor.TextViewMargin.XOffset, x + editor.TextViewMargin.RulerX);
				if (divider >= x2) {
					g.MoveTo (new Cairo.PointD (divider + 0.5, y2));
					g.LineTo (new Cairo.PointD (divider + 0.5, y2Bottom));
					g.Color = colorMatrix[active, BOTTOM, DARK, highlighted, selected];
					g.Stroke ();
				}
			}
			
			if (errors.Count > 1 && errorCountLayout != null) {
				double rX = x2 + (ShowIconsInBubble ? errorPixbuf.Width : 0) + border + LayoutWidth;
				double rY = y + editor.LineHeight / 6;
				double rW = errorCounterWidth - 2;
				double rH = editor.LineHeight * 3 / 4;
				BookmarkMarker.DrawRoundRectangle (g, rX, rY, 8, rW, rH);
				
				g.Color = oldIsOver ? new Cairo.Color (0.3, 0.3, 0.3) : new Cairo.Color (0.5, 0.5, 0.5);
				g.Fill ();
				if (CollapseExtendedErrors) {
					g.Color = gcLight;
					g.Save ();
					g.Translate (x2 + (ShowIconsInBubble ? errorPixbuf.Width : 0) + border + LayoutWidth + 4, y + (editor.LineHeight - eh) / 2 + eh % 2);
					g.ShowLayout (errorCountLayout);
					g.Restore ();
				} else {
					g.MoveTo (rX + rW / 2 - rW / 4, rY + rH - rH / 4);
					g.LineTo (rX + rW / 2 + rW / 4, rY + rH - rH / 4);
					g.LineTo (rX + rW / 2, rY + rH / 4);
					g.ClosePath ();
					
					g.Color = new Cairo.Color (1, 1, 1);
					g.Fill ();
				}
			}
			
			for (int i = 0; i < layouts.Count; i++) {
				LayoutDescriptor layout = layouts[i];
				x2 = right - layout.Width - border - errorPixbuf.Width;
				if (i == 0)
					x2 -= errorCounterWidth;
				x2 = System.Math.Max (x2, fitsInSameLine ? editor.TextViewMargin.XOffset + editor.LineHeight / 2 : editor.TextViewMargin.XOffset);
				if (i > 0) {
					editor.TextViewMargin.DrawRectangleWithRuler (g, x, new Cairo.Rectangle (x, y, right, editor.LineHeight), isEolSelected ? editor.ColorStyle.Selection.CairoBackgroundColor : editor.ColorStyle.Default.CairoBackgroundColor, true);
					g.MoveTo (new Cairo.PointD (x2 + 0.5, y));
					g.LineTo (new Cairo.PointD (x2 + 0.5, y + editor.LineHeight));
					g.LineTo (new Cairo.PointD (right, y + editor.LineHeight));
					g.LineTo (new Cairo.PointD (right, y));
					g.ClosePath ();
					
					if (CollapseExtendedErrors) {
						Cairo.Gradient pat = new Cairo.LinearGradient (x2, y, x2, y + editor.LineHeight);
						pat.AddColorStop (0, colorMatrix[active, TOP, LIGHT, highlighted, selected]);
						pat.AddColorStop (1, colorMatrix[active, BOTTOM, LIGHT, highlighted, selected]);
						g.Pattern = pat;
					} else {
						g.Color = colorMatrix[active, TOP, LIGHT, highlighted, selected];
					}
					g.Fill ();
					if (editor.Options.ShowRuler) {
						double divider = Math.Max (editor.TextViewMargin.XOffset, x + editor.TextViewMargin.RulerX);
						if (divider >= x2) {
							g.MoveTo (new Cairo.PointD (divider + 0.5, y));
							g.LineTo (new Cairo.PointD (divider + 0.5, y + editor.LineHeight));
							g.Color = colorMatrix[active, BOTTOM, DARK, highlighted, selected];
							g.Stroke ();
						}
					}
				}
				int lw, lh;
				layout.Layout.GetPixelSize (out lw, out lh);
				g.Color = (HslColor)(selected == 0 ? gc : gcSelected);
				g.Save ();
				g.Translate (x2 + errorPixbuf.Width + border, y + (editor.LineHeight - layout.Height) / 2 + layout.Height % 2);
				g.ShowLayout (layout.Layout);
				g.Restore ();
				y += editor.LineHeight;
				if (!UseVirtualLines)
					break;
			}
			return true;
		}
		public void Draw (TextEditor editor, Cairo.Context g, int lineNr, Cairo.Rectangle lineArea)
		{
			EnsureLayoutCreated (editor);
			int lineNumber = editor.Document.OffsetToLineNumber (lineSegment.Offset);
			int errorNumber = lineNr - lineNumber;
			if (!IsCurrentErrorTextFitting ())
				errorNumber--;
			double x = editor.TextViewMargin.XOffset;
			double y = lineArea.Y;
			double right = editor.Allocation.Width;
			int errorCounterWidth = GetErrorCountBounds ().Item1;
//			int eh = GetErrorCountBounds ().Item2;
			
			double x2 = System.Math.Max (right - LayoutWidth - border - (ShowIconsInBubble ? cache.errorPixbuf.Width : 0) - errorCounterWidth, fitsInSameLine ? editor.TextViewMargin.XOffset + editor.LineHeight / 2 : editor.TextViewMargin.XOffset);
			if (errors.Count == 1)
				x2 = editor.TextViewMargin.XOffset;
//			bool isEolSelected = editor.IsSomethingSelected && editor.SelectionMode != SelectionMode.Block ? editor.SelectionRange.Contains (lineSegment.Offset  + lineSegment.EditableLength) : false;
			int active = editor.Document.GetTextAt (lineSegment) == initialText ? 0 : 1;
			bool isCaretInLine = lineSegment.Offset <= editor.Caret.Offset && editor.Caret.Offset <= lineSegment.EndOffsetIncludingDelimiter;
			bool highlighted = active == 0 && isCaretInLine;
			bool selected = false;
			var layout = layouts [errorNumber];
			x2 = right - LayoutWidth - border - (ShowIconsInBubble ? cache.errorPixbuf.Width : 0);
			
			x2 -= errorCounterWidth;
			x2 = System.Math.Max (x2, fitsInSameLine ? editor.TextViewMargin.XOffset + editor.LineHeight / 2 : editor.TextViewMargin.XOffset);
			
			g.MoveTo (new Cairo.PointD (x2 + 0.5, y));
			g.LineTo (new Cairo.PointD (x2 + 0.5, y + editor.LineHeight));
			g.LineTo (new Cairo.PointD (right, y + editor.LineHeight));
			g.LineTo (new Cairo.PointD (right, y));
			g.ClosePath ();
			g.Color = TagColor.Color;// GetLineColorTop (highlighted, selected);
			g.Fill ();
			
			g.Color = TagColor.BorderColor; //GetLineColorBottom (highlighted, selected);
			g.MoveTo (new Cairo.PointD (x2 + 0.5, y));
			g.LineTo (new Cairo.PointD (x2 + 0.5, y + editor.LineHeight));
			if (errorNumber == errors.Count - 1)
				g.LineTo (new Cairo.PointD (lineArea.X + lineArea.Width, y + editor.LineHeight));
			g.Stroke ();
			
			if (editor.Options.ShowRuler) {
				double divider = Math.Max (editor.TextViewMargin.XOffset, x + editor.TextViewMargin.RulerX);
				if (divider >= x2) {
					g.MoveTo (new Cairo.PointD (divider + 0.5, y));
					g.LineTo (new Cairo.PointD (divider + 0.5, y + editor.LineHeight));
					g.Color = TagColor.BorderColor;
					g.Stroke ();
				}
			}
			g.Save ();
			g.Translate (x2 + (ShowIconsInBubble ? cache.errorPixbuf.Width : 0) + border, y + (editor.LineHeight - layout.Height) / 2 + layout.Height % 2);
			g.Color = TextColor.Color;
			g.ShowLayout (layout.Layout);
			g.Restore ();
			
			if (ShowIconsInBubble) {
				var pixbuf = errors [errorNumber].IsError ? cache.errorPixbuf: cache.warningPixbuf;
				Gdk.CairoHelper.SetSourcePixbuf (g, pixbuf, x2, y + (editor.LineHeight - cache.errorPixbuf.Height) / 2);
				g.Paint ();
			}
		}
		public override void DrawAfterEol (MonoTextEditor textEditor, Cairo.Context g, EndOfLineMetrics metrics)
		{
			if (!IsVisible)
				return;
			EnsureLayoutCreated (editor);
			int errorCounterWidth = 0, eh = 0;
			if (errorCountLayout != null) {
				errorCountLayout.GetPixelSize (out errorCounterWidth, out eh);
				errorCounterWidth = Math.Max (15, Math.Max (errorCounterWidth + 3, (int)(editor.LineHeight * 3 / 4)));
			}

			var sx = metrics.TextRenderEndPosition;
			var width = LayoutWidth + errorCounterWidth + editor.LineHeight;
			var drawLayout = layouts[0].Layout;
			var y = metrics.LineYRenderStartPosition;
			bool customLayout = true; //sx + width > editor.Allocation.Width;
			bool hideText = false;
			bubbleIsReduced = customLayout;
			var showErrorCount = errorCounterWidth > 0 && errorCountLayout != null;
			double roundingRadius = editor.LineHeight / 2 - 1;

			if (customLayout) {
				width = editor.Allocation.Width - sx;
				string text = layouts[0].Layout.Text;
				drawLayout = new Pango.Layout (editor.PangoContext);
				drawLayout.FontDescription = cache.fontDescription;
				var paintWidth = (width - errorCounterWidth - editor.LineHeight + 4);
				var minWidth = Math.Max (25, errorCounterWidth) * editor.Options.Zoom;
				if (paintWidth < minWidth) {
					hideText = true;
					showErrorCount = false;
//					drawLayout.SetMarkup ("<span weight='heavy'>···</span>");
					width = minWidth;
					//roundingRadius = 10 * editor.Options.Zoom;
					sx = Math.Min (sx, editor.Allocation.Width - width);
				} else {
					drawLayout.Ellipsize = Pango.EllipsizeMode.End;
					drawLayout.Width = (int)(paintWidth * Pango.Scale.PangoScale);
					drawLayout.SetText (text);
					int w2, h2;
					drawLayout.GetPixelSize (out w2, out h2);
					width = w2 + errorCounterWidth + editor.LineHeight - 2;
				}
			}

			bubbleDrawX = sx - editor.TextViewMargin.XOffset;
			bubbleDrawY = y + 2;
			bubbleWidth = width;
			var bubbleHeight = editor.LineHeight;

			g.RoundedRectangle (sx, y, width, bubbleHeight, roundingRadius);
			g.SetSourceColor (TagColor.Color);
			g.Fill ();

			// Draw error count icon
			if (showErrorCount) {
				var errorCounterHeight = bubbleHeight - 2;
				var errorCounterX = sx + width - errorCounterWidth - 1;
				var errorCounterY = Math.Round (y + (bubbleHeight - errorCounterHeight) / 2);

				g.RoundedRectangle (
					errorCounterX, 
					errorCounterY, 
					errorCounterWidth, 
					errorCounterHeight, 
					editor.LineHeight / 2 - 2
				);

				using (var lg = new Cairo.LinearGradient (errorCounterX, errorCounterY, errorCounterX, errorCounterY + errorCounterHeight)) {
					lg.AddColorStop (0, CounterColor.Color);
					lg.AddColorStop (1, CounterColor.Color.AddLight (-0.1));
					g.SetSource (lg);
					g.Fill ();
				}

				g.Save ();

				int ew;
				errorCountLayout.GetPixelSize (out ew, out eh);

				var tx = Math.Round (errorCounterX + (2 + errorCounterWidth - ew) / 2);
				var ty = Math.Round (errorCounterY + (-1 + errorCounterHeight - eh) / 2);

				g.Translate (tx, ty);
				g.SetSourceColor (CounterColor.SecondColor);
				g.ShowLayout (errorCountLayout);
				g.Restore ();
			}

			if (hideText) {
				// Draw dots
				double radius = 2 * editor.Options.Zoom;
				double spacing = 1 * editor.Options.Zoom;

				sx += 1 * editor.Options.Zoom + Math.Ceiling((bubbleWidth - 3 * (radius * 2) - 2 * spacing) / 2);

				for (int i = 0; i < 3; i++) {
					g.Arc (sx, y + bubbleHeight / 2, radius, 0, Math.PI * 2);
					g.SetSourceColor (TagColor.SecondColor);
					g.Fill ();
					sx += radius * 2 + spacing;
				}
			} else {
				// Draw label text
				var tx = Math.Round (sx + editor.LineHeight / 2);
				var ty = Math.Round (y + (editor.LineHeight - layouts [0].Height) / 2) - 1;

				g.Save ();
				g.Translate (tx, ty);

				g.SetSourceColor (TagColor.SecondColor);
				g.ShowLayout (drawLayout);
				g.Restore ();
			}

			if (customLayout)
				drawLayout.Dispose ();
		}
		internal protected override void Draw (Cairo.Context cr, Cairo.Rectangle area, DocumentLine lineSegment, int line, double x, double y, double lineHeight)
		{
			var gutterMarker = lineSegment != null ? (MarginMarker)lineSegment.Markers.FirstOrDefault (marker => marker is MarginMarker && ((MarginMarker)marker).CanDraw (this)) : null;
			if (gutterMarker != null && gutterMarker.CanDrawBackground (this)) {
				bool hasDrawn = gutterMarker.DrawBackground (editor, cr, new MarginDrawMetrics (this, area, lineSegment, line, x, y, lineHeight));
				if (!hasDrawn)
					DrawGutterBackground (cr, line, x, y, lineHeight);
			} else {
				DrawGutterBackground (cr, line, x, y, lineHeight);
			}

			if (gutterMarker != null && gutterMarker.CanDrawForeground (this)) {
				gutterMarker.DrawForeground (editor, cr, new MarginDrawMetrics (this, area, lineSegment, line, x, y, lineHeight));
				return;
			}

			if (line <= editor.Document.LineCount) {
				// Due to a mac? gtk bug I need to re-create the layout here
				// otherwise I get pango exceptions.
				using (var layout = editor.LayoutCache.RequestLayout ()) {
					layout.FontDescription = gutterFont;
					layout.Width = (int)Width;
					layout.Alignment = Pango.Alignment.Right;
					layout.SetText (line.ToString ());
					cr.Save ();
					cr.Translate (x + (int)Width + (editor.Options.ShowFoldMargin ? 0 : -2), y);
					cr.SetSourceColor (lineNumberGC);
					cr.ShowLayout (layout);
					cr.Restore ();
				}
			}
		}
		public bool DrawBackground (TextEditor editor, Cairo.Context g, TextViewMargin.LayoutWrapper layout2, int selectionStart, int selectionEnd, int startOffset, int endOffset, double startYPos, double startXPos, double endXPos, ref bool drawBg)
		{
			if (!IsVisible)
				return true;
			EnsureLayoutCreated (editor);
			double x = editor.TextViewMargin.XOffset;
			double y = startYPos;
			int right = editor.Allocation.Width;
			bool isCaretInLine = startOffset <= editor.Caret.Offset && editor.Caret.Offset <= endOffset;
			var lineTextPx = editor.TextViewMargin.XOffset + editor.TextViewMargin.TextStartPosition + layout2.PangoWidth / Pango.Scale.PangoScale;
			int errorCounterWidth = GetErrorCountBounds (layout2).Item1;
//			int eh = GetErrorCountBounds ().Item2;
			double x2 = System.Math.Max (right - LayoutWidth - border - (ShowIconsInBubble ? cache.errorPixbuf.Width : 0) - errorCounterWidth, fitsInSameLine ? editor.TextViewMargin.XOffset + editor.LineHeight / 2 : editor.TextViewMargin.XOffset);
			
			bool isEolSelected = editor.IsSomethingSelected && editor.SelectionMode != SelectionMode.Block ? editor.SelectionRange.Contains (lineSegment.Offset + lineSegment.Length) : false;
			
			int active = editor.Document.GetTextAt (lineSegment) == initialText ? 0 : 1;
			bool highlighted = active == 0 && isCaretInLine;
			bool selected = false;
			
			double topSize = Math.Floor (editor.LineHeight / 2);
			double bottomSize = editor.LineHeight / 2 + editor.LineHeight % 2;
			if (!fitsInSameLine) {
				if (isEolSelected) {
					x -= (int)editor.HAdjustment.Value;
					editor.TextViewMargin.DrawRectangleWithRuler (g, x, new Cairo.Rectangle (x, y + editor.LineHeight, editor.TextViewMargin.TextStartPosition, editor.LineHeight), editor.ColorStyle.PlainText.Background, true);
					editor.TextViewMargin.DrawRectangleWithRuler (g, x + editor.TextViewMargin.TextStartPosition, new Cairo.Rectangle (x + editor.TextViewMargin.TextStartPosition, y + editor.LineHeight, editor.Allocation.Width + (int)editor.HAdjustment.Value, editor.LineHeight), editor.ColorStyle.SelectedText.Background, true);
					x += (int)editor.HAdjustment.Value;
				} else {
					editor.TextViewMargin.DrawRectangleWithRuler (g, x, new Cairo.Rectangle (x, y + editor.LineHeight, x2, editor.LineHeight), editor.ColorStyle.PlainText.Background, true);
				}
			}
			DrawRectangle (g, x, y, right, topSize);
			g.Color = GetLineColorTop (highlighted, selected);
			g.Fill ();

			DrawRectangle (g, x, y + topSize, right, bottomSize);
			g.Color = GetLineColorBottom (highlighted, selected);
 			g.Fill ();
			
			g.MoveTo (new Cairo.PointD (x, y + 0.5));
			g.LineTo (new Cairo.PointD (x + right, y + 0.5));
			g.Color = GetLineColorBorder (highlighted, selected);
			g.Stroke ();
			
			g.MoveTo (new Cairo.PointD (x, y + editor.LineHeight - 0.5));
			g.LineTo (new Cairo.PointD ((fitsInSameLine ? x + right : x2 + 1), y + editor.LineHeight - 0.5));
			g.Color = GetLineColorBorder (highlighted, selected);
			g.Stroke ();
			/*
			if (editor.Options.ShowRuler) {
				double divider = Math.Max (editor.TextViewMargin.XOffset, x + editor.TextViewMargin.RulerX);
				g.MoveTo (new Cairo.PointD (divider + 0.5, y));
				g.LineTo (new Cairo.PointD (divider + 0.5, y + editor.LineHeight));
				g.Color = GetLineColorBorder (highlighted, selected);
				g.Stroke ();
			}*/

// draw background
			if (layout2.StartSet || selectionStart == endOffset) {
				double startX;
				double endX;
				
				if (selectionStart != endOffset) {
					var start = layout2.Layout.IndexToPos ((int)layout2.SelectionStartIndex);
					startX = (int)(start.X / Pango.Scale.PangoScale);
					var end = layout2.Layout.IndexToPos ((int)layout2.SelectionEndIndex);
					endX = (int)(end.X / Pango.Scale.PangoScale);
				} else {
					startX = x2;
					endX = startX;
				}
				
				if (editor.MainSelection.SelectionMode == SelectionMode.Block && startX == endX)
					endX = startX + 2;
				startX += startXPos;
				endX += startXPos;
				startX = Math.Max (editor.TextViewMargin.XOffset, startX);
// clip region to textviewmargin start
				if (isEolSelected)
					endX = editor.Allocation.Width + (int)editor.HAdjustment.Value;
				if (startX < endX) {
					DrawRectangle (g, startX, y, endX - startX, topSize);
					g.Color = GetLineColorTop (highlighted, true);
					g.Fill ();
					DrawRectangle (g, startX, y + topSize, endX - startX, bottomSize);
					g.Color = GetLineColorBottom (highlighted, true);
					g.Fill ();
					
					g.MoveTo (new Cairo.PointD (startX, y + 0.5));
					g.LineTo (new Cairo.PointD (endX, y + 0.5));
					g.Color = GetLineColorBorder (highlighted, true);
					g.Stroke ();
					
					if (startX < x2) {
						g.MoveTo (new Cairo.PointD (startX, y + editor.LineHeight - 0.5));
						g.LineTo (new Cairo.PointD (System.Math.Min (endX, x2 + 1), y + editor.LineHeight - 0.5));
						g.Color = GetLineColorBorder (highlighted, true);
						g.Stroke ();
						if (x2 + 1 < endX) {
							g.MoveTo (new Cairo.PointD (x2 + 1, y + editor.LineHeight - 0.5));
							g.LineTo (new Cairo.PointD (endX, y + editor.LineHeight - 0.5));
							g.Color = GetLineColorBorder (highlighted, true);
							g.Stroke ();
						}
					}
					
					if (editor.Options.ShowRuler) {
						double divider = Math.Max (editor.TextViewMargin.XOffset, x + editor.TextViewMargin.RulerX);
						g.MoveTo (new Cairo.PointD (divider + 0.5, y));
						g.LineTo (new Cairo.PointD (divider + 0.5, y + editor.LineHeight));
						g.Color = GetLineColorBorder (highlighted, true);
						g.Stroke ();
					}
				}
			}
			
			if (!fitsInSameLine)
				y += editor.LineHeight;
			double y2 = y + 0.5;
			double y2Bottom = y2 + editor.LineHeight - 1;
			selected = isEolSelected && (CollapseExtendedErrors);
			if (x2 < lineTextPx) 
				x2 = lineTextPx;

// draw message text background
			if (CollapseExtendedErrors) {
				if (!fitsInSameLine) {
// draw box below line 
					g.MoveTo (new Cairo.PointD (x2 + 0.5, y2 - 1));
					g.LineTo (new Cairo.PointD (x2 + 0.5, y2Bottom));
					g.LineTo (new Cairo.PointD (right, y2Bottom));
					g.LineTo (new Cairo.PointD (right, y2 - 1));
					g.ClosePath ();
					g.Color = TagColor.Color;
					g.Fill ();
					
					g.MoveTo (new Cairo.PointD (x2 + 0.5, y2 - 1));
					g.LineTo (new Cairo.PointD (x2 + 0.5, y2Bottom));
					g.LineTo (new Cairo.PointD (right, y2Bottom));
					g.Color = TagColor.BorderColor;
					g.Stroke ();
				} else {
// draw 'arrow marker' in the same line
				//	if (errors.Count > 1) {
						g.MoveTo (new Cairo.PointD (x2 + 0.5, y2));
						double mid = y2 + topSize;
						g.LineTo (new Cairo.PointD (x2 - editor.LineHeight / 2 + 0.5, mid));
						
						g.LineTo (new Cairo.PointD (right, mid));
						g.LineTo (new Cairo.PointD (right, y2));
						g.ClosePath ();
						g.Color = TagColor.Color;
						g.Fill ();
						g.MoveTo (new Cairo.PointD (x2 + 0.5, y2Bottom));
						g.LineTo (new Cairo.PointD (x2 - editor.LineHeight / 2 + 0.5, mid));
						
						g.LineTo (new Cairo.PointD (right, mid));
						g.LineTo (new Cairo.PointD (right, y2Bottom));
						g.ClosePath ();
						
						g.Color = TagColor.SecondColor;
						g.Fill ();
				//	}
					
// draw border
					g.MoveTo (new Cairo.PointD (x2 + 0.5, y2));
					g.LineTo (new Cairo.PointD (x2 - editor.LineHeight / 2 + 0.5, y2 + editor.LineHeight / 2));
					
					g.LineTo (new Cairo.PointD (x2 + 0.5, y2Bottom));
					g.LineTo (new Cairo.PointD (right, y2Bottom));
					g.LineTo (new Cairo.PointD (right, y2));
					g.ClosePath ();
					
					g.Color = TagColor.BorderColor;
					g.Stroke ();
				}
			} else {
				if (!fitsInSameLine) {
// draw box below line
					g.MoveTo (new Cairo.PointD (x2 + 0.5, y2 - 1));
					g.LineTo (new Cairo.PointD (x2 + 0.5, y2Bottom));
					g.LineTo (new Cairo.PointD (right, y2Bottom));
					g.LineTo (new Cairo.PointD (right, y2 - 1));
					g.ClosePath ();
				} else {
// draw filled arrow box
					if (!(errors.Count == 1 && !CollapseExtendedErrors)) {
						g.MoveTo (new Cairo.PointD (x2 + 0.5, y2));
						g.LineTo (new Cairo.PointD (x2 - editor.LineHeight / 2 + 0.5, y2 + editor.LineHeight / 2));
						g.LineTo (new Cairo.PointD (x2 + 0.5, y2Bottom));
						g.LineTo (new Cairo.PointD (right, y2Bottom));
						g.LineTo (new Cairo.PointD (right, y2));
						g.ClosePath ();
					}
				}
				g.Color = TagColor.Color;
				g.Fill ();
				
// draw light bottom line
				g.MoveTo (new Cairo.PointD (right, y2Bottom));
				g.LineTo (new Cairo.PointD (x2 + 0.5, y2Bottom));
				g.Stroke ();
				
// stroke left line
				if (fitsInSameLine) {
					g.MoveTo (new Cairo.PointD (x2 + 0.5, y2));
					g.LineTo (new Cairo.PointD (x2 - editor.LineHeight / 2 + 0.5, y2 + editor.LineHeight / 2));
					g.LineTo (new Cairo.PointD (x2 + 0.5, y2Bottom));
				} else {
					g.MoveTo (new Cairo.PointD (x2 + 0.5, y2 - 1));
					g.LineTo (new Cairo.PointD (x2 + 0.5, y2Bottom + 1));
				}
				
				g.Color = TagColor.BorderColor;
				g.Stroke ();
				
// stroke top line
				if (fitsInSameLine) {
					g.Color = TagColor.BorderColor;
					g.MoveTo (new Cairo.PointD (right, y2));
					g.LineTo (new Cairo.PointD (x2 + 0.5, y2));
					g.Stroke ();
				}
			}
			
			if (editor.Options.ShowRuler) {
				double divider = Math.Max (editor.TextViewMargin.XOffset, x + editor.TextViewMargin.RulerX);
				if (divider >= x2) {
					g.MoveTo (new Cairo.PointD (divider + 0.5, y2));
					g.LineTo (new Cairo.PointD (divider + 0.5, y2Bottom));
					g.Color = GetLineColorBorder (highlighted, selected);
					g.Stroke ();
				}
			}

			
			for (int i = 0; i < layouts.Count; i++) {
				if (!IsCurrentErrorTextFitting (layout2) && !CollapseExtendedErrors)
					break;
				
				var layout = layouts [i];
				x2 = right - layout.Width - border - (ShowIconsInBubble ? cache.errorPixbuf.Width : 0);
				if (i == 0) {
					x2 -= errorCounterWidth;
					if (x2 < lineTextPx) {
						//			if (CollapseExtendedErrors) {
						x2 = lineTextPx;
						//			}
					}
				}
//				x2 = System.Math.Max (x2, fitsInSameLine ? editor.TextViewMargin.XOffset + editor.LineHeight / 2 : editor.TextViewMargin.XOffset);
				
				if (i > 0) {
					editor.TextViewMargin.DrawRectangleWithRuler (g, x, new Cairo.Rectangle (x, y, right, editor.LineHeight), isEolSelected ? editor.ColorStyle.SelectedText.Background : editor.ColorStyle.PlainText.Background, true);
					g.MoveTo (new Cairo.PointD (x2 + 0.5, y));
					g.LineTo (new Cairo.PointD (x2 + 0.5, y + editor.LineHeight));
					g.LineTo (new Cairo.PointD (right, y + editor.LineHeight));
					g.LineTo (new Cairo.PointD (right, y));
					g.ClosePath ();
					
					if (CollapseExtendedErrors) {
						using (var pat = new Cairo.LinearGradient (x2, y, x2, y + editor.LineHeight)) {
							pat.AddColorStop (0, GetLineColorTop (highlighted, selected));
							pat.AddColorStop (1, GetLineColorBottom (highlighted, selected));
							g.Pattern = pat;
						}
					} else {
						g.Color = GetLineColorTop (highlighted, selected);
					}
					g.Fill ();
					if (editor.Options.ShowRuler) {
						double divider = Math.Max (editor.TextViewMargin.XOffset, x + editor.TextViewMargin.RulerX);
						if (divider >= x2) {
							g.MoveTo (new Cairo.PointD (divider + 0.5, y));
							g.LineTo (new Cairo.PointD (divider + 0.5, y + editor.LineHeight));
							g.Color = TagColor.BorderColor;
							g.Stroke ();
						}
					}
				}
				g.Color = TextColor.Color;
				g.Save ();
				g.Translate (x2 + (ShowIconsInBubble ? cache.errorPixbuf.Width : 0) + border, y + (editor.LineHeight - layout.Height) / 2 + layout.Height % 2);
				g.ShowLayout (layout.Layout);
				g.Restore ();
				y += editor.LineHeight;
				if (!UseVirtualLines)
					break;
			}

			DrawErrorMarkers (editor, g, layout2, startXPos, startYPos);

			return true;
		}
Example #12
0
		void DrawButtonTabs (Cairo.Context cr, Cairo.Rectangle rectangle)
		{
			if (IsSeparator) {
				cr.NewPath ();
				double x = Math.Ceiling (rectangle.X + rectangle.Width / 2) + 0.5;
				cr.MoveTo (x, rectangle.Y + 0.5 + 2);
				cr.RelLineTo (0, rectangle.Height - 1 - 4);
				cr.ClosePath ();
				cr.Color = (HslColor)parent.Style.Dark (StateType.Normal);
				cr.LineWidth = 1;
				cr.Stroke ();
				return;
			}
			
			int topPadding = 2;
			
			if (Active || HoverPosition.X >= 0) {
				cr.Rectangle (rectangle.X + 1, rectangle.Y + 1 + topPadding, rectangle.Width - 1, rectangle.Height - topPadding);
				if (Active) {
					cr.Color = (HslColor)parent.Style.Background (StateType.Prelight);
				} else if (HoverPosition.X >= 0) {
					double rx = rectangle.X + HoverPosition.X;
					double ry = rectangle.Y + HoverPosition.Y;
					Cairo.RadialGradient gradient = new Cairo.RadialGradient (rx, ry, rectangle.Height * 1.5, 
						rx, ry, 2);
					var color = (HslColor)parent.Style.Dark (StateType.Normal);
					color.L *= 1.1;
					gradient.AddColorStop (0, color);
					color.L *= 1.1;
					gradient.AddColorStop (1, color);
					cr.Pattern = gradient;
				}
				cr.Fill ();
				
				if (Active) {
					cr.Rectangle (rectangle.X + 0.5, rectangle.Y + 0.5 + topPadding, rectangle.Width - 1, rectangle.Height - topPadding);
					cr.Color = (HslColor)parent.Style.Dark (StateType.Normal);
					cr.LineWidth = 1;
					cr.Stroke ();
				}
			}
			
			cr.Save ();
			cr.Translate (rectangle.X + (rectangle.Width - w) / 2, (rectangle.Height - h) / 2 + topPadding);
			cr.Color = (HslColor)parent.Style.Text (StateType.Normal);
			
			cr.ShowLayout (layout);
			
			cr.Restore ();
		}
Example #13
0
		void DrawCurveTabs (Cairo.Context cr, Cairo.Rectangle rectangle)
		{
			if (IsSeparator)
				return;
			
			cr.MoveTo (rectangle.X, rectangle.Y);
			
			double bottom = rectangle.Y + rectangle.Height - 1;
			
			cr.CurveTo (
				rectangle.X + SpacerWidth / 2, rectangle.Y,
				rectangle.X + SpacerWidth / 2, bottom,
				rectangle.X + SpacerWidth, bottom);
			
			cr.LineTo (rectangle.X + rectangle.Width - SpacerWidth, bottom);
			
			cr.CurveTo (
				rectangle.X + rectangle.Width - SpacerWidth / 2, bottom,
				rectangle.X + rectangle.Width - SpacerWidth / 2, rectangle.Y,
				rectangle.X + rectangle.Width, rectangle.Y);
			
			cr.Color = (HslColor)parent.Style.Dark (StateType.Normal);
			cr.StrokePreserve ();
			cr.ClosePath ();
			if (Active) {
				cr.Color = (HslColor)parent.Style.Background (StateType.Prelight);
			} else if (HoverPosition.X >= 0) {
				double rx = rectangle.X + HoverPosition.X;
				double ry = rectangle.Y + HoverPosition.Y;
				Cairo.RadialGradient gradient = new Cairo.RadialGradient (rx, ry, rectangle.Height * 1.5, 
					rx, ry, 2);
				var color = (HslColor)parent.Style.Mid (StateType.Normal);
				color.L *= 1.05;
				gradient.AddColorStop (0, color);
				color.L *= 1.07;
				gradient.AddColorStop (1, color);
				cr.Pattern = gradient;
			} else {
				cr.Color = (HslColor)parent.Style.Mid (StateType.Normal);
			}
			cr.Fill ();
			
			cr.Save ();
			cr.Translate (rectangle.X + (rectangle.Width - w) / 2, (rectangle.Height - h) / 2);
			cr.Color = (HslColor)parent.Style.Text (StateType.Normal);
			
			cr.ShowLayout (layout);
			
			cr.Restore ();
		}
Example #14
0
		internal protected override void Draw (Cairo.Context cr, Cairo.Rectangle area, LineSegment lineSegment, int line, double x, double y, double lineHeight)
		{
			cr.Rectangle (x, y, Width, lineHeight);
			cr.Color = lineNumberBgGC;
			cr.Fill ();
			
			if (line <= editor.Document.LineCount) {
				layout.SetText (line.ToString ());
				cr.Save ();
				cr.Translate (x + (int)Width, y);
				cr.Color = editor.Caret.Line == line ? lineNumberHighlightGC : lineNumberGC;
				cr.ShowLayout (layout);
				cr.Restore ();
			}
		}
Example #15
0
		void DrawEolMarker (Cairo.Context cr, LineSegment line, bool selected, double x, double y)
		{
			Pango.Layout layout;
			switch (line.DelimiterLength) {
			case 0:
				// an emty line end should only happen at eof
				layout = eofEolLayout;
				break;
			case 1:
				if (Document.GetCharAt (line.Offset + line.Length) == '\n') {
					layout = unixEolLayout;
				} else {
					layout = macEolLayout;
				}
				break;
			case 2:
				layout = windowEolLayout;
				break;
			default:
				throw new InvalidOperationException (); // other line endings are not known.
			}
			cr.Save ();
			cr.Translate (x, y);
			cr.Color = selected ? SelectionColor.CairoColor : ColorStyle.EolWhitespaceMarker;
			cr.ShowLayout (layout);
			cr.Restore ();
		}
		void RenderLineNumberIcon (Widget widget, Cairo.Context cr, Gdk.Rectangle cell_area, int markupHeight, int yOffset)
		{
			if (Frame == null)
				return;

			cr.Save ();

			#if CENTER_ROUNDED_RECTANGLE
			cr.Translate (cell_area.X + Padding, (cell_area.Y + (cell_area.Height - RoundedRectangleHeight) / 2.0));
			#else
			cr.Translate (cell_area.X + Padding, cell_area.Y + Padding + yOffset);
			#endif

			cr.Antialias = Cairo.Antialias.Subpixel;

			cr.RoundedRectangle (0.0, 0.0, RoundedRectangleWidth, RoundedRectangleHeight, RoundedRectangleRadius);
			cr.Clip ();

			if (IsUserCode)
				cr.SetSourceRGBA (0.90, 0.60, 0.87, 1.0); // 230, 152, 223
			else
				cr.SetSourceRGBA (0.77, 0.77, 0.77, 1.0); // 197, 197, 197

			cr.RoundedRectangle (0.0, 0.0, RoundedRectangleWidth, RoundedRectangleHeight, RoundedRectangleRadius);
			cr.Fill ();

			cr.SetSourceRGBA (0.0, 0.0, 0.0, 0.11);
			cr.RoundedRectangle (0.0, 0.0, RoundedRectangleWidth, RoundedRectangleHeight, RoundedRectangleRadius);
			cr.LineWidth = 2;
			cr.Stroke ();

			var lineNumber = !string.IsNullOrEmpty (Frame.File) ? Frame.Line : -1;

			using (var layout = PangoUtil.CreateLayout (widget, lineNumber != -1 ? lineNumber.ToString () : "???")) {
				layout.Alignment = Pango.Alignment.Left;
				layout.FontDescription = LineNumberFont;

				int width, height;
				layout.GetPixelSize (out width, out height);

				double y_offset = (RoundedRectangleHeight - height) / 2.0;
				double x_offset = (RoundedRectangleWidth - width) / 2.0;

				// render the text shadow
				cr.Save ();
				cr.SetSourceRGBA (0.0, 0.0, 0.0, 0.34);
				cr.Translate (x_offset, y_offset + 1);
				cr.ShowLayout (layout);
				cr.Restore ();

				cr.SetSourceRGBA (1.0, 1.0, 1.0, 1.0);
				cr.Translate (x_offset, y_offset);
				cr.ShowLayout (layout);
			}

			cr.Restore ();
		}
Example #17
0
		void DrawInvalidLineMarker (Cairo.Context cr, double x, double y)
		{
			cr.Save ();
			cr.Translate (x, y);
			cr.Color = ColorStyle.InvalidLineMarker;
			cr.ShowLayout (invalidLineLayout);
			cr.Restore ();
		}
Example #18
0
		public void Render (Cairo.Context cr, double _x, double _y, int max_height)
		{
			double x = _x;
			double y = _y;
			int w = Width;
			int h = max_height;
			int inner_padding = 0;

			if (Outlined) {
				x -= outlinePadding;
				y -= outlinePadding;
				w += outlinePadding * 2;
				h += outlinePadding * 2;

				cr.MoveTo (x, y);
				cr.LineWidth = 1;
				cr.SetSourceColor (Styles.ModeHelpWindowTokenOutlineColor.ToCairoColor());

				if (Symbol == SymbolTokenType.None)
					inner_padding = textInnerPadding;

				// -0.5f to fix the @1x stroke problem:
				// 1px stroke is rendered on the center of the shape edge, resulting in
				// two semitransparent pixels. Even worse the rounded rectangle renders
				// transparency artifacts on edge overlaps. See http://vncr.in/atks
				FoldingScreenbackgroundRenderer.DrawRoundRectangle (cr, true, true, x - inner_padding - 0.5f, y - 0.5f, 8, w + inner_padding * 2 + 1, h + 1);

				cr.Stroke ();

				if (Symbol == SymbolTokenType.Down) {
					RenderTriangleDown (cr, x + 4, y + 3, 8, 6);
				} else if (Symbol == SymbolTokenType.Up) {
					RenderTriangleUp (cr, x + 4, y + 3, 8, 6);
				} else {
					cr.MoveTo (x + outlinePadding, y + (max_height - Height - 0.5));
					cr.ShowLayout (layout);
				}
			} else {
				cr.MoveTo (x, y);
				cr.SetSourceColor (Styles.ModeHelpWindowTokenTextColor.ToCairoColor());
				cr.ShowLayout (layout);
			}
		}
		public override void DrawAfterEol (TextEditor textEditor, Cairo.Context g, double y, EndOfLineMetrics metrics)
		{
			EnsureLayoutCreated (editor);
			int errorCounterWidth = 0, eh = 0;
			if (errorCountLayout != null) 
				errorCountLayout.GetPixelSize (out errorCounterWidth, out eh);

			var sx = metrics.TextRenderEndPosition;
			var width = LayoutWidth + errorCounterWidth + editor.LineHeight;
			var drawLayout = layouts[0].Layout;
			int ex = 0 , ey = 0;
			bool customLayout = sx + width > editor.Allocation.Width;
			bool hideText = false;
			bubbleIsReduced = customLayout;
			if (customLayout) {
				width = editor.Allocation.Width - sx;
				string text = layouts[0].Layout.Text;
				drawLayout = new Pango.Layout (editor.PangoContext);
				drawLayout.FontDescription = cache.fontDescription;
				for (int j = text.Length - 4; j > 0; j--) {
					drawLayout.SetText (text.Substring (0, j) + "...");
					drawLayout.GetPixelSize (out ex, out ey);
					if (ex + (errorCountLayout != null ? errorCounterWidth : 0) + editor.LineHeight < width)
						break;
				}
				if (ex + (errorCountLayout != null ? errorCounterWidth : 0) + editor.LineHeight > width) {
					hideText = true;
					drawLayout.SetMarkup ("<span weight='heavy'>···</span>");
					width = Math.Max (17, errorCounterWidth) + editor.LineHeight;
					sx = Math.Min (sx, editor.Allocation.Width - width);
				}
			}
			bubbleDrawX = sx - editor.TextViewMargin.XOffset;
			bubbleDrawY = y;
			bubbleWidth = width;
			g.RoundedRectangle (sx, y + 1, width, editor.LineHeight - 2, editor.LineHeight / 2 - 1);
			g.Color = TagColor.Color;
			g.Fill ();

			if (errorCounterWidth > 0 && errorCountLayout != null) {
				g.RoundedRectangle (sx + width - errorCounterWidth - editor.LineHeight / 2, y + 2, errorCounterWidth, editor.LineHeight - 4, editor.LineHeight / 2 - 3);
				g.Color = CounterColor.Color;
				g.Fill ();

				g.Save ();
				g.Translate (sx + width - errorCounterWidth - editor.LineHeight / 2 + (errorCounterWidth - errorCounterWidth) / 2, y + 1);
				g.Color = CounterColor.SecondColor;
				g.ShowLayout (errorCountLayout);
				g.Restore ();
			}

			if (errorCounterWidth <= 0 || errorCountLayout == null || !hideText) {
				g.Save ();
				g.Translate (sx + editor.LineHeight / 2, y + (editor.LineHeight - layouts [0].Height) / 2 + layouts [0].Height % 2);
				g.Color = TagColor.SecondColor;
				g.ShowLayout (drawLayout);
				g.Restore ();
			}

			if (customLayout)
				drawLayout.Dispose ();

		}
Example #20
0
		internal protected override void Draw (Cairo.Context cr, Cairo.Rectangle area, LineSegment lineSegment, int line, double x, double y, double lineHeight)
		{
			cr.Rectangle (x, y, Width, lineHeight);
			cr.Color = lineNumberBgGC;
			cr.Fill ();
			
			if (line <= editor.Document.LineCount) {
				// Due to a mac? gtk bug I need to re-create the layout here
				// otherwise I get pango exceptions.
				using (var layout = PangoUtil.CreateLayout (editor)) {
					layout.FontDescription = editor.Options.Font;
					layout.Width = (int)Width;
					layout.Alignment = Pango.Alignment.Right;
					layout.SetText (line.ToString ());
					cr.Save ();
					cr.Translate (x + (int)Width + (editor.Options.ShowFoldMargin ? 0 : -2), y);
					cr.Color = editor.Caret.Line == line ? lineNumberHighlightGC : lineNumberGC;
					cr.ShowLayout (layout);
					cr.Restore ();
				}
			}
		}
		public void Draw (TextEditor editor, Cairo.Context g, int lineNr, Cairo.Rectangle lineArea)
		{
			EnsureLayoutCreated (editor);
			int lineNumber = editor.Document.OffsetToLineNumber (lineSegment.Offset);
			int errorNumber = lineNr - lineNumber;
			double x = editor.TextViewMargin.XOffset;
			double y = lineArea.Y;
			double right = editor.Allocation.Width;
			int errorCounterWidth = 0;
			
			int ew = 0, eh = 0;
			if (errors.Count > 1 && errorCountLayout != null) {
				errorCountLayout.GetPixelSize (out ew, out eh);
				errorCounterWidth = ew + 10;
			}
			
			double x2 = System.Math.Max (right - LayoutWidth - border - (ShowIconsInBubble ? errorPixbuf.Width : 0) - errorCounterWidth, fitsInSameLine ? editor.TextViewMargin.XOffset + editor.LineHeight / 2 : editor.TextViewMargin.XOffset);
//			bool isEolSelected = editor.IsSomethingSelected && editor.SelectionMode != SelectionMode.Block ? editor.SelectionRange.Contains (lineSegment.Offset  + lineSegment.EditableLength) : false;
			int active = editor.Document.GetTextAt (lineSegment) == initialText ? 0 : 1;
			bool isCaretInLine = lineSegment.Offset <= editor.Caret.Offset && editor.Caret.Offset <= lineSegment.EndOffset;
			int highlighted = active == 0 && isCaretInLine ? 1 : 0;
			int selected = 0;
			LayoutDescriptor layout = layouts[errorNumber];
			x2 = right - LayoutWidth - border - (ShowIconsInBubble ? errorPixbuf.Width : 0);
			
			x2 -= errorCounterWidth;
			x2 = System.Math.Max (x2, fitsInSameLine ? editor.TextViewMargin.XOffset + editor.LineHeight / 2 : editor.TextViewMargin.XOffset);
			
			g.MoveTo (new Cairo.PointD (x2 + 0.5, y));
			g.LineTo (new Cairo.PointD (x2 + 0.5, y + editor.LineHeight));
			g.LineTo (new Cairo.PointD (right, y + editor.LineHeight));
			g.LineTo (new Cairo.PointD (right, y));
			g.ClosePath ();
			g.Color = colorMatrix[active, BOTTOM, LIGHT, highlighted, selected];
			g.Fill ();
			
			g.Color = colorMatrix[active, BOTTOM, LINE, highlighted, selected];
			g.MoveTo (new Cairo.PointD (x2 + 0.5, y));
			g.LineTo (new Cairo.PointD (x2 + 0.5, y + editor.LineHeight));
			if (errorNumber == errors.Count - 1)
				g.LineTo (new Cairo.PointD (lineArea.X + lineArea.Width, y + editor.LineHeight));
			g.Stroke ();
			
			if (editor.Options.ShowRuler) {
				double divider = Math.Max (editor.TextViewMargin.XOffset, x + editor.TextViewMargin.RulerX);
				if (divider >= x2) {
					g.MoveTo (new Cairo.PointD (divider + 0.5, y));
					g.LineTo (new Cairo.PointD (divider + 0.5, y + editor.LineHeight));
					g.Color = colorMatrix[active, BOTTOM, DARK, highlighted, selected];
					g.Stroke ();
				}
			}
			g.Save ();
			g.Translate (x2 + (ShowIconsInBubble ? errorPixbuf.Width : 0) + border, y + (editor.LineHeight - layout.Height) / 2 + layout.Height % 2);
			g.Color = selected == 0 ? gc : gcSelected;
			g.ShowLayout (layout.Layout);
			g.Restore ();
//			if (ShowIconsInBubble)
//				win.DrawPixbuf (editor.Style.BaseGC (Gtk.StateType.Normal), errors[errorNumber].IsError ? errorPixbuf : warningPixbuf, 0, 0, x2, y + (editor.LineHeight - errorPixbuf.Height) / 2, errorPixbuf.Width, errorPixbuf.Height, Gdk.RgbDither.None, 0, 0);
		}
Example #22
0
		internal protected override void Draw (Cairo.Context cr, Cairo.Rectangle area, DocumentLine lineSegment, int line, double x, double y, double lineHeight)
		{
			var gutterMarker = lineSegment != null ? (IGutterMarker)lineSegment.Markers.FirstOrDefault (marker => marker is IGutterMarker) : null;
			if (gutterMarker != null) {
				gutterMarker.DrawLineNumber (editor, Width, cr, area, lineSegment, line, x, y, lineHeight);
				return;
			}
			if (editor.Caret.Line == line) {
				editor.TextViewMargin.DrawCaretLineMarker (cr, x, y, Width, lineHeight);
			} else {
				cr.Rectangle (x, y, Width, lineHeight);
				cr.Color = lineNumberBgGC;
				cr.Fill ();
			}
			
			if (line <= editor.Document.LineCount) {
				// Due to a mac? gtk bug I need to re-create the layout here
				// otherwise I get pango exceptions.
				using (var layout = PangoUtil.CreateLayout (editor)) {
					layout.FontDescription = gutterFont;
					layout.Width = (int)Width;
					layout.Alignment = Pango.Alignment.Right;
					layout.SetText (line.ToString ());
					cr.Save ();
					cr.Translate (x + (int)Width + (editor.Options.ShowFoldMargin ? 0 : -2), y + (lineHeight - fontHeight) / 2);
					cr.Color = lineNumberGC;
					cr.ShowLayout (layout);
					cr.Restore ();
				}
			}
		}
		void DrawEolMarker (Cairo.Context cr, DocumentLine line, bool selected, double x, double y)
		{
			if (!textEditor.Options.IncludeWhitespaces.HasFlag (IncludeWhitespaces.LineEndings))
				return;

			Pango.Layout layout;
			Pango.Rectangle rect;

			var index = GetEolMarkerIndex (line.UnicodeNewline);
			layout = eolMarkerLayout [index];
			rect = eolMarkerLayoutRect [index];
			cr.Save ();
			cr.Translate (x, y + System.Math.Max (0, LineHeight - rect.Height - 1));
			var col = ColorStyle.PlainText.Foreground;

			if (selected && !SelectionColor.TransparentForeground) {
				col = SelectionColor.Foreground;
			} else {
				if (line != null && line.NextLine != null && line.NextLine.StartSpan != null && line.NextLine.StartSpan.Count > 0) {
					var span = line.NextLine.StartSpan.Peek ();
					var chunkStyle = ColorStyle.GetChunkStyle (span.Color);
					if (chunkStyle != null)
						col = ColorStyle.GetForeground (chunkStyle);
				}
			}

			cr.SetSourceRGBA (col.R, col.G, col.B, whitespaceMarkerAlpha * 1.4); // needs to more opaque due to font rendering
			cr.ShowLayout (layout);
			cr.Restore ();
		}
		void DrawMessageExtendIcon (Mono.TextEditor.TextEditor editor, Cairo.Context g, double y, int errorCounterWidth, int eh)
		{
			EnsureLayoutCreated (editor);
			double rW = errorCounterWidth - 2;
			double rH = editor.LineHeight * 3 / 4;
			
			double rX = editor.Allocation.Width - rW - 2;
			double rY = y + (editor.LineHeight - rH) / 2;
			BookmarkMarker.DrawRoundRectangle (g, rX, rY, 8, rW, rH);
			
			g.Color = oldIsOver ? new Cairo.Color (0.3, 0.3, 0.3) : new Cairo.Color (0.5, 0.5, 0.5);
			g.Fill ();
			if (CollapseExtendedErrors) {
				if (errorCountLayout != null) {
					g.Color = cache.gcLight;
					g.Save ();
					g.Translate (rX + rW / 4, rY + (rH - eh) / 2);
					g.ShowLayout (errorCountLayout);
					g.Restore ();
				} else {
					g.MoveTo (rX + rW / 2 - rW / 4, rY + rH / 4);
					g.LineTo (rX + rW / 2 + rW / 4, rY + rH / 4);
					g.LineTo (rX + rW / 2, rY + rH - rH / 4);
					g.ClosePath ();
				
					g.Color = new Cairo.Color (1, 1, 1);
					g.Fill ();
				}
			} else {
				g.MoveTo (rX + rW / 2 - rW / 4, rY + rH - rH / 4);
				g.LineTo (rX + rW / 2 + rW / 4, rY + rH - rH / 4);
				g.LineTo (rX + rW / 2, rY + rH / 4);
				g.ClosePath ();
				
				g.Color = new Cairo.Color (1, 1, 1);
				g.Fill ();
			}
		}
		void DrawEolMarker (Cairo.Context cr, DocumentLine line, bool selected, double x, double y)
		{
			if (!textEditor.Options.IncludeWhitespaces.HasFlag (IncludeWhitespaces.LineEndings))
				return;

			Pango.Layout layout;
			Pango.Rectangle rect;
			switch (line.DelimiterLength) {
			case 0:
				// an emty line end should only happen at eof
				layout = eofEolLayout;
				rect = eofEolLayoutRect;
				break;
			case 1:
				var eolIndex = GetEolMarkerIndex (Document.GetCharAt (line.Offset + line.Length));
				layout = eolMarkerLayout[eolIndex];
				rect = eolMarkerLayoutRect[eolIndex];
				break;
			case 2:
				layout = eolMarkerLayout[2];
				rect = eolMarkerLayoutRect[2];
				break;
			default:
				throw new InvalidOperationException (); // other line endings are not known.
			}
			cr.Save ();
			cr.Translate (x, y + System.Math.Max (0, LineHeight - rect.Height - 1));
			var col = ColorStyle.PlainText.Foreground;

			if (selected && !SelectionColor.TransparentForeground) {
				col = SelectionColor.Foreground;
			} else {
				if (line != null && line.NextLine != null && line.NextLine.StartSpan != null && line.NextLine.StartSpan.Count > 0) {
					var span = line.NextLine.StartSpan.Peek ();
					var chunkStyle = ColorStyle.GetChunkStyle (span.Color);
					if (chunkStyle != null)
						col = ColorStyle.GetForeground (chunkStyle);
				}
			}

			cr.Color = new Cairo.Color (col.R, col.G, col.B, whitespaceMarkerAlpha);
			cr.ShowLayout (layout);
			cr.Restore ();
		}
Example #26
0
		void DrawTabMarker (Cairo.Context cr, bool selected, double x, double y)
		{
			cr.Save ();
			cr.Translate (x, y);
			cr.ShowLayout (tabMarkerLayout);
			cr.Restore ();
		}
Example #27
0
			protected override void OnDrawContent (Gdk.EventExpose evnt, Cairo.Context g)
			{
				g.Rectangle (0, 0, Allocation.Width, Allocation.Height);
				g.SetSourceColor (marker.TooltipColor.Color);
				g.Fill ();

				using (var drawingLayout = new Pango.Layout (this.PangoContext)) {
					drawingLayout.FontDescription = cache.tooltipFontDescription;

					double y = verticalTextBorder;
					var showBulletedList = marker.Errors.Count > 1;

					foreach (var msg in marker.Errors) {
						var icon = msg.IsError ? errorPixbuf : warningPixbuf;
						int w, h;

						if (!showBulletedList)
							drawingLayout.Width = maxTextWidth;

						drawingLayout.SetText (GetFirstLine (msg));
						drawingLayout.GetPixelSize (out w, out h);

						if (showBulletedList) {
							g.Save ();

							g.Translate (textBorder, y + verticalTextSpace / 2 + Math.Max (0, (h - icon.Height) / 2));
							g.DrawImage (this, icon, 0, 0);
							g.Restore ();
						}

						g.Save ();

						g.Translate (showBulletedList ? textBorder + iconTextSpacing + icon.Width: textBorder, y + verticalTextSpace / 2);
						g.SetSourceColor (marker.TagColor.SecondColor);
						g.ShowLayout (drawingLayout);

						g.Restore ();

						y += h + verticalTextSpace;
					}
				}
			}
Example #28
0
		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 ();
		}
			protected override void OnDrawContent (Gdk.EventExpose evnt, Cairo.Context g)
			{
				g.Rectangle (0, 0, Allocation.Width, Allocation.Height);
				g.Color = marker.LineColor.SecondColor;
				g.Fill ();

				double y = 8;
				double x = 4;
				foreach (var layout in marker.Layouts) {
					g.Save ();
					g.Translate (x, y);
					g.Color = marker.TagColor.SecondColor;
					g.ShowLayout (layout.Layout);
					g.Restore ();
					y += layout.Height;
				}

			}
		void DrawLine (Cairo.Context g, TextEditor editor, int lineNumber, ref int y)
		{
			using (var drawingLayout = new Pango.Layout (this.PangoContext)) {
				drawingLayout.FontDescription = fontDescription;
				var line = editor.GetLine (lineNumber);
				var correctedIndentLength = CorrectIndent (editor, line, indentLength);
				drawingLayout.SetMarkup (editor.GetPangoMarkup (line.Offset + Math.Min (correctedIndentLength, line.Length), Math.Max (0, line.Length - correctedIndentLength)));
				g.Save ();
				g.Translate (textBorder, y);
				g.ShowLayout (drawingLayout);
				g.Restore ();
				y += lineHeight;
			}
		}