Пример #1
0
		protected override LayoutWrapper RenderLine (long line)
		{
			var layout = new TextLayout (Editor);
			layout.Font = Editor.Options.Font;
			StringBuilder sb = new StringBuilder ();
			long startOffset = line * Editor.BytesInRow;
			long endOffset   = System.Math.Min (startOffset + Editor.BytesInRow, Data.Length);
			byte[] lineBytes = Data.GetBytes (startOffset, (int)(endOffset - startOffset));
			for (int i = 0; i < lineBytes.Length; i++) {
				byte b = lineBytes[i];
				char ch = (char)b;
				if (b < 128 && (Char.IsLetterOrDigit (ch) || Char.IsPunctuation (ch))) {
					sb.Append (ch);
				} else {
					sb.Append (".");
				}
			}
			
			layout.Text = sb.ToString ();
			Margin.LayoutWrapper result = new LayoutWrapper (layout);
			if (Data.IsSomethingSelected) {
				ISegment selection = Data.MainSelection.Segment;
				HandleSelection (selection.Offset, selection.EndOffset, startOffset, endOffset, null, delegate(long start, long end) {
					result.Layout.SetForeground (Style.Selection, (int)(start - startOffset), (int)(end - start));
					result.Layout.SetBackground (Style.SelectionBg, (int)(start - startOffset), (int)(end - start));
				});
			}
			return result;
		}
Пример #2
0
        internal protected override void Draw(Context ctx, Rectangle area, long line, double x, double y)
        {
            ctx.Rectangle(x, y, Width, Editor.LineHeight);
            ctx.SetColor(Style.HexDigitBg);
            ctx.Fill();

            LayoutWrapper layout = GetLayout(line);

            if (!Data.IsSomethingSelected && !Caret.InTextEditor && line == Data.Caret.Line)
            {
                var column = (int)(Caret.Offset % BytesInRow);
                if (Editor.Options.StringRepresentationType == StringRepresentationTypes.UTF16)
                {
                    column /= 2;
                }
                var xOffset = charWidth * column;
                ctx.Rectangle(x + xOffset, y, charWidth, Editor.LineHeight);
                ctx.SetColor(Style.HighlightOffset);
                ctx.Fill();
            }
            ctx.SetColor(Style.HexDigit);
            ctx.DrawTextLayout(layout.Layout, x, y);
            if (layout.IsUncached)
            {
                layout.Dispose();
            }
        }
Пример #3
0
        protected override LayoutWrapper RenderLine(long line)
        {
            var layout = new TextLayout(Editor);

            layout.Font = Editor.Options.Font;
//			layout.Tabs = tabArray;
            StringBuilder sb          = new StringBuilder();
            long          startOffset = line * Editor.BytesInRow;
            long          endOffset   = System.Math.Min(startOffset + Editor.BytesInRow, Data.Length);

            byte[] lineBytes = Data.GetBytes(startOffset, (int)(endOffset - startOffset));
            for (int i = 0; i < lineBytes.Length; i++)
            {
                sb.Append(string.Format("{0:X2}", lineBytes[i]));
                if ((i + 1) % Editor.Options.GroupBytes == 0)
                {
                    sb.Append(" ");                      // \t
                }
            }

            layout.Text = sb.ToString();
            Margin.LayoutWrapper result = new LayoutWrapper(layout);
            if (Data.IsSomethingSelected)
            {
                ISegment selection = Data.MainSelection.Segment;
                HandleSelection(selection.Offset, selection.EndOffset, startOffset, endOffset, null, delegate(long start, long end) {
                    result.Layout.SetForeground(Style.Selection, (int)(start - startOffset) * 3, (int)(end - start) * 3 - 1);
                    result.Layout.SetBackground(Style.SelectionBg, (int)(start - startOffset) * 3, (int)(end - start) * 3 - 1);
                });
            }
            return(result);
        }
Пример #4
0
        protected override LayoutWrapper RenderLine(long line)
        {
            var layout = new TextLayout(Editor);

            layout.Font = Editor.Options.Font;
            StringBuilder sb          = new StringBuilder();
            long          startOffset = line * Editor.BytesInRow;
            long          endOffset   = System.Math.Min(startOffset + Editor.BytesInRow, Data.Length);

            byte[] lineBytes = Data.GetBytes(startOffset, (int)(endOffset - startOffset));
            switch (Editor.Options.StringRepresentationType)
            {
            case StringRepresentationTypes.ASCII:
                for (int i = 0; i < lineBytes.Length; i++)
                {
                    byte b  = lineBytes [i];
                    char ch = (char)b;
                    if (!char.IsControl(ch))
                    {
                        sb.Append(ch);
                    }
                    else
                    {
                        sb.Append(".");
                    }
                }
                break;

            case StringRepresentationTypes.UTF16:
                for (int i = 0; i < lineBytes.Length - 1; i += 2)
                {
                    char ch = Encoding.Unicode.GetChars(lineBytes, i, 2) [0];
                    if (char.IsLetterOrDigit(ch) || char.IsWhiteSpace(ch) || char.IsSymbol(ch) || char.IsPunctuation(ch))
                    {
                        sb.Append(ch);
                    }
                    else
                    {
                        sb.Append(".");
                    }
                }
                break;

            default:
                throw new NotImplementedException(Editor.Options.StringRepresentationType.ToString());
            }

            layout.Text = sb.ToString();
            Margin.LayoutWrapper result = new LayoutWrapper(layout);
            if (Data.IsSomethingSelected)
            {
                ISegment selection = Data.MainSelection.Segment;
                HandleSelection(selection.Offset, selection.EndOffset, startOffset, endOffset, null, delegate(long start, long end) {
                    result.Layout.SetForeground(Style.Selection, (int)(start - startOffset) / 2, (int)(end - start) / 2);
                    result.Layout.SetBackground(Style.SelectionBg, (int)(start - startOffset) / 2, (int)(end - start) / 2);
                });
            }
            return(result);
        }
        protected override LayoutWrapper RenderLine(long line)
        {
            Pango.Layout layout = new Pango.Layout(Editor.PangoContext);
            layout.FontDescription = Editor.Options.Font;
            StringBuilder sb          = new StringBuilder();
            long          startOffset = line * Editor.BytesInRow;
            long          endOffset   = System.Math.Min(startOffset + Editor.BytesInRow, Data.Length);

            byte[] lineBytes = Data.GetBytes(startOffset, (int)(endOffset - startOffset));
            for (int i = 0; i < lineBytes.Length; i++)
            {
                byte b  = lineBytes[i];
                char ch = (char)b;
                if (b < 128 && (Char.IsLetterOrDigit(ch) || Char.IsPunctuation(ch)))
                {
                    sb.Append(ch);
                }
                else
                {
                    sb.Append(".");
                }
            }

            layout.SetText(sb.ToString());
            char[] lineChars = layout.Text.ToCharArray();
            Margin.LayoutWrapper result = new LayoutWrapper(layout);
            uint curIndex = 0, byteIndex = 0;

            if (Data.IsSomethingSelected)
            {
                ISegment selection = Data.MainSelection.Segment;
                HandleSelection(selection.Offset, selection.EndOffset, startOffset, endOffset, null, delegate(long start, long end)
                {
                    Pango.AttrForeground selectedForeground = new Pango.AttrForeground(Style.Selection.Red,
                                                                                       Style.Selection.Green,
                                                                                       Style.Selection.Blue);
                    selectedForeground.StartIndex = TranslateToUTF8Index(lineChars, (uint)(start - startOffset), ref curIndex, ref byteIndex);
                    selectedForeground.EndIndex   = TranslateToUTF8Index(lineChars, (uint)(end - startOffset), ref curIndex, ref byteIndex);

                    result.Add(selectedForeground);

                    Pango.AttrBackground attrBackground = new Pango.AttrBackground(Style.SelectionBg.Red,
                                                                                   Style.SelectionBg.Green,
                                                                                   Style.SelectionBg.Blue);
                    attrBackground.StartIndex = selectedForeground.StartIndex;
                    attrBackground.EndIndex   = selectedForeground.EndIndex;
                    result.Add(attrBackground);
                });
            }
            result.SetAttributes();
            return(result);
        }
Пример #6
0
        internal protected override void Draw(Gdk.Drawable drawable, Gdk.Rectangle area, long line, int x, int y)
        {
            drawable.DrawRectangle(GetGC(Style.HexOffsetBg), true, x, y, Width, Editor.LineHeight);
            LayoutWrapper layout = GetLayout(line);
            int           w, h;

            layout.Layout.GetPixelSize(out w, out h);
            drawable.DrawLayout(GetGC(line != Caret.Line ? Style.HexOffset : Style.HexOffsetHighlighted), x + Width - w - 4, y, layout.Layout);
            if (layout.IsUncached)
            {
                layout.Dispose();
            }
        }
        internal protected override void Draw(Gdk.Drawable drawable, Gdk.Rectangle area, long line, int x, int y)
        {
            drawable.DrawRectangle(bgGC, true, x, y, Width, Editor.LineHeight);
            LayoutWrapper layout = GetLayout(line);

            if (!Data.IsSomethingSelected && Caret.InTextEditor && line == Data.Caret.Line)
            {
                drawable.DrawRectangle(GetGC(Style.HighlightOffset), true, CalculateCaretXPos(false), y, byteWidth, Editor.LineHeight);
            }

            drawable.DrawLayout(fgGC, x, y, layout.Layout);
            if (layout.IsUncached)
            {
                layout.Dispose();
            }
        }
        protected override LayoutWrapper RenderLine(long line)
        {
            Pango.Layout layout = new Pango.Layout(Editor.PangoContext);
            layout.FontDescription = Editor.Options.Font;
            layout.Tabs            = tabArray;
            StringBuilder sb          = new StringBuilder();
            long          startOffset = line * Editor.BytesInRow;
            long          endOffset   = System.Math.Min(startOffset + Editor.BytesInRow, Data.Length);

            byte[] lineBytes = Data.GetBytes(startOffset, (int)(endOffset - startOffset));
            for (int i = 0; i < lineBytes.Length; i++)
            {
                sb.Append(string.Format("{0:X2}", lineBytes[i]));
                if (i % Editor.Options.GroupBytes == 0)
                {
                    sb.Append("\t");
                }
            }

            layout.SetText(sb.ToString());
            char[] lineChars = sb.ToString().ToCharArray();
            Margin.LayoutWrapper result = new LayoutWrapper(layout);
            uint curIndex = 0, byteIndex = 0;

            if (Data.IsSomethingSelected)
            {
                ISegment selection = Data.MainSelection.Segment;
                HandleSelection(selection.Offset, selection.EndOffset, startOffset, endOffset, null, delegate(long start, long end)
                {
                    Pango.AttrForeground selectedForeground = new Pango.AttrForeground(Style.Selection.Red,
                                                                                       Style.Selection.Green,
                                                                                       Style.Selection.Blue);
                    selectedForeground.StartIndex = TranslateToUTF8Index(lineChars, TranslateColumn(start - startOffset), ref curIndex, ref byteIndex);
                    selectedForeground.EndIndex   = TranslateToUTF8Index(lineChars, TranslateColumn(end - startOffset) - 1, ref curIndex, ref byteIndex);
                    result.Add(selectedForeground);

                    Pango.AttrBackground attrBackground = new Pango.AttrBackground(Style.SelectionBg.Red,
                                                                                   Style.SelectionBg.Green,
                                                                                   Style.SelectionBg.Blue);
                    attrBackground.StartIndex = selectedForeground.StartIndex;
                    attrBackground.EndIndex   = selectedForeground.EndIndex;
                    result.Add(attrBackground);
                });
            }
            result.SetAttributes();
            return(result);
        }
        internal protected override void Draw(Gdk.Drawable drawable, Gdk.Rectangle area, long line, int x, int y)
        {
            drawable.DrawRectangle(bgGC, true, x, y, Width, Editor.LineHeight);
            LayoutWrapper layout = GetLayout(line);

            if (!Data.IsSomethingSelected && !Caret.InTextEditor && line == Data.Caret.Line)
            {
                int column  = (int)(Caret.Offset % BytesInRow);
                int xOffset = charWidth * column;
                drawable.DrawRectangle(GetGC(Style.HighlightOffset), true, x + xOffset, y, charWidth, Editor.LineHeight);
            }
            drawable.DrawLayout(fgGC, x, y, layout.Layout);
            if (layout.IsUncached)
            {
                layout.Dispose();
            }
        }
		protected override LayoutWrapper RenderLine (long line)
		{
			Pango.Layout layout = new Pango.Layout (Editor.PangoContext);
			layout.FontDescription = Editor.Options.Font;
			StringBuilder sb = new StringBuilder ();
			long startOffset = line * Editor.BytesInRow;
			long endOffset   = System.Math.Min (startOffset + Editor.BytesInRow, Data.Length);
			byte[] lineBytes = Data.GetBytes (startOffset, (int)(endOffset - startOffset));
			for (int i = 0; i < lineBytes.Length; i++) {
				byte b = lineBytes[i];
				char ch = (char)b;
				if (b < 128 && (Char.IsLetterOrDigit (ch) || Char.IsPunctuation (ch))) {
					sb.Append (ch);
				} else {
					sb.Append (".");
				}
			}
			
			layout.SetText (sb.ToString ());
			char[] lineChars = layout.Text.ToCharArray ();
			Margin.LayoutWrapper result = new LayoutWrapper (layout);
			uint curIndex = 0, byteIndex = 0;
			if (Data.IsSomethingSelected) {
				ISegment selection = Data.MainSelection.Segment;
				HandleSelection (selection.Offset, selection.EndOffset, startOffset, endOffset, null, delegate(long start, long end) {
					Pango.AttrForeground selectedForeground = new Pango.AttrForeground (Style.Selection.Red, 
					                                                                    Style.Selection.Green, 
					                                                                    Style.Selection.Blue);
					selectedForeground.StartIndex = TranslateToUTF8Index (lineChars, (uint)(start - startOffset), ref curIndex, ref byteIndex);
					selectedForeground.EndIndex = TranslateToUTF8Index (lineChars, (uint)(end - startOffset), ref curIndex, ref byteIndex);
					
					result.Add (selectedForeground);
					
					Pango.AttrBackground attrBackground = new Pango.AttrBackground (Style.SelectionBg.Red, 
					                                                                Style.SelectionBg.Green, 
					                                                                Style.SelectionBg.Blue);
					attrBackground.StartIndex = selectedForeground.StartIndex;
					attrBackground.EndIndex = selectedForeground.EndIndex;
					result.Add (attrBackground);

				});
			}
			result.SetAttributes ();
			return result;
		}
Пример #11
0
        internal protected override void Draw(Context ctx, Rectangle area, long line, double x, double y)
        {
            ctx.Rectangle(x, y, Width, Editor.LineHeight);
            ctx.SetColor(Style.HexOffsetBg);
            ctx.Fill();

            if (line >= 0 && line * Editor.BytesInRow < Data.Length)
            {
                LayoutWrapper layout = GetLayout(line);
                var           sz     = layout.Layout.GetSize();
                ctx.SetColor(line != Caret.Line ? Style.HexOffset : Style.HexOffsetHighlighted);
                ctx.DrawTextLayout(layout.Layout, x + Width - sz.Width - 4, y);
                if (layout.IsUncached)
                {
                    layout.Dispose();
                }
            }
        }
        int CalculateCaretXPos(bool useSubPositon)
        {
            int byteInRow   = (int)Caret.Offset % BytesInRow;
            int groupNumber = byteInRow / Editor.Options.GroupBytes;
            int groupByte   = byteInRow % Editor.Options.GroupBytes;
            int caretIndex  = groupNumber * (Editor.Options.GroupBytes * 2 + 1) + groupByte * 2;

            if (useSubPositon)
            {
                caretIndex += Caret.SubPosition;
            }
            LayoutWrapper layout = GetLayout((int)Caret.Line);

            Pango.Rectangle rectangle = layout.Layout.IndexToPos(caretIndex);
            if (layout.IsUncached)
            {
                layout.Dispose();
            }
            return(XOffset + (int)(rectangle.X / Pango.Scale.PangoScale));
        }
Пример #13
0
        internal protected override void Draw(Context ctx, Rectangle area, long line, double x, double y)
        {
            ctx.Rectangle(x, y, Width, Editor.LineHeight);
            ctx.SetColor(Style.HexDigitBg);
            ctx.Fill();

            LayoutWrapper layout = GetLayout(line);
            char          ch;

            if (!Data.IsSomethingSelected && Caret.InTextEditor && line == Data.Caret.Line)
            {
                ctx.Rectangle(CalculateCaretXPos(false, out ch), y, byteWidth, Editor.LineHeight);
                ctx.SetColor(Style.HighlightOffset);
                ctx.Fill();
            }
            ctx.SetColor(Style.HexDigit);
            ctx.DrawTextLayout(layout.Layout, x, y);
            if (layout.IsUncached)
            {
                layout.Dispose();
            }
        }
Пример #14
0
        double CalculateCaretXPos(bool useSubPositon, out char ch)
        {
            int byteInRow   = (int)Caret.Offset % BytesInRow;
            int groupNumber = byteInRow / Editor.Options.GroupBytes;
            int groupByte   = byteInRow % Editor.Options.GroupBytes;
            int caretIndex  = groupNumber * (Editor.Options.GroupBytes * 2 + 1) + groupByte * 2;

            if (useSubPositon)
            {
                caretIndex += Caret.SubPosition;
            }
            LayoutWrapper layout    = GetLayout((int)Caret.Line);
            var           rectangle = layout.Layout.GetCoordinateFromIndex(caretIndex);
            var           text      = layout.Layout.Text;

            ch = caretIndex < text.Length ? text [caretIndex] : ' ';
            if (layout.IsUncached)
            {
                layout.Dispose();
            }
            return(XOffset + rectangle.X);
        }
Пример #15
0
        protected override LayoutWrapper RenderLine(long line)
        {
            var layout = new TextLayout(Editor);

            layout.Font = Editor.Options.Font;
            StringBuilder sb          = new StringBuilder();
            long          startOffset = line * Editor.BytesInRow;
            long          endOffset   = System.Math.Min(startOffset + Editor.BytesInRow, Data.Length);

            byte[] lineBytes = Data.GetBytes(startOffset, (int)(endOffset - startOffset));
            for (int i = 0; i < lineBytes.Length; i++)
            {
                byte b  = lineBytes[i];
                char ch = (char)b;
                if (b < 128 && (Char.IsLetterOrDigit(ch) || Char.IsPunctuation(ch)))
                {
                    sb.Append(ch);
                }
                else
                {
                    sb.Append(".");
                }
            }

            layout.Text = sb.ToString();
            Margin.LayoutWrapper result = new LayoutWrapper(layout);
            if (Data.IsSomethingSelected)
            {
                ISegment selection = Data.MainSelection.Segment;
                HandleSelection(selection.Offset, selection.EndOffset, startOffset, endOffset, null, delegate(long start, long end) {
                    result.Layout.SetForeground(Style.Selection, (int)(start - startOffset), (int)(end - start));
                    result.Layout.SetBackgound(Style.SelectionBg, (int)(start - startOffset), (int)(end - start));
                });
            }
            return(result);
        }
Пример #16
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;
		}
Пример #17
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 ();
		}
Пример #18
0
		void DecorateTabsAndSpaces (Cairo.Context ctx, LayoutWrapper layout, int offset, int length, double xPos, double y, int selectionStart, int selectionEnd)
		{
			uint curIndex = 0, byteIndex = 0;
			bool first = true, oldSelected = false;
			int index, trailing;
			layout.Layout.XyToIndex ((int)textEditor.HAdjustment.Value, 0, out index, out trailing);

			for (int i = index; i < layout.LineChars.Length; i++) {
				char ch = layout.LineChars [i];
				if (ch != ' ' && ch != '\t')
					continue;
				bool selected = selectionStart <= offset + i && offset + i < selectionEnd;
				if (first || oldSelected != selected) {
					ctx.Color = selected ? SelectionColor.CairoColor : ColorStyle.WhitespaceMarker;
					first = false;
					oldSelected = selected;
				}
				Pango.Rectangle pos = layout.Layout.IndexToPos ((int)TranslateToUTF8Index (layout.LineChars, (uint)i, ref curIndex, ref byteIndex));
				double xpos = xPos + pos.X / Pango.Scale.PangoScale;
				if (xpos > textEditor.Allocation.Width)
					break;
				if (ch == '\t') {
					DrawTabMarker (ctx, selected, xpos, y);
				} else {
					DrawSpaceMarker (ctx, selected, xpos, y);
				}
			}
		}
Пример #19
0
			bool ConsumeLayout (LayoutWrapper layoutWrapper, int xp, int yp)
			{
				int trailing;
				bool isInside = layoutWrapper.Layout.XyToIndex (xp, yp, out index, out trailing);

				if (isInside) {
					int lineNr;
					int xp1, xp2;
					layoutWrapper.Layout.IndexToLineX (index, false, out lineNr, out xp1);
					layoutWrapper.Layout.IndexToLineX (index + 1, false, out lineNr, out xp2);
					index = TranslateIndexToUTF8 (layoutWrapper.Layout.Text, index);

					if (snapCharacters && !IsNearX1 (xp, xp1, xp2))
						index++;
					return true;
				}
				index = line.Length;
				return false;
			}
Пример #20
0
		protected override LayoutWrapper RenderLine (long line)
		{
			var layout = new TextLayout (Editor);
			layout.Font = Editor.Options.Font;
			StringBuilder sb = new StringBuilder ();
			long startOffset = line * Editor.BytesInRow;
			long endOffset   = System.Math.Min (startOffset + Editor.BytesInRow, Data.Length);
			byte[] lineBytes = Data.GetBytes (startOffset, (int)(endOffset - startOffset));
			switch (Editor.Options.StringRepresentationType) {
			case StringRepresentationTypes.ASCII:
				for (int i = 0; i < lineBytes.Length; i++) {
					byte b = lineBytes [i];
					char ch = (char)b;
					if (!char.IsControl (ch)) {
						sb.Append (ch);
					} else {
						sb.Append (".");
					}
				}
				break;
			case StringRepresentationTypes.UTF16:
				for (int i = 0; i < lineBytes.Length - 1; i += 2) {

					char ch = Encoding.Unicode.GetChars (lineBytes, i, 2) [0];
					if (char.IsLetterOrDigit (ch) || char.IsWhiteSpace (ch) || char.IsSymbol (ch) || char.IsPunctuation (ch))
						sb.Append (ch);
					else
						sb.Append (".");
				}
				break;
			default:
				throw new NotImplementedException (Editor.Options.StringRepresentationType.ToString ());
			}
			
			layout.Text = sb.ToString ();
			Margin.LayoutWrapper result = new LayoutWrapper (layout);
			if (Data.IsSomethingSelected) {
				ISegment selection = Data.MainSelection.Segment;
				HandleSelection (selection.Offset, selection.EndOffset, startOffset, endOffset, this, new LayoutOffsetPair (startOffset, result.Layout), null, OnSelected);
			}
			return result;
		}
Пример #21
0
			public LayoutDescriptor (DocumentLine line, int offset, int length, LayoutWrapper layout, int selectionStart, int selectionEnd) : base(line, offset, length)
			{
				this.Layout = layout;
				if (selectionEnd >= 0) {
					this.SelectionStart = selectionStart;
					this.SelectionEnd = selectionEnd;
				}
			}
Пример #22
0
		void DrawIndent (Cairo.Context cr, LayoutWrapper layout, DocumentLine line, double xPos, double y)
		{
			if (!textEditor.Options.DrawIndentationMarkers)
				return;
			if (line.Length == 0) {
				var nextLine = line.NextLine;
				while (nextLine != null && nextLine.Length == 0)
					nextLine = nextLine.NextLine;
				if (nextLine != null)
					layout = GetLayout (nextLine);
			}
			if (layout.IndentSize == 0)
				return;
			cr.Save ();
			var dotted = new [] { textEditor.Options.Zoom };
			cr.SetDash (dotted, (int)y + textEditor.VAdjustment.Value);
			var top = y;
			var bottom = y + LineHeight;
			if (Caret.Line == line.LineNumber && textEditor.Options.HighlightCaretLine) {
				top += textEditor.Options.Zoom;
				bottom -= textEditor.Options.Zoom;
			}
			for (int i = 0; i < layout.IndentSize; i += textEditor.Options.IndentationSize) {
				var x = System.Math.Floor (xPos + i * charWidth);
				cr.MoveTo (x + 0.5, top);
				cr.LineTo (x + 0.5, bottom);

				cr.Color = ColorStyle.IndentationGuide.Color;
				cr.Stroke ();
			}
			cr.Restore ();
		}
Пример #23
0
		void DecorateTabsAndSpaces (Cairo.Context ctx, LayoutWrapper layout, int offset, int length, double xPos, double y, int selectionStart, int selectionEnd)
		{
			uint curIndex = 0, byteIndex = 0;
			bool first = true, oldSelected = false;
			int index, trailing;
			layout.Layout.XyToIndex ((int)textEditor.HAdjustment.Value, 0, out index, out trailing);
			var curchunk = layout.Chunks != null ? layout.Chunks.FirstOrDefault () : null;
			for (int i = index; i < layout.LineChars.Length; i++) {
				char ch = layout.LineChars [i];
				if (ch != ' ' && ch != '\t')
					continue;
				if (ch == ' ' && !textEditor.Options.IncludeWhitespaces.HasFlag (IncludeWhitespaces.Space))
					continue;
				if (ch == '\t' && !textEditor.Options.IncludeWhitespaces.HasFlag (IncludeWhitespaces.Tab))
					continue;
				bool selected = selectionStart <= offset + i && offset + i < selectionEnd;
				if (first || oldSelected != selected) {
					first = false;
					oldSelected = selected;
				}
				if (!selected && textEditor.Options.ShowWhitespaces != ShowWhitespaces.Always)
					continue;
				Pango.Rectangle pos = layout.Layout.IndexToPos ((int)TranslateToUTF8Index (layout.LineChars, (uint)i, ref curIndex, ref byteIndex));
				double xpos = xPos + pos.X / Pango.Scale.PangoScale;
				if (xpos > textEditor.Allocation.Width)
					break;
				Pango.Rectangle pos2 = layout.Layout.IndexToPos ((int)TranslateToUTF8Index (layout.LineChars, (uint)i + 1, ref curIndex, ref byteIndex));
				double xpos2 = xPos + pos2.X / Pango.Scale.PangoScale;
				Cairo.Color col = new Cairo.Color (0, 0, 0);
				if (SelectionColor.TransparentForeground) {
					while (curchunk != null && curchunk.EndOffset < offset + i)
						curchunk = curchunk.Next;
					if (curchunk != null && curchunk.SpanStack.Count > 0 && curchunk.SpanStack.Peek ().Color != "Plain Text") {
						var chunkStyle = ColorStyle.GetChunkStyle (curchunk.SpanStack.Peek ().Color);
						if (chunkStyle != null)
							col = ColorStyle.GetForeground (chunkStyle);
					} else {
						col = ColorStyle.PlainText.Foreground;
					}
				} else {
					col = selected ? SelectionColor.Foreground : col = ColorStyle.PlainText.Foreground;
				}
				ctx.Color = new Cairo.Color (col.R, col.G, col.B, whitespaceMarkerAlpha);

				if (ch == '\t') {
					DrawTabMarker (ctx, selected, xpos, xpos2, y);
				} else {
					DrawSpaceMarker (ctx, selected, xpos, xpos2, y);
				}
			}
		}
Пример #24
0
		void DecorateTabsAndSpaces (Cairo.Context ctx, LayoutWrapper layout, int offset, double x, double y, int selectionStart, int selectionEnd)
		{
			if (textEditor.Options.IncludeWhitespaces.HasFlag (IncludeWhitespaces.Space)) {
				InnerDecorateTabsAndSpaces (ctx, layout, offset, x, y, selectionStart, selectionEnd, ' ');
			}
			if (textEditor.Options.IncludeWhitespaces.HasFlag (IncludeWhitespaces.Tab)) {
				InnerDecorateTabsAndSpaces (ctx, layout, offset, x, y, selectionStart, selectionEnd, '\t');
			}
		}
Пример #25
0
		protected override LayoutWrapper RenderLine (long line)
		{
			var layout = new TextLayout (Editor);
			layout.Font = Editor.Options.Font;
//			layout.Tabs = tabArray;
			StringBuilder sb = new StringBuilder ();
			long startOffset = line * Editor.BytesInRow;
			long endOffset   = System.Math.Min (startOffset + Editor.BytesInRow, Data.Length);
			byte[] lineBytes = Data.GetBytes (startOffset, (int)(endOffset - startOffset));
			for (int i = 0; i < lineBytes.Length; i++) {
				sb.Append (string.Format ("{0:X2}", lineBytes[i]));
				if (i % Editor.Options.GroupBytes == 0)
					sb.Append (" "); // \t
			}
			
			layout.Text = sb.ToString ();
			Margin.LayoutWrapper result = new LayoutWrapper (layout);
			if (Data.IsSomethingSelected) {
				ISegment selection = Data.MainSelection.Segment;
				HandleSelection (selection.Offset, selection.EndOffset, startOffset, endOffset, null, delegate(long start, long end) {
					result.Layout.SetForeground (Style.Selection, (int)(start - startOffset) * 3, (int)(end - start) * 3 - 1);
					result.Layout.SetBackgound (Style.SelectionBg, (int)(start - startOffset) * 3, (int)(end - start) * 3 - 1);
				});
			}
			return result;
		}
		void DecorateTabsAndSpaces (Cairo.Context ctx, LayoutWrapper layout, int offset, int length, double xPos, double y, int selectionStart, int selectionEnd)
		{
			uint curIndex = 0, byteIndex = 0;
			bool first = true, oldSelected = false;
			for (int i = 0; i < layout.LineChars.Length; i++) {
				char ch = layout.LineChars[i];
				if (ch != ' ' && ch != '\t')
					continue;
				bool selected = selectionStart <= offset + i && offset + i < selectionEnd;
				if (first || oldSelected != selected) {
					ctx.Color = selected ? SelectionColor.CairoColor : ColorStyle.WhitespaceMarker;
					first = false;
					oldSelected = selected;
				}
				Pango.Rectangle pos = layout.Layout.IndexToPos ((int)TranslateToUTF8Index (layout.LineChars, (uint)i, ref curIndex, ref byteIndex));
				int xpos = pos.X;
				if (ch == '\t') {
					DrawTabMarker (ctx, selected, xPos + xpos / Pango.Scale.PangoScale, y);
				} else {
					DrawSpaceMarker (ctx, selected, xPos + xpos / Pango.Scale.PangoScale, y);
				}
			}
		}
		protected override LayoutWrapper RenderLine (long line)
		{
			Pango.Layout layout = new Pango.Layout (Editor.PangoContext);
			layout.FontDescription = Editor.Options.Font;
			layout.Tabs = tabArray;
			StringBuilder sb = new StringBuilder ();
			long startOffset = line * Editor.BytesInRow;
			long endOffset   = System.Math.Min (startOffset + Editor.BytesInRow, Data.Length);
			byte[] lineBytes = Data.GetBytes (startOffset, (int)(endOffset - startOffset));
			for (int i = 0; i < lineBytes.Length; i++) {
				sb.Append (string.Format ("{0:X2}", lineBytes[i]));
				if (i % Editor.Options.GroupBytes == 0)
					sb.Append ("\t");
			}
			
			layout.SetText (sb.ToString ());
			char[] lineChars = sb.ToString ().ToCharArray ();
			Margin.LayoutWrapper result = new LayoutWrapper (layout);
			uint curIndex = 0, byteIndex = 0;
			if (Data.IsSomethingSelected) {
				ISegment selection = Data.MainSelection.Segment;
				HandleSelection (selection.Offset, selection.EndOffset, startOffset, endOffset, null, delegate(long start, long end) {
					Pango.AttrForeground selectedForeground = new Pango.AttrForeground (Style.Selection.Red, 
					                                                                    Style.Selection.Green, 
					                                                                    Style.Selection.Blue);
					selectedForeground.StartIndex = TranslateToUTF8Index (lineChars, TranslateColumn (start - startOffset), ref curIndex, ref byteIndex);
					selectedForeground.EndIndex = TranslateToUTF8Index (lineChars, TranslateColumn (end - startOffset) - 1, ref curIndex, ref byteIndex);
					result.Add (selectedForeground);
					
					Pango.AttrBackground attrBackground = new Pango.AttrBackground (Style.SelectionBg.Red, 
					                                                                Style.SelectionBg.Green, 
					                                                                Style.SelectionBg.Blue);
					attrBackground.StartIndex = selectedForeground.StartIndex;
					attrBackground.EndIndex = selectedForeground.EndIndex;
					result.Add (attrBackground);

				});
			}
			result.SetAttributes ();
			return result;
		}
Пример #28
0
		void InnerDecorateTabsAndSpaces (Cairo.Context ctx, LayoutWrapper layout, int offset, double x, double y, int selectionStart, int selectionEnd, char spaceOrTab)
		{
			var chars = layout.LineChars;
			if (Array.IndexOf (chars, spaceOrTab) == -1)
				return;

			uint curIndex = 0, byteIndex = 0;
			bool first = true, oldSelected = false;
			var curchunk = layout.Chunks != null ? layout.Chunks.FirstOrDefault () : null;

			var dotThickness = textEditor.Options.Zoom * 2;
			var textEditorWidth = textEditor.Allocation.Width;

			//Get 1st visible character index from left based on HAdjustment
			int index, trailing;
			layout.Layout.XyToIndex ((int)textEditor.HAdjustment.Value, 0, out index, out trailing);

			double ypos;
			if (spaceOrTab == ' ') {
				ypos = System.Math.Floor (y + (LineHeight - dotThickness) / 2);
			} else {
				ypos = 0.5 + System.Math.Floor (y + LineHeight / 2);
			}

			var showOnlySelected = textEditor.Options.ShowWhitespaces != ShowWhitespaces.Always;

			var lastColor = new Cairo.Color ();
			bool firstDraw = true;
			var foregroundColor = ColorStyle.PlainText.Foreground;

			int lastIndex = -1;
			int lastPosX = 0;

			for (int i = index; i < chars.Length; i++) {
				if (spaceOrTab != chars [i])
					continue;

				bool selected = selectionStart <= offset + i && offset + i < selectionEnd;
				if (first || oldSelected != selected) {
					first = false;
					oldSelected = selected;
				}

				if (showOnlySelected && !selected)
					continue;
				int line, posX;
				if (lastIndex == i) {
					posX = lastPosX;
				} else {
					layout.Layout.IndexToLineX ((int)TranslateToUTF8Index (chars, (uint)i, ref curIndex, ref byteIndex), false, out line, out posX);
				}
				double xpos = x + posX / Pango.Scale.PangoScale;
				if (xpos > textEditorWidth)
					break;
				layout.Layout.IndexToLineX ((int)TranslateToUTF8Index (chars, (uint)i + 1, ref curIndex, ref byteIndex), false, out line, out posX);
				lastPosX = posX;
				lastIndex = i + 1;
				double xpos2 = x + posX / Pango.Scale.PangoScale;
				var col = new Cairo.Color (0, 0, 0);
				if (SelectionColor.TransparentForeground) {
					while (curchunk != null && curchunk.EndOffset < offset + i)
						curchunk = curchunk.Next;
					if (curchunk != null && curchunk.SpanStack.Count > 0 && curchunk.SpanStack.Peek ().Color != "Plain Text") {
						var chunkStyle = ColorStyle.GetChunkStyle (curchunk.SpanStack.Peek ().Color);
						if (chunkStyle != null)
							col = ColorStyle.GetForeground (chunkStyle);
					} else {
						col = foregroundColor;
					}
				} else {
					col = selected ? SelectionColor.Foreground : foregroundColor;
				}

				if (firstDraw || (lastColor.R != col.R && lastColor.G != col.G && lastColor.B != col.B)) {
					ctx.SetSourceRGBA (col.R, col.G, col.B, whitespaceMarkerAlpha);
					lastColor = col;
					firstDraw = false;
				}

				if (spaceOrTab == ' ') {
					ctx.Rectangle (xpos + (xpos2 - xpos - dotThickness) / 2, ypos, dotThickness, dotThickness);
				} else {
					ctx.MoveTo (0.5 + xpos, ypos);
					ctx.LineTo (0.5 + xpos2 - charWidth / 2, ypos);
				}
			}
			if (!firstDraw) {//Atleast one draw was called
				if (spaceOrTab == ' ') {
					ctx.Fill ();
				} else {
					ctx.Stroke ();
				}
			}
		}
Пример #29
0
		void DecorateTabs (Gdk.Drawable win, LayoutWrapper layout, int offset, int length, int xPos, int y, int selectionStart, int selectionEnd)
		{
			uint curIndex = 0, byteIndex = 0;
			for (int i = 0; i < layout.LineChars.Length; i++) {
				if (layout.LineChars[i] == '\t') {
					Pango.Rectangle pos = layout.Layout.IndexToPos ((int)TranslateToUTF8Index (layout.LineChars, (uint)i, ref curIndex, ref byteIndex));
					int xpos = pos.X;
					DrawTabMarker (win, selectionStart <= offset + i && offset + i < selectionEnd, xPos + xpos / 1024, y);
				}
			}
		}
Пример #30
0
		LayoutWrapper GetVirtualSpaceLayout (DocumentLine line, DocumentLocation location)
		{
			string virtualSpace = "";
			var data = textEditor.GetTextEditorData ();
			if (data.HasIndentationTracker && line.Length == 0) {
				virtualSpace = this.textEditor.GetTextEditorData ().GetIndentationString (location);
			}
			if (location.Column > line.Length + 1 + virtualSpace.Length)
				virtualSpace += new string (' ', location.Column - line.Length - 1 - virtualSpace.Length);
			// predit layout already contains virtual space.
			if (!string.IsNullOrEmpty (textEditor.preeditString))
				virtualSpace = "";
			LayoutWrapper wrapper = new LayoutWrapper (textEditor.LayoutCache.RequestLayout ());
			wrapper.LineChars = virtualSpace.ToCharArray ();
			wrapper.Layout.SetText (virtualSpace);
			wrapper.Layout.Tabs = tabArray;
			wrapper.Layout.FontDescription = textEditor.Options.Font;
			int vy, vx;
			wrapper.Layout.GetSize (out vx, out vy);
			wrapper.Width = wrapper.LastLineWidth = vx / Pango.Scale.PangoScale;
			return wrapper;
		}
Пример #31
0
		void DecorateMatchingBracket (Gdk.Drawable win, LayoutWrapper layout, int offset, int length, int xPos, int y, int selectionStart, int selectionEnd)
		{
			uint curIndex = 0, byteIndex = 0;
			if (offset <= highlightBracketOffset && highlightBracketOffset <= offset + length) {
				int index = highlightBracketOffset - offset;
				Pango.Rectangle rect = layout.Layout.IndexToPos ((int)TranslateToUTF8Index (layout.LineChars, (uint)index, ref curIndex, ref byteIndex));
				
				Gdk.Rectangle bracketMatch = new Gdk.Rectangle (xPos + (int)(rect.X / Pango.Scale.PangoScale), y, (int)(rect.Width / Pango.Scale.PangoScale) - 1, (int)(rect.Height / Pango.Scale.PangoScale) - 1);
				if (BackgroundRenderer == null)
					win.DrawRectangle (GetGC (this.ColorStyle.BracketHighlightRectangle.BackgroundColor), true, bracketMatch);
				
				win.DrawRectangle (GetGC (this.ColorStyle.BracketHighlightRectangle.Color), false, bracketMatch);
			}
		}
Пример #32
0
		void DecorateMatchingBracket (Cairo.Context ctx, LayoutWrapper layout, int offset, int length, double xPos, double y, int selectionStart, int selectionEnd)
		{
			uint curIndex = 0, byteIndex = 0;
			if (offset <= highlightBracketOffset && highlightBracketOffset <= offset + length) {
				int index = highlightBracketOffset - offset;
				Pango.Rectangle rect = layout.Layout.IndexToPos ((int)TranslateToUTF8Index (layout.LineChars, (uint)index, ref curIndex, ref byteIndex));
				
				var bracketMatch = new Cairo.Rectangle (xPos + rect.X / Pango.Scale.PangoScale + 0.5, y + 0.5, (rect.Width / Pango.Scale.PangoScale) - 1, (rect.Height / Pango.Scale.PangoScale) - 1);
				if (BackgroundRenderer == null) {
					ctx.Color = this.ColorStyle.BraceMatchingRectangle.Color;
					ctx.Rectangle (bracketMatch);
					ctx.FillPreserve ();
					ctx.Color = this.ColorStyle.BraceMatchingRectangle.SecondColor;
					ctx.Stroke ();
				}
			}
		}
Пример #33
0
		void DrawLinePart (Gdk.Drawable win, LineSegment line, int offset, int length, ref int pangoPosition, ref bool isSelectionDrawn, int y, int maxX)
		{
			SyntaxMode mode = Document.SyntaxMode != null && textEditor.Options.EnableSyntaxHighlighting ? Document.SyntaxMode : SyntaxMode.Default;
			int selectionStart;
			int selectionEnd;
			if (BackgroundRenderer != null || this.HideSelection) {
				selectionStart = selectionEnd = -1;
			} else {
				GetSelectionOffsets (line, out selectionStart, out selectionEnd);
			}
			
			// ---- new renderer
			LayoutWrapper layout = CreateLinePartLayout (mode, line, offset, length, selectionStart, selectionEnd);
			int width = (int)(layout.PangoWidth / Pango.Scale.PangoScale);
			
			int xPos = (int)(pangoPosition / Pango.Scale.PangoScale);
			bool drawBg = true;
			bool drawText = true;
			foreach (TextMarker marker in line.Markers) {
				IBackgroundMarker bgMarker = marker as IBackgroundMarker;
				if (bgMarker == null || !marker.IsVisible)
					continue;
				isSelectionDrawn |= (marker.Flags & TextMarkerFlags.DrawsSelection) == TextMarkerFlags.DrawsSelection;
				drawText &= bgMarker.DrawBackground (textEditor, win, layout, selectionStart, selectionEnd, offset, offset + length, y, xPos, xPos + width, ref drawBg);
			}
			
			if (DecorateLineBg != null)
				DecorateLineBg (win, layout, offset, length, xPos, y, selectionStart, selectionEnd);
		
			if (!isSelectionDrawn && (layout.StartSet || selectionStart == offset + length)) {
				int startX;
				int endX;
				
				if (selectionStart != offset + length) {
					var start = layout.Layout.IndexToPos ((int)layout.SelectionStartIndex);
					startX = (int)(start.X / Pango.Scale.PangoScale);
					var end = layout.Layout.IndexToPos ((int)layout.SelectionEndIndex);
					endX = (int)(end.X / Pango.Scale.PangoScale);
				} else {
					startX = width;
					endX = startX;
				}
				
				if (textEditor.MainSelection.SelectionMode == SelectionMode.Block && startX == endX) {
					endX = startX + 2;
				}
				DrawRectangleWithRuler (win, xPos + (int)textEditor.HAdjustment.Value - TextStartPosition, new Rectangle (xPos + startX, y, endX - startX, textEditor.LineHeight), this.SelectionColor.BackgroundColor, true);
			}
			
				
			// highlight search results
			ISegment firstSearch;
			int o = offset;
			uint curIndex = 0, byteIndex = 0;
			
			while ((firstSearch = GetFirstSearchResult (o, offset + length)) != null) {
				int x = pangoPosition;
				HandleSelection (line, selectionStart, selectionEnd, firstSearch.Offset, firstSearch.EndOffset, delegate(int start, int end) {
					uint startIndex = (uint)(start - offset);
					uint endIndex = (uint)(end - offset);
					if (startIndex < endIndex && endIndex <= layout.LineChars.Length) {
						uint startTranslated = TranslateToUTF8Index (layout.LineChars, startIndex, ref curIndex, ref byteIndex);
						uint endTranslated = TranslateToUTF8Index (layout.LineChars, endIndex, ref curIndex, ref byteIndex);
						using (Cairo.Context cr = Gdk.CairoHelper.Create (win)) {
							cr.Rectangle (XOffset, 0, textEditor.Allocation.Width - XOffset, textEditor.Allocation.Height);
							cr.Clip ();
							
							int l, x1, x2;
							layout.Layout.IndexToLineX ((int)startTranslated, false, out l, out x1);
							layout.Layout.IndexToLineX ((int)endTranslated, false, out l, out x2);
							x1 += x; 
							x2 += x;
							x1 /= (int)Pango.Scale.PangoScale;
							x2 /= (int)Pango.Scale.PangoScale;
							
							cr.Color = Mono.TextEditor.Highlighting.Style.ToCairoColor (MainSearchResult == null || MainSearchResult.Offset != firstSearch.Offset ? ColorStyle.SearchTextBg : ColorStyle.SearchTextMainBg, AlphaBlendSearchResults ? 0.6 : 1.0);
							FoldingScreenbackgroundRenderer.DrawRoundRectangle (cr, true, true, x1, y, (int)(System.Math.Min (10, width) * textEditor.Options.Zoom), x2 - x1, textEditor.LineHeight);
							cr.Fill ();
						}
						
					}
				}, null);
			
				o = System.Math.Max (firstSearch.EndOffset, o + 1);
			}
			
			
			win.DrawLayout (GetGC (ColorStyle.Default.Color), xPos, y, layout.Layout);
			
			if (DecorateLineFg != null)
				DecorateLineFg (win, layout, offset, length, xPos, y, selectionStart, selectionEnd);

			if (Document.GetLine (Caret.Line) == line) {
				int caretOffset = Caret.Offset;
				if (offset <= caretOffset && caretOffset <= offset + length) {
					Pango.Rectangle strong_pos, weak_pos;
					int index = caretOffset- offset;
					if (offset <= textEditor.preeditOffset && textEditor.preeditOffset < offset + length) {
						index += textEditor.preeditString.Length;
					}
					
					if (Caret.Column > line.EditableLength) {
						string virtualSpace = this.textEditor.GetTextEditorData ().GetVirtualSpaces (Caret.Line, Caret.Column);
						LayoutWrapper wrapper = new LayoutWrapper (PangoUtil.CreateLayout (textEditor));
						wrapper.LineChars = virtualSpace.ToCharArray ();
						wrapper.Layout.SetText (virtualSpace);
						wrapper.Layout.Tabs = tabArray;
						int vy, vx;
						wrapper.Layout.GetSize (out vx, out vy);
						SetVisibleCaretPosition (win, ' ', (int)((pangoPosition + vx + layout.PangoWidth) / Pango.Scale.PangoScale), y);
						xPos = (int)((pangoPosition + layout.PangoWidth) / Pango.Scale.PangoScale);
						
						if (!isSelectionDrawn && (selectionEnd == line.Offset + line.EditableLength)) {
							int startX;
							int endX;
							startX = xPos;
							endX = (int)((pangoPosition + vx + layout.PangoWidth) / Pango.Scale.PangoScale);
							DrawRectangleWithRuler (win, xPos + (int)textEditor.HAdjustment.Value - TextStartPosition, new Rectangle (startX, y, endX - startX, textEditor.LineHeight), this.SelectionColor.BackgroundColor, true);
						}
						
						if (DecorateLineBg != null)
							DecorateLineBg (win, wrapper, offset, length, xPos, y, selectionStart, selectionEnd + virtualSpace.Length);
						if (DecorateLineFg != null)
							DecorateLineFg (win, wrapper, offset, length, xPos, y, selectionStart, selectionEnd + virtualSpace.Length);
						wrapper.Dispose ();
						pangoPosition += vx;
					} else if (index >= 0 && index < length) {
						curIndex = byteIndex = 0;
						layout.Layout.GetCursorPos ((int)TranslateToUTF8Index (layout.LineChars, (uint)index, ref curIndex, ref byteIndex), out strong_pos, out weak_pos);
						char caretChar = Document.GetCharAt (caretOffset);
						if (textEditor.Options.ShowSpaces && caretChar == ' ')
							caretChar = spaceMarkerChar;
						if (textEditor.Options.ShowTabs && caretChar == '\t')
							caretChar = tabMarkerChar;
						SetVisibleCaretPosition (win, caretChar, xPos + (int)(strong_pos.X / Pango.Scale.PangoScale), y);
					} else if (index == length) {
						SetVisibleCaretPosition (win, textEditor.Options.ShowEolMarkers ? eolMarkerChar : ' ', (int)((pangoPosition + layout.PangoWidth) / Pango.Scale.PangoScale), y);
					}
				}
			}

			foreach (TextMarker marker in line.Markers) {
				marker.Draw (textEditor, win, layout.Layout, false, /*selected*/offset, offset + length, y, xPos, xPos + width);
			}
			
			pangoPosition += layout.PangoWidth;
			if (layout.IsUncached)
				layout.Dispose ();
		}
Пример #34
0
		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 ();
		}
Пример #35
0
			public LayoutDescriptor (LineSegment line, int offset, int length, LayoutWrapper layout, int selectionStart, int selectionEnd) : base(line, offset, length)
			{
				this.Layout = layout;
				this.SelectionStart = selectionStart;
				this.SelectionEnd = selectionEnd;
			}
Пример #36
0
		public LayoutWrapper CreateLinePartLayout (ISyntaxMode mode, DocumentLine line, int logicalRulerColumn, int offset, int length, int selectionStart, int selectionEnd)
		{
			bool containsPreedit = textEditor.ContainsPreedit (offset, length);
			LayoutDescriptor descriptor;
			if (!containsPreedit && layoutDict.TryGetValue (line, out descriptor)) {
				bool isInvalid;
				if (descriptor.Equals (line, offset, length, selectionStart, selectionEnd, out isInvalid) && descriptor.Layout != null) {
					return descriptor.Layout;
				}
				descriptor.Dispose ();
				layoutDict.Remove (line);
			}
			var wrapper = new LayoutWrapper (PangoUtil.CreateLayout (textEditor));
			wrapper.IsUncached = containsPreedit;
			if (logicalRulerColumn < 0)
				logicalRulerColumn = line.GetLogicalColumn (textEditor.GetTextEditorData (), textEditor.Options.RulerColumn);
			var atts = new FastPangoAttrList ();
			wrapper.Layout.Alignment = Pango.Alignment.Left;
			wrapper.Layout.FontDescription = textEditor.Options.Font;
			wrapper.Layout.Tabs = tabArray;
			if (textEditor.Options.WrapLines) {
				wrapper.Layout.Wrap = Pango.WrapMode.WordChar;
				wrapper.Layout.Width = (int)((textEditor.Allocation.Width - XOffset - TextStartPosition) * Pango.Scale.PangoScale);
			}
			StringBuilder textBuilder = new StringBuilder ();
			var chunks = GetCachedChunks (mode, Document, textEditor.ColorStyle, line, offset, length);
			wrapper.Chunks = chunks;
			foreach (var chunk in chunks) {
				try {
					textBuilder.Append (Document.GetTextAt (chunk));
				} catch {
					Console.WriteLine (chunk);
				}
			}
			int lineOffset = line.Offset;
			string lineText = textBuilder.ToString ();
			uint preeditLength = 0;
			
			if (containsPreedit) {
				if (textEditor.GetTextEditorData ().IsCaretInVirtualLocation) {
					lineText = textEditor.GetTextEditorData ().GetIndentationString (textEditor.Caret.Location) + textEditor.preeditString;
				} else {
					lineText = lineText.Insert (textEditor.preeditOffset - offset, textEditor.preeditString);
				}
				preeditLength = (uint)textEditor.preeditString.Length;
			}
			char[] lineChars = lineText.ToCharArray ();
			//int startOffset = offset, endOffset = offset + length;
			uint curIndex = 0, byteIndex = 0;
			uint curChunkIndex = 0, byteChunkIndex = 0;
			
			uint oldEndIndex = 0;
			foreach (Chunk chunk in chunks) {
				ChunkStyle chunkStyle = chunk != null ? textEditor.ColorStyle.GetChunkStyle (chunk) : null;
				foreach (TextLineMarker marker in line.Markers)
					chunkStyle = marker.GetStyle (chunkStyle);

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

					uint startIndex = (uint)(oldEndIndex);
					uint endIndex = (uint)(startIndex + chunk.Length);
					oldEndIndex = endIndex;
					var markers = Document.GetTextSegmentMarkersAt (line).Where (m => m.IsVisible).ToArray ();
					HandleSelection (lineOffset, logicalRulerColumn, selectionStart, selectionEnd, chunk.Offset, chunk.EndOffset, delegate(int start, int end) {
						if (containsPreedit) {
							if (textEditor.preeditOffset < start)
								start += (int)preeditLength;
							if (textEditor.preeditOffset < end)
								end += (int)preeditLength;
						}
						var si = TranslateToUTF8Index (lineChars, (uint)(startIndex + start - chunk.Offset), ref curIndex, ref byteIndex);
						var ei = TranslateToUTF8Index (lineChars, (uint)(startIndex + end - chunk.Offset), ref curIndex, ref byteIndex);
						var color = ColorStyle.GetForeground (chunkStyle);
						foreach (var marker in markers) {
							var chunkMarker = marker as IChunkMarker;
							if (chunkMarker == null)
								continue;
							chunkMarker.ChangeForeColor (textEditor, chunk, ref color);
						}
						atts.AddForegroundAttribute ((HslColor)color, si, ei);
						
						if (!chunkStyle.TransparentBackground && GetPixel (ColorStyle.PlainText.Background) != GetPixel (chunkStyle.Background)) {
							wrapper.AddBackground (chunkStyle.Background, (int)si, (int)ei);
						} else if (chunk.SpanStack != null && ColorStyle != null) {
							foreach (var span in chunk.SpanStack) {
								if (span == null || string.IsNullOrEmpty (span.Color))
									continue;
								var spanStyle = ColorStyle.GetChunkStyle (span.Color);
								if (spanStyle != null && !spanStyle.TransparentBackground && GetPixel (ColorStyle.PlainText.Background) != GetPixel (spanStyle.Background)) {
									wrapper.AddBackground (spanStyle.Background, (int)si, (int)ei);
									break;
								}
							}
						}
					}, delegate(int start, int end) {
						if (containsPreedit) {
							if (textEditor.preeditOffset < start)
								start += (int)preeditLength;
							if (textEditor.preeditOffset < end)
								end += (int)preeditLength;
						}
						var si = TranslateToUTF8Index (lineChars, (uint)(startIndex + start - chunk.Offset), ref curIndex, ref byteIndex);
						var ei = TranslateToUTF8Index (lineChars, (uint)(startIndex + end - chunk.Offset), ref curIndex, ref byteIndex);
						var color = !SelectionColor.TransparentForeground ? SelectionColor.Foreground : ColorStyle.GetForeground (chunkStyle);
						foreach (var marker in markers) {
							var chunkMarker = marker as IChunkMarker;
							if (chunkMarker == null)
								continue;
							chunkMarker.ChangeForeColor (textEditor, chunk, ref color);
						}
						atts.AddForegroundAttribute ((HslColor)color, si, ei);
						if (!wrapper.StartSet)
							wrapper.SelectionStartIndex = (int)si;
						wrapper.SelectionEndIndex = (int)ei;
					});

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

					if (chunkStyle.FontWeight != Xwt.Drawing.FontWeight.Normal)
						atts.AddWeightAttribute ((Pango.Weight)chunkStyle.FontWeight, translatedStartIndex, translatedEndIndex);

					if (chunkStyle.FontStyle != Xwt.Drawing.FontStyle.Normal)
						atts.AddStyleAttribute ((Pango.Style)chunkStyle.FontStyle, translatedStartIndex, translatedEndIndex);

					if (chunkStyle.Underline)
						atts.AddUnderlineAttribute (Pango.Underline.Single, translatedStartIndex, translatedEndIndex);
				}
			}
			if (containsPreedit) {
				var si = TranslateToUTF8Index (lineChars, (uint)(textEditor.preeditOffset - offset), ref curIndex, ref byteIndex);
				var ei = TranslateToUTF8Index (lineChars, (uint)(textEditor.preeditOffset - offset + preeditLength), ref curIndex, ref byteIndex);

				if (textEditor.GetTextEditorData ().IsCaretInVirtualLocation) {
					uint len = (uint)textEditor.GetTextEditorData ().GetIndentationString (textEditor.Caret.Location).Length;
					si += len;
					ei += len;
				}

				atts.AddForegroundAttribute ((HslColor)ColorStyle.PlainText.Foreground, si, ei);
				var hasBackground = wrapper.BackgroundColors.Any (bg => bg.FromIdx <= si && bg.ToIdx >= ei);
				if (hasBackground)
					atts.AddBackgroundAttribute ((HslColor)ColorStyle.PlainText.Background, si, ei);
				atts.InsertOffsetList (textEditor.preeditAttrs, si, ei);
			}
			wrapper.LineChars = lineChars;
			wrapper.Layout.SetText (lineText);
			wrapper.IndentSize = 0;
			for (int i = 0; i < lineChars.Length; i++) {
				char ch = lineChars [i];
				if (ch == ' ') {
					wrapper.IndentSize ++;
				} else if (ch == '\t') {
					wrapper.IndentSize = GetNextTabstop (textEditor.GetTextEditorData (), wrapper.IndentSize);
				} else {
					break;
				}
			}

			var nextLine = line.NextLine;
			wrapper.EolSpanStack = nextLine != null ? nextLine.StartSpan : null;
			atts.AssignTo (wrapper.Layout);
			atts.Dispose ();
			int w, h;
			wrapper.Layout.GetSize (out w, out h);
			wrapper.PangoWidth = w;

			selectionStart = System.Math.Max (line.Offset - 1, selectionStart);
			selectionEnd = System.Math.Min (line.EndOffsetIncludingDelimiter + 1, selectionEnd);
			descriptor = new LayoutDescriptor (line, offset, length, wrapper, selectionStart, selectionEnd);
			if (!containsPreedit)
				layoutDict [line] = descriptor;
			//textEditor.GetTextEditorData ().HeightTree.SetLineHeight (line.LineNumber, System.Math.Max (LineHeight, System.Math.Floor (h / Pango.Scale.PangoScale)));
			return wrapper;
		}
Пример #37
0
		LayoutWrapper GetCachedLayout (LineSegment line, int offset, int length, int selectionStart, int selectionEnd, Action<LayoutWrapper> createNew)
		{
			bool containsPreedit = offset <= textEditor.preeditOffset && textEditor.preeditOffset <= offset + length;
			LayoutDescriptor descriptor;
			if (!containsPreedit && layoutDict.TryGetValue (line, out descriptor)) {
				bool isInvalid;
				if (descriptor.Equals (line, offset, length, selectionStart, selectionEnd, out isInvalid)) {
					return descriptor.Layout;
				}
				descriptor.Dispose ();
				layoutDict.Remove (line);
			}
			
			var wrapper = new LayoutWrapper (PangoUtil.CreateLayout (textEditor));
			wrapper.IsUncached = containsPreedit;
			createNew (wrapper);
			selectionStart = System.Math.Max (line.Offset - 1, selectionStart);
			selectionEnd = System.Math.Min (line.EndOffset + 1, selectionEnd);
			descriptor = new LayoutDescriptor (line, offset, length, wrapper, selectionStart, selectionEnd);
			if (!containsPreedit)
				layoutDict[line] = descriptor;
			return wrapper;
		}