示例#1
0
            void CopyData(TextEditorData data, Selection selection)
            {
                copiedDocument = null;
                monoDocument   = null;
                if (selection != null && data != null && data.Document != null)
                {
                    copiedDocument = new Document();
                    monoDocument   = new Document();
                    this.docStyle  = data.ColorStyle;
                    this.options   = data.Options;
                    this.mode      = data.Document.SyntaxMode != null && data.Options.EnableSyntaxHighlighting ? data.Document.SyntaxMode : Mono.TextEditor.Highlighting.SyntaxMode.Default;
                    switch (selection.SelectionMode)
                    {
                    case SelectionMode.Normal:
                        isBlockMode = false;
                        ISegment segment = selection.GetSelectionRange(data);
                        copiedDocument.Text = this.mode.GetTextWithoutMarkup(data.Document, data.ColorStyle, segment.Offset, segment.Length);
                        monoDocument.Text   = this.mode.GetTextWithoutMarkup(data.Document, data.ColorStyle, segment.Offset, segment.Length);
                        LineSegment line      = data.Document.GetLineByOffset(segment.Offset);
                        var         spanStack = line.StartSpan.Clone();
                        SyntaxModeService.ScanSpans(data.Document, this.mode, this.mode, spanStack, line.Offset, segment.Offset);
                        this.copiedDocument.GetLine(DocumentLocation.MinLine).StartSpan = spanStack;
                        break;

                    case SelectionMode.Block:
                        isBlockMode = true;
                        DocumentLocation visStart = data.LogicalToVisualLocation(selection.Anchor);
                        DocumentLocation visEnd   = data.LogicalToVisualLocation(selection.Lead);
                        int startCol = System.Math.Min(visStart.Column, visEnd.Column);
                        int endCol   = System.Math.Max(visStart.Column, visEnd.Column);
                        for (int lineNr = selection.MinLine; lineNr <= selection.MaxLine; lineNr++)
                        {
                            LineSegment curLine = data.Document.GetLine(lineNr);
                            int         col1    = curLine.GetLogicalColumn(data, startCol) - 1;
                            int         col2    = System.Math.Min(curLine.GetLogicalColumn(data, endCol) - 1, curLine.EditableLength);
                            if (col1 < col2)
                            {
                                ((IBuffer)copiedDocument).Insert(copiedDocument.Length, data.Document.GetTextAt(curLine.Offset + col1, col2 - col1));
                                ((IBuffer)monoDocument).Insert(monoDocument.Length, data.Document.GetTextAt(curLine.Offset + col1, col2 - col1));
                            }
                            if (lineNr < selection.MaxLine)
                            {
                                // Clipboard line end needs to be system dependend and not the document one.
                                ((IBuffer)copiedDocument).Insert(copiedDocument.Length, Environment.NewLine);
                                // \r in mono document stands for block selection line end.
                                ((IBuffer)monoDocument).Insert(monoDocument.Length, "\r");
                            }
                        }
                        line      = data.Document.GetLine(selection.MinLine);
                        spanStack = line.StartSpan.Clone();
                        SyntaxModeService.ScanSpans(data.Document, this.mode, this.mode, spanStack, line.Offset, line.Offset + startCol);
                        this.copiedDocument.GetLine(DocumentLocation.MinLine).StartSpan = spanStack;
                        break;
                    }
                }
                else
                {
                    copiedDocument = null;
                }
            }
示例#2
0
        internal void DeleteSelection(Selection selection)
        {
            if (selection == null)
            {
                throw new ArgumentNullException("selection");
            }
            switch (selection.SelectionMode)
            {
            case SelectionMode.Normal:
                ISegment segment = selection.GetSelectionRange(this);
                if (Caret.Offset > segment.Offset)
                {
                    Caret.Offset -= System.Math.Min(segment.Length, Caret.Offset - segment.Offset);
                }
                int len = System.Math.Min(segment.Length, Document.Length - segment.Offset);
                if (len > 0)
                {
                    Remove(segment.Offset, len);
                }
                break;

            case SelectionMode.Block:
                DocumentLocation visStart = LogicalToVisualLocation(selection.Anchor);
                DocumentLocation visEnd   = LogicalToVisualLocation(selection.Lead);
                int  startCol             = System.Math.Min(visStart.Column, visEnd.Column);
                int  endCol   = System.Math.Max(visStart.Column, visEnd.Column);
                bool preserve = Caret.PreserveSelection;
                Caret.PreserveSelection = true;
                for (int lineNr = selection.MinLine; lineNr <= selection.MaxLine; lineNr++)
                {
                    LineSegment curLine = Document.GetLine(lineNr);
                    int         col1    = curLine.GetLogicalColumn(this, startCol) - 1;
                    int         col2    = System.Math.Min(curLine.GetLogicalColumn(this, endCol) - 1, curLine.EditableLength);
                    if (col1 >= col2)
                    {
                        continue;
                    }
                    Remove(curLine.Offset + col1, col2 - col1);

                    if (Caret.Line == lineNr && Caret.Column >= col1)
                    {
                        Caret.Column = col1 + 1;
                    }
                }
                int column = System.Math.Min(selection.Anchor.Column, selection.Lead.Column);
                selection.Anchor        = new DocumentLocation(selection.Anchor.Line, column);
                selection.Lead          = new DocumentLocation(selection.Lead.Line, column);
                Caret.Column            = column;
                Caret.PreserveSelection = preserve;
                break;
            }
        }
示例#3
0
        void SetColumn()
        {
            LineSegment curLine = this.document.GetLine(this.Line);

            if (curLine == null)
            {
                return;
            }
            this.location.Column = curLine.GetLogicalColumn(editor, this.DesiredColumn);
            if (curLine.GetVisualColumn(editor, this.location.Column) < this.DesiredColumn)
            {
                this.location.Column = editor.GetNextVirtualColumn(Line, this.location.Column);
            }
            else
            {
                if (this.Column > curLine.EditableLength)
                {
                    this.location.Column = System.Math.Min(curLine.EditableLength, System.Math.Max(0, this.Column));
                    if (AllowCaretBehindLineEnd)
                    {
                        this.location.Column = editor.GetNextVirtualColumn(Line, this.location.Column);
                    }
                }
            }
        }
示例#4
0
        void SetColumn()
        {
            LineSegment curLine = TextEditorData.Document.GetLine(this.Line);

            if (curLine == null)
            {
                return;
            }
            this.location.Column = curLine.GetLogicalColumn(TextEditorData, this.DesiredColumn);
            if (curLine.GetVisualColumn(TextEditorData, this.location.Column) < this.DesiredColumn)
            {
                this.location.Column = TextEditorData.GetNextVirtualColumn(Line, this.location.Column);
            }
            else
            {
                if (this.Column > curLine.EditableLength + 1)
                {
                    this.location.Column = System.Math.Min(curLine.EditableLength + 1, System.Math.Max(DocumentLocation.MinColumn, this.Column));
                    if (AllowCaretBehindLineEnd)
                    {
                        this.location.Column = TextEditorData.GetNextVirtualColumn(Line, this.location.Column);
                    }
                }
            }
        }
示例#5
0
		public LayoutWrapper CreateLinePartLayout (ISyntaxMode mode, LineSegment line, int logicalRulerColumn, int offset, int length, int selectionStart, int selectionEnd)
		{
			bool containsPreedit = textEditor.ContainsPreedit (offset, length);
			LayoutDescriptor descriptor;
			if (!containsPreedit && layoutDict.TryGetValue (line, out descriptor)) {
				bool isInvalid;
				if (descriptor.Equals (line, offset, length, selectionStart, selectionEnd, out isInvalid) && descriptor.Layout != null) {
					return descriptor.Layout;
				}
				descriptor.Dispose ();
				layoutDict.Remove (line);
			}
			var wrapper = new LayoutWrapper (PangoUtil.CreateLayout (textEditor));
			wrapper.IsUncached = containsPreedit;

			if (logicalRulerColumn < 0)
				logicalRulerColumn = line.GetLogicalColumn (textEditor.GetTextEditorData (), textEditor.Options.RulerColumn);
			var atts = new FastPangoAttrList ();
			wrapper.Layout.Alignment = Pango.Alignment.Left;
			wrapper.Layout.FontDescription = textEditor.Options.Font;
			wrapper.Layout.Tabs = tabArray;
			StringBuilder textBuilder = new StringBuilder ();
			var chunks = GetCachedChunks (mode, Document, textEditor.ColorStyle, line, offset, length);
			foreach (var chunk in chunks) {
				try {
					textBuilder.Append (Document.GetTextAt (chunk));
				} catch {
					Console.WriteLine (chunk);
				}
			}
			var spanStack = line.StartSpan;
			int lineOffset = line.Offset;
			string lineText = textBuilder.ToString ();
			uint preeditLength = 0;
			
			if (containsPreedit) {
				lineText = lineText.Insert (textEditor.preeditOffset - offset, textEditor.preeditString);
				preeditLength = (uint)textEditor.preeditString.Length;
			}
			char[] lineChars = lineText.ToCharArray ();
			//int startOffset = offset, endOffset = offset + length;
			uint curIndex = 0, byteIndex = 0;
			uint curChunkIndex = 0, byteChunkIndex = 0;
			
			uint oldEndIndex = 0;
			foreach (Chunk chunk in chunks) {
				ChunkStyle chunkStyle = chunk != null ? textEditor.ColorStyle.GetChunkStyle (chunk) : null;
				spanStack = chunk.SpanStack ?? spanStack;
				foreach (TextMarker marker in line.Markers)
					chunkStyle = marker.GetStyle (chunkStyle);

				if (chunkStyle != null) {
					//startOffset = chunk.Offset;
					//endOffset = chunk.EndOffset;

					uint startIndex = (uint)(oldEndIndex);
					uint endIndex = (uint)(startIndex + chunk.Length);
					oldEndIndex = endIndex;

					HandleSelection (lineOffset, logicalRulerColumn, selectionStart, selectionEnd, chunk.Offset, chunk.EndOffset, delegate(int start, int end) {
						if (containsPreedit) {
							if (textEditor.preeditOffset < start)
								start += (int)preeditLength;
							if (textEditor.preeditOffset < end)
								end += (int)preeditLength;
						}
						var si = TranslateToUTF8Index (lineChars, (uint)(startIndex + start - chunk.Offset), ref curIndex, ref byteIndex);
						var ei = TranslateToUTF8Index (lineChars, (uint)(startIndex + end - chunk.Offset), ref curIndex, ref byteIndex);
						atts.AddForegroundAttribute (chunkStyle.Color, si, ei);
						
						if (!chunkStyle.TransparentBackround && GetPixel (ColorStyle.Default.BackgroundColor) != GetPixel (chunkStyle.BackgroundColor)) {
							wrapper.AddBackground (chunkStyle.CairoBackgroundColor, (int)si, (int)ei);
						} else if (chunk.SpanStack != null && ColorStyle != null) {
							foreach (var span in chunk.SpanStack) {
								if (span == null)
									continue;
								var spanStyle = ColorStyle.GetChunkStyle (span.Color);
								if (!spanStyle.TransparentBackround && GetPixel (ColorStyle.Default.BackgroundColor) != GetPixel (spanStyle.BackgroundColor)) {
									wrapper.AddBackground (spanStyle.CairoBackgroundColor, (int)si, (int)ei);
									break;
								}
							}
						}
					}, delegate(int start, int end) {
						if (containsPreedit) {
							if (textEditor.preeditOffset < start)
								start += (int)preeditLength;
							if (textEditor.preeditOffset < end)
								end += (int)preeditLength;
						}
						var si = TranslateToUTF8Index (lineChars, (uint)(startIndex + start - chunk.Offset), ref curIndex, ref byteIndex);
						var ei = TranslateToUTF8Index (lineChars, (uint)(startIndex + end - chunk.Offset), ref curIndex, ref byteIndex);
						atts.AddForegroundAttribute (SelectionColor.Color, si, ei);
						if (!wrapper.StartSet)
							wrapper.SelectionStartIndex = (int)si;
						wrapper.SelectionEndIndex = (int)ei;
					});

					var translatedStartIndex = TranslateToUTF8Index (lineChars, (uint)startIndex, ref curChunkIndex, ref byteChunkIndex);
					var translatedEndIndex = TranslateToUTF8Index (lineChars, (uint)endIndex, ref curChunkIndex, ref byteChunkIndex);

					if (chunkStyle.Bold)
						atts.AddWeightAttribute (Pango.Weight.Bold, translatedStartIndex, translatedEndIndex);

					if (chunkStyle.Italic)
						atts.AddStyleAttribute (Pango.Style.Italic, translatedStartIndex, translatedEndIndex);

					if (chunkStyle.Underline)
						atts.AddUnderlineAttribute (Pango.Underline.Single, translatedStartIndex, translatedEndIndex);
				}
			}
			if (containsPreedit) {
				var si = TranslateToUTF8Index (lineChars, (uint)(textEditor.preeditOffset - offset), ref curIndex, ref byteIndex);
				var ei = TranslateToUTF8Index (lineChars, (uint)(textEditor.preeditOffset - offset + preeditLength), ref curIndex, ref byteIndex);
				atts.Splice (textEditor.preeditAttrs, (int)si, (int)(ei - si));
			}
			wrapper.LineChars = lineChars;
			wrapper.Layout.SetText (lineText);
			wrapper.EolSpanStack = spanStack;
			atts.AssignTo (wrapper.Layout);
			atts.Dispose ();
			int w, h;
			wrapper.Layout.GetSize (out w, out h);
			wrapper.PangoWidth = w;

			selectionStart = System.Math.Max (line.Offset - 1, selectionStart);
			selectionEnd = System.Math.Min (line.EndOffsetIncludingDelimiter + 1, selectionEnd);
			descriptor = new LayoutDescriptor (line, offset, length, wrapper, selectionStart, selectionEnd);
			if (!containsPreedit)
				layoutDict[line] = descriptor;
			return wrapper;
		}
示例#6
0
		void GetSelectionOffsets (LineSegment line, out int selectionStart, out int selectionEnd)
		{
			selectionStart = -1;
			selectionEnd = -1;
			if (textEditor.IsSomethingSelected) {
				TextSegment segment = textEditor.SelectionRange;
				selectionStart = segment.Offset;
				selectionEnd = segment.EndOffset;

				if (textEditor.SelectionMode == SelectionMode.Block) {
					DocumentLocation start = textEditor.MainSelection.Anchor;
					DocumentLocation end = textEditor.MainSelection.Lead;

					DocumentLocation visStart = textEditor.LogicalToVisualLocation (start);
					DocumentLocation visEnd = textEditor.LogicalToVisualLocation (end);
					int lineOffset = line.Offset;
					int lineNumber = Document.OffsetToLineNumber (lineOffset);
					if (textEditor.MainSelection.MinLine <= lineNumber && lineNumber <= textEditor.MainSelection.MaxLine) {
						selectionStart = lineOffset + line.GetLogicalColumn (this.textEditor.GetTextEditorData (), System.Math.Min (visStart.Column, visEnd.Column)) - 1;
						selectionEnd = lineOffset + line.GetLogicalColumn (this.textEditor.GetTextEditorData (), System.Math.Max (visStart.Column, visEnd.Column)) - 1;
					}
				}
			}
		}
示例#7
0
		public double ColumnToX (LineSegment line, int column)
		{
			column--;
			if (line == null || line.Length == 0 || column < 0)
				return 0;
			int logicalRulerColumn = line.GetLogicalColumn (textEditor.GetTextEditorData (), textEditor.Options.RulerColumn);
			int lineOffset = line.Offset;
			StringBuilder textBuilder = new StringBuilder ();
			ISyntaxMode mode = Document.SyntaxMode != null && textEditor.Options.EnableSyntaxHighlighting ? Document.SyntaxMode : new SyntaxMode (Document);
			var startChunk = GetCachedChunks (mode, Document, textEditor.ColorStyle, line, lineOffset, line.Length);
			foreach (Chunk chunk in startChunk) {
				try {
					textBuilder.Append (Document.GetTextAt (chunk));
				} catch (Exception e) {
					Console.WriteLine (e);
					return 0;
				}
			}
			string lineText = textBuilder.ToString ();
			char[] lineChars = lineText.ToCharArray ();
			
			bool containsPreedit = textEditor.ContainsPreedit (lineOffset, line.Length);
			uint preeditLength = 0;

			if (containsPreedit) {
				lineText = lineText.Insert (textEditor.preeditOffset - lineOffset, textEditor.preeditString);
				preeditLength = (uint)textEditor.preeditString.Length;
			}
			if (column < lineText.Length)
				lineText = lineText.Substring (0, column);

			var layout = PangoUtil.CreateLayout (textEditor, lineText);
			layout.Alignment = Pango.Alignment.Left;
			layout.FontDescription = textEditor.Options.Font;
			layout.Tabs = tabArray;

			int startOffset = lineOffset, endOffset = lineOffset + line.Length;
			uint curIndex = 0, byteIndex = 0;
			uint curChunkIndex = 0, byteChunkIndex = 0;
			List<Pango.Attribute> attributes = new List<Pango.Attribute> ();
			uint oldEndIndex = 0;
			foreach (Chunk chunk in startChunk) {
				ChunkStyle chunkStyle = chunk != null ? textEditor.ColorStyle.GetChunkStyle (chunk) : null;

				foreach (TextMarker marker in line.Markers)
					chunkStyle = marker.GetStyle (chunkStyle);

				if (chunkStyle != null) {
					startOffset = chunk.Offset;
					endOffset = chunk.EndOffset;

					uint startIndex = (uint)(oldEndIndex);
					uint endIndex = (uint)(startIndex + chunk.Length);
					oldEndIndex = endIndex;

					if (containsPreedit) {
						if (textEditor.preeditOffset < startOffset)
							startIndex += preeditLength;
						if (textEditor.preeditOffset < endOffset)
							endIndex += preeditLength;
					}

					HandleSelection (lineOffset, logicalRulerColumn, - 1, -1, chunk.Offset, chunk.EndOffset, delegate(int start, int end) {
						Pango.AttrForeground foreGround = new Pango.AttrForeground (chunkStyle.Color.Red, chunkStyle.Color.Green, chunkStyle.Color.Blue);
						foreGround.StartIndex = TranslateToUTF8Index (lineChars, (uint)(startIndex + start - chunk.Offset), ref curIndex, ref byteIndex);
						foreGround.EndIndex = TranslateToUTF8Index (lineChars, (uint)(startIndex + end - chunk.Offset), ref curIndex, ref byteIndex);
						attributes.Add (foreGround);
						if (!chunkStyle.TransparentBackround) {
							var background = new Pango.AttrBackground (chunkStyle.BackgroundColor.Red, chunkStyle.BackgroundColor.Green, chunkStyle.BackgroundColor.Blue);
							background.StartIndex = foreGround.StartIndex;
							background.EndIndex = foreGround.EndIndex;
							attributes.Add (background);
						}
					}, delegate(int start, int end) {
						Pango.AttrForeground selectedForeground = new Pango.AttrForeground (SelectionColor.Color.Red, SelectionColor.Color.Green, SelectionColor.Color.Blue);
						selectedForeground.StartIndex = TranslateToUTF8Index (lineChars, (uint)(startIndex + start - chunk.Offset), ref curIndex, ref byteIndex);
						selectedForeground.EndIndex = TranslateToUTF8Index (lineChars, (uint)(startIndex + end - chunk.Offset), ref curIndex, ref byteIndex);
						attributes.Add (selectedForeground);
					});

					var translatedStartIndex = TranslateToUTF8Index (lineChars, (uint)startIndex, ref curChunkIndex, ref byteChunkIndex);
					var translatedEndIndex = TranslateToUTF8Index (lineChars, (uint)endIndex, ref curChunkIndex, ref byteChunkIndex);

					if (chunkStyle.Bold) {
						Pango.AttrWeight attrWeight = new Pango.AttrWeight (Pango.Weight.Bold);
						attrWeight.StartIndex = translatedStartIndex;
						attrWeight.EndIndex = translatedEndIndex;
						attributes.Add (attrWeight);
					}

					if (chunkStyle.Italic) {
						Pango.AttrStyle attrStyle = new Pango.AttrStyle (Pango.Style.Italic);
						attrStyle.StartIndex = translatedStartIndex;
						attrStyle.EndIndex = translatedEndIndex;
						attributes.Add (attrStyle);
					}

					if (chunkStyle.Underline) {
						Pango.AttrUnderline attrUnderline = new Pango.AttrUnderline (Pango.Underline.Single);
						attrUnderline.StartIndex = translatedStartIndex;
						attrUnderline.EndIndex = translatedEndIndex;
						attributes.Add (attrUnderline);
					}
				}
			}
			Pango.AttrList attributeList = new Pango.AttrList ();
			attributes.ForEach (attr => attributeList.Insert (attr));
			layout.Attributes = attributeList;
			Pango.Rectangle ink_rect, logical_rect;
			layout.GetExtents (out ink_rect, out logical_rect);
			attributes.ForEach (attr => attr.Dispose ());
			attributeList.Dispose ();
			layout.Dispose ();
			return (logical_rect.Width + Pango.Scale.PangoScale - 1) / Pango.Scale.PangoScale;
		}
示例#8
0
			public DocumentLocation PointToLocation (double xp, double yp)
			{
				lineNumber = System.Math.Min (margin.YToLine (yp + margin.textEditor.VAdjustment.Value), margin.Document.LineCount);
				line = lineNumber <= margin.Document.LineCount ? margin.Document.GetLine (lineNumber) : null;
				if (line == null)
					return DocumentLocation.Empty;
				
				int offset = line.Offset;
				
				yp = ((int)yp % margin.LineHeight);
				xp -= margin.TextStartPosition;
				xp += margin.textEditor.HAdjustment.Value;
				xp *= Pango.Scale.PangoScale;
				yp *= Pango.Scale.PangoScale;
				yp = System.Math.Max (0, yp);
				if (xp < 0)
					return new DocumentLocation (lineNumber, DocumentLocation.MinColumn);
				int column = DocumentLocation.MinColumn;
				ISyntaxMode mode = margin.Document.SyntaxMode != null && margin.textEditor.Options.EnableSyntaxHighlighting ? margin.Document.SyntaxMode : new SyntaxMode (margin.Document);
				IEnumerable<FoldSegment> foldings = margin.Document.GetStartFoldings (line);
				bool done = false;
				Pango.Layout measueLayout = null;
				restart:
				int logicalRulerColumn = line.GetLogicalColumn(margin.textEditor.GetTextEditorData(), margin.textEditor.Options.RulerColumn);
				foreach (FoldSegment folding in foldings.Where(f => f.IsFolded))
				{
					int foldOffset = folding.StartLine.Offset + folding.Column - 1;
					if (foldOffset < offset)
						continue;
					layoutWrapper = margin.CreateLinePartLayout(mode, line, logicalRulerColumn, line.Offset, foldOffset - offset, -1, -1);
					done |= ConsumeLayout ((int)(xp - xPos), (int)yp);
					if (done)
						break;
					int height, width;
					layoutWrapper.Layout.GetPixelSize (out width, out height);
					xPos += width * (int)Pango.Scale.PangoScale;
					if (measueLayout == null) {
						measueLayout = PangoUtil.CreateLayout (margin.textEditor, folding.Description);
						measueLayout.FontDescription = margin.textEditor.Options.Font;
					}

					int delta;
					measueLayout.GetPixelSize (out delta, out height);
					delta *= (int)Pango.Scale.PangoScale;
					xPos += delta;
					if (xPos - delta / 2 >= xp) {
						index = foldOffset - offset;
						done = true;
						break;
					}

					offset = folding.EndLine.Offset + folding.EndColumn;
					DocumentLocation foldingEndLocation = margin.Document.OffsetToLocation(offset);
					lineNumber = foldingEndLocation.Line;
					column = foldingEndLocation.Column;
					if (xPos >= xp) {
						index = 0;
						done = true;
						break;
					}

					if (folding.EndLine != line) {
						line = folding.EndLine;
						foldings = margin.Document.GetStartFoldings (line);
						goto restart;
					}
				}
				if (!done) {
					layoutWrapper = margin.CreateLinePartLayout(mode, line, logicalRulerColumn, offset, line.Offset + line.Length - offset, -1, -1);
					ConsumeLayout ((int)(xp - xPos), (int)yp);
				}
				if (measueLayout != null)
					measueLayout.Dispose ();
				return new DocumentLocation (lineNumber, column + index);
			}
示例#9
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;
		}
示例#10
0
		void HandleSelection (LineSegment line, int selectionStart, int selectionEnd, int startOffset, int endOffset, HandleSelectionDelegate handleNotSelected, HandleSelectionDelegate handleSelected)
		{
			int selectionStartColumn = selectionStart - line.Offset;
			int selectionEndColumn = selectionEnd - line.Offset;
			int logicalRulerColumn = line.GetLogicalColumn (textEditor.GetTextEditorData (), textEditor.Options.RulerColumn);
			int rulerOffset = line.Offset + logicalRulerColumn;
			if (textEditor.Options.ShowRuler && selectionStartColumn < logicalRulerColumn && logicalRulerColumn < selectionEndColumn && startOffset < rulerOffset && rulerOffset < endOffset) {
				InternalHandleSelection (selectionStart, selectionEnd, startOffset, rulerOffset, handleNotSelected, handleSelected);
				InternalHandleSelection (selectionStart, selectionEnd, rulerOffset, endOffset, handleNotSelected, handleSelected);
			} else {
				InternalHandleSelection (selectionStart, selectionEnd, startOffset, endOffset, handleNotSelected, handleSelected);
			}
		}
		public LayoutWrapper CreateLinePartLayout (SyntaxMode mode, LineSegment line, int logicalRulerColumn, int offset, int length, int selectionStart, int selectionEnd)
		{
			return GetCachedLayout (line, offset, length, selectionStart, selectionEnd, delegate(LayoutWrapper wrapper) {
				if (logicalRulerColumn < 0)
					logicalRulerColumn = line.GetLogicalColumn(textEditor.GetTextEditorData(), textEditor.Options.RulerColumn);
				var atts = new FastPangoAttrList ();
				wrapper.Layout.Alignment = Pango.Alignment.Left;
				wrapper.Layout.FontDescription = textEditor.Options.Font;
				wrapper.Layout.Tabs = tabArray;
				StringBuilder textBuilder = new StringBuilder ();
				Chunk startChunk = GetCachedChunks (mode, Document, textEditor.ColorStyle, line, offset, length);
				for (Chunk chunk = startChunk; chunk != null; chunk = chunk != null ? chunk.Next : null) {
					try {
						textBuilder.Append (chunk.GetText (Document));
					} catch {
						Console.WriteLine (chunk);
					}
				}
				var spanStack = line.StartSpan;
				int lineOffset = line.Offset;
				string lineText = textBuilder.ToString ();
				bool containsPreedit = !string.IsNullOrEmpty (textEditor.preeditString) && offset <= textEditor.preeditOffset && textEditor.preeditOffset <= offset + length;
				uint preeditLength = 0;
				
				if (containsPreedit) {
					lineText = lineText.Insert (textEditor.preeditOffset - offset, textEditor.preeditString);
					preeditLength = (uint)textEditor.preeditString.Length;
				}
				char[] lineChars = lineText.ToCharArray ();
				//int startOffset = offset, endOffset = offset + length;
				uint curIndex = 0, byteIndex = 0;
				uint curChunkIndex = 0, byteChunkIndex = 0;
				
				uint oldEndIndex = 0;
				for (Chunk chunk = startChunk; chunk != null; chunk = chunk != null ? chunk.Next : null) {
					ChunkStyle chunkStyle = chunk != null ? chunk.GetChunkStyle (textEditor.ColorStyle) : null;
					spanStack = chunk.SpanStack ?? spanStack;
					foreach (TextMarker marker in line.Markers)
						chunkStyle = marker.GetStyle (chunkStyle);

					if (chunkStyle != null) {
						//startOffset = chunk.Offset;
						//endOffset = chunk.EndOffset;

						uint startIndex = (uint)(oldEndIndex);
						uint endIndex = (uint)(startIndex + chunk.Length);
						oldEndIndex = endIndex;

						HandleSelection(lineOffset, logicalRulerColumn, selectionStart, selectionEnd, chunk.Offset, chunk.EndOffset, delegate(int start, int end) {
							if (containsPreedit) {
								if (textEditor.preeditOffset < start)
									start += (int)preeditLength;
								if (textEditor.preeditOffset < end)
									end += (int)preeditLength;
							}
							var si = TranslateToUTF8Index (lineChars, (uint)(startIndex + start - chunk.Offset), ref curIndex, ref byteIndex);
							var ei = TranslateToUTF8Index (lineChars, (uint)(startIndex + end - chunk.Offset), ref curIndex, ref byteIndex);
							atts.AddForegroundAttribute (chunkStyle.Color, si, ei);
							
							if (!chunkStyle.TransparentBackround && GetPixel (ColorStyle.Default.BackgroundColor) != GetPixel (chunkStyle.BackgroundColor)) {
								wrapper.AddBackground (chunkStyle.CairoBackgroundColor, (int)si, (int)ei);
							} else if (chunk.SpanStack != null && ColorStyle != null) {
								foreach (var span in chunk.SpanStack) {
									if (span == null)
										continue;
									var spanStyle = ColorStyle.GetChunkStyle (span.Color);
									if (!spanStyle.TransparentBackround && GetPixel (ColorStyle.Default.BackgroundColor) != GetPixel (spanStyle.BackgroundColor)) {
										wrapper.AddBackground (spanStyle.CairoBackgroundColor, (int)si, (int)ei);
										break;
									}
								}
							}
						}, delegate(int start, int end) {
							if (containsPreedit) {
								if (textEditor.preeditOffset < start)
									start += (int)preeditLength;
								if (textEditor.preeditOffset < end)
									end += (int)preeditLength;
							}
							var si = TranslateToUTF8Index (lineChars, (uint)(startIndex + start - chunk.Offset), ref curIndex, ref byteIndex);
							var ei = TranslateToUTF8Index (lineChars, (uint)(startIndex + end - chunk.Offset), ref curIndex, ref byteIndex);
							atts.AddForegroundAttribute (SelectionColor.Color, si, ei);
							if (!wrapper.StartSet)
								wrapper.SelectionStartIndex = (int)si;
							wrapper.SelectionEndIndex   = (int)ei;
						});

						var translatedStartIndex = TranslateToUTF8Index (lineChars, (uint)startIndex, ref curChunkIndex, ref byteChunkIndex);
						var translatedEndIndex = TranslateToUTF8Index (lineChars, (uint)endIndex, ref curChunkIndex, ref byteChunkIndex);

						if (chunkStyle.Bold)
							atts.AddWeightAttribute (Pango.Weight.Bold, translatedStartIndex, translatedEndIndex);

						if (chunkStyle.Italic)
							atts.AddStyleAttribute (Pango.Style.Italic, translatedStartIndex, translatedEndIndex);

						if (chunkStyle.Underline)
							atts.AddUnderlineAttribute (Pango.Underline.Single, translatedStartIndex, translatedEndIndex);
					}
				}
				if (containsPreedit) {
					var si = TranslateToUTF8Index (lineChars, (uint)(textEditor.preeditOffset - offset), ref curIndex, ref byteIndex);
					var ei = TranslateToUTF8Index (lineChars, (uint)(textEditor.preeditOffset - offset + preeditLength), ref curIndex, ref byteIndex);
					atts.AddUnderlineAttribute (Pango.Underline.Single, si, ei);
					
					var parser = Document.SyntaxMode.CreateSpanParser (Document, Document.SyntaxMode, line, line.StartSpan);
					
					parser.ParseSpans (line.Offset, textEditor.preeditOffset);
					var preEditColor = parser.CurSpan != null ? ColorStyle.GetChunkStyle (parser.CurSpan.Color).Color : ColorStyle.Default.Color;
					atts.AddForegroundAttribute (preEditColor, si, ei);
				}
				wrapper.LineChars = lineChars;
				wrapper.Layout.SetText (lineText);
				wrapper.EolSpanStack = spanStack;
				atts.AssignTo (wrapper.Layout);
				atts.Dispose ();
				int w, h;
				wrapper.Layout.GetSize (out w, out h);
				wrapper.PangoWidth = w;
			});
		}
示例#12
0
        protected void InsertCharacter(uint unicodeKey)
        {
            if (!textEditorData.CanEdit(Data.Caret.Line))
            {
                return;
            }

            HideMouseCursor();
            using (var undo = Document.OpenUndoGroup()) {
                textEditorData.DeleteSelectedText(textEditorData.IsSomethingSelected ? textEditorData.MainSelection.SelectionMode != SelectionMode.Block : true);

                char ch = (char)unicodeKey;
                if (!char.IsControl(ch) && textEditorData.CanEdit(Caret.Line))
                {
                    LineSegment line = Document.GetLine(Caret.Line);
                    if (Caret.IsInInsertMode || Caret.Column >= line.EditableLength + 1)
                    {
                        string text = Caret.Column > line.EditableLength + 1 ? textEditorData.GetVirtualSpaces(Caret.Line, Caret.Column) + ch.ToString() : ch.ToString();
                        if (textEditorData.IsSomethingSelected && textEditorData.MainSelection.SelectionMode == SelectionMode.Block)
                        {
                            int length = 0;
                            var visualInsertLocation = editor.LogicalToVisualLocation(Caret.Location);
                            for (int lineNumber = textEditorData.MainSelection.MinLine; lineNumber <= textEditorData.MainSelection.MaxLine; lineNumber++)
                            {
                                LineSegment lineSegment  = textEditorData.GetLine(lineNumber);
                                int         insertOffset = lineSegment.GetLogicalColumn(textEditorData, visualInsertLocation.Column) - 1;
                                string      textToInsert;
                                if (lineSegment.EditableLength < insertOffset)
                                {
                                    int visualLastColumn = lineSegment.GetVisualColumn(textEditorData, lineSegment.EditableLength + 1);
                                    int charsToInsert    = visualInsertLocation.Column - visualLastColumn;
                                    int spaceCount       = charsToInsert % editor.Options.TabSize;
                                    textToInsert = new string ('\t', (charsToInsert - spaceCount) / editor.Options.TabSize) + new string (' ', spaceCount) + text;
                                    insertOffset = lineSegment.EditableLength;
                                }
                                else
                                {
                                    textToInsert = text;
                                }
                                length = textEditorData.Insert(lineSegment.Offset + insertOffset, textToInsert);
                            }
                            Caret.PreserveSelection = true;
                            Caret.Column           += length - 1;

                            textEditorData.MainSelection.Lead   = new DocumentLocation(textEditorData.MainSelection.Lead.Line, Caret.Column + 1);
                            textEditorData.MainSelection.Anchor = new DocumentLocation(textEditorData.MainSelection.Anchor.Line, Caret.Column + 1);
                            Document.CommitMultipleLineUpdate(textEditorData.MainSelection.MinLine, textEditorData.MainSelection.MaxLine);
                        }
                        else
                        {
                            int length = textEditorData.Insert(Caret.Offset, text);
                            Caret.Column += length - 1;
                        }
                    }
                    else
                    {
                        int length = textEditorData.Replace(Caret.Offset, 1, ch.ToString());
                        if (length > 1)
                        {
                            Caret.Offset += length - 1;
                        }
                    }
                    // That causes unnecessary redraws:
                    //				bool autoScroll = Caret.AutoScrollToCaret;
                    Caret.Column++;
                    if (Caret.PreserveSelection)
                    {
                        Caret.PreserveSelection = false;
                    }
                    //				Caret.AutoScrollToCaret = autoScroll;
                    //				if (autoScroll)
                    //					Editor.ScrollToCaret ();
                    //				Document.RequestUpdate (new LineUpdate (Caret.Line));
                    //				Document.CommitDocumentUpdate ();
                }
            }
            Document.OptimizeTypedUndo();
        }
示例#13
0
        static int PasteFrom(Clipboard clipboard, TextEditorData data, bool preserveSelection, int insertionOffset, bool preserveState)
        {
            int result = -1;

            if (!data.CanEdit(data.Document.OffsetToLineNumber(insertionOffset)))
            {
                return(result);
            }
            if (clipboard.WaitIsTargetAvailable(CopyOperation.MD_ATOM))
            {
                clipboard.RequestContents(CopyOperation.MD_ATOM, delegate(Clipboard clp, SelectionData selectionData) {
                    if (selectionData.Length > 0)
                    {
                        byte[] selBytes = selectionData.Data;

                        string text     = System.Text.Encoding.UTF8.GetString(selBytes, 1, selBytes.Length - 1);
                        bool pasteBlock = (selBytes [0] & 1) == 1;
                        bool pasteLine  = (selBytes [0] & 2) == 2;
                        if (!pasteBlock && !pasteLine)
                        {
                            return;
                        }

                        data.Document.BeginAtomicUndo();
                        if (preserveSelection && data.IsSomethingSelected)
                        {
                            data.DeleteSelectedText();
                        }

                        data.Caret.PreserveSelection = true;
                        if (pasteBlock)
                        {
                            string[] lines = text.Split('\r');
                            int lineNr     = data.Document.OffsetToLineNumber(insertionOffset);
                            int col        = insertionOffset - data.Document.GetLine(lineNr).Offset;
                            int visCol     = data.Document.GetLine(lineNr).GetVisualColumn(data, col);
                            LineSegment curLine;
                            int lineCol = col;
                            result      = 0;
                            for (int i = 0; i < lines.Length; i++)
                            {
                                while (data.Document.LineCount <= lineNr + i)
                                {
                                    data.Insert(data.Document.Length, Environment.NewLine);
                                    result += Environment.NewLine.Length;
                                }
                                curLine = data.Document.GetLine(lineNr + i);
                                if (lines [i].Length > 0)
                                {
                                    lineCol = curLine.GetLogicalColumn(data, visCol);
                                    if (curLine.EditableLength + 1 < lineCol)
                                    {
                                        result += lineCol - curLine.EditableLength;
                                        data.Insert(curLine.Offset + curLine.EditableLength, new string (' ', lineCol - curLine.EditableLength));
                                    }
                                    data.Insert(curLine.Offset + lineCol, lines [i]);
                                    result += lines [i].Length;
                                }
                                if (!preserveState)
                                {
                                    data.Caret.Offset = curLine.Offset + lineCol + lines [i].Length;
                                }
                            }
                        }
                        else if (pasteLine)
                        {
                            result = text.Length;
                            LineSegment curLine = data.Document.GetLine(data.Caret.Line);
                            data.Insert(curLine.Offset, text + data.EolMarker);
                            if (!preserveState)
                            {
                                data.Caret.Offset += text.Length + data.EolMarker.Length;
                            }
                        }

                        /*				data.MainSelection = new Selection (data.Document.OffsetToLocation (insertionOffset),
                         *                                  data.Caret.Location,
                         *                                  lines.Length > 1 ? SelectionMode.Block : SelectionMode.Normal);*/
                        if (!preserveState)
                        {
                            data.ClearSelection();
                        }
                        data.Caret.PreserveSelection = false;
                        data.Document.EndAtomicUndo();
                    }
                });
            }

            if (result < 0 && clipboard.WaitIsTextAvailable())
            {
                clipboard.RequestText(delegate(Clipboard clp, string text) {
                    if (string.IsNullOrEmpty(text))
                    {
                        return;
                    }
                    data.Document.BeginAtomicUndo();
                    int caretPos = data.Caret.Offset;
                    if (data.IsSomethingSelected && data.MainSelection.SelectionMode == SelectionMode.Block)
                    {
                        data.Caret.PreserveSelection = true;
                        data.DeleteSelectedText(false);
                        int textLength           = 0;
                        int minLine              = data.MainSelection.MinLine;
                        int maxLine              = data.MainSelection.MaxLine;
                        var visualInsertLocation = data.LogicalToVisualLocation(data.Caret.Location);
                        for (int lineNumber = minLine; lineNumber <= maxLine; lineNumber++)
                        {
                            LineSegment lineSegment = data.GetLine(lineNumber);
                            int insertOffset        = lineSegment.GetLogicalColumn(data, visualInsertLocation.Column) - 1;
                            if (lineSegment.EditableLength < insertOffset)
                            {
                                int visualLastColumn = lineSegment.GetVisualColumn(data, lineSegment.EditableLength + 1);
                                int charsToInsert    = visualInsertLocation.Column - visualLastColumn;
                                int spaceCount       = charsToInsert % data.Options.TabSize;
                                string textToInsert  = new string ('\t', (charsToInsert - spaceCount) / data.Options.TabSize) + new string (' ', spaceCount) + text;
                                insertOffset         = lineSegment.EditableLength;
                                data.Insert(lineSegment.Offset + insertOffset, textToInsert);
                                data.PasteText(lineSegment.Offset + insertOffset, textToInsert);
                            }
                            else
                            {
                                textLength = data.Insert(lineSegment.Offset + insertOffset, text);
                                data.PasteText(lineSegment.Offset + insertOffset, text);
                            }
                        }

                        data.Caret.Offset           += textLength;
                        data.MainSelection.Anchor    = new DocumentLocation(System.Math.Max(DocumentLocation.MinLine, data.Caret.Line == minLine ? maxLine : minLine), System.Math.Max(DocumentLocation.MinColumn, data.Caret.Column - textLength));
                        data.MainSelection.Lead      = new DocumentLocation(data.Caret.Line, data.Caret.Column);
                        data.Caret.PreserveSelection = false;
                        data.Document.CommitMultipleLineUpdate(data.MainSelection.MinLine, data.MainSelection.MaxLine);
                    }
                    else
                    {
                        ISegment selection = data.SelectionRange;
                        if (preserveSelection && data.IsSomethingSelected)
                        {
                            data.DeleteSelectedText();
                        }
                        data.Caret.PreserveSelection = true;
                        //int oldLine = data.Caret.Line;
                        int textLength = data.Insert(insertionOffset, text);
                        result         = textLength;

                        if (data.IsSomethingSelected && data.SelectionRange.Offset >= insertionOffset)
                        {
                            data.SelectionRange.Offset += textLength;
                        }
                        if (data.IsSomethingSelected && data.MainSelection.GetAnchorOffset(data) >= insertionOffset)
                        {
                            data.MainSelection.Anchor = data.Document.OffsetToLocation(data.MainSelection.GetAnchorOffset(data) + textLength);
                        }

                        data.Caret.PreserveSelection = false;
                        if (!preserveState)
                        {
                            data.Caret.Offset += textLength;
                        }
                        else
                        {
                            if (caretPos >= insertionOffset)
                            {
                                data.Caret.Offset += textLength;
                            }
                            if (selection != null)
                            {
                                int offset = selection.Offset;
                                if (offset >= insertionOffset)
                                {
                                    offset += textLength;
                                }
                                data.SelectionRange = new Segment(offset, selection.Length);
                            }
                        }
                        data.PasteText(insertionOffset, text);
                    }
                    data.Document.EndAtomicUndo();
                });
            }

            return(result);
        }