IEnumerable <KeyValuePair <LineElementKind, int> > GetColumnPositions(HexBufferLine line) { var columns = line.ColumnOrder.Where(a => line.IsColumnPresent(a)).ToArray(); for (int i = 1; i < columns.Length; i++) { Debug.Assert(i < 3); if (i >= 3) { break; } var colSpan1 = line.LineProvider.GetColumnSpan(columns[i - 1]); var colSpan2 = line.LineProvider.GetColumnSpan(columns[i]); Debug.Assert(colSpan1.End < colSpan2.Start); var kind = i == 1 ? LineElementKind.Column0 : LineElementKind.Column1; yield return(new KeyValuePair <LineElementKind, int>(kind, colSpan1.End)); } if (line.IsValuesColumnPresent) { var spanInfos = line.GetValuesSpans(line.BufferSpan, HexSpanSelectionFlags.Group0 | HexSpanSelectionFlags.Group1).ToArray(); for (int i = 1; i < spanInfos.Length; i++) { Debug.Assert(spanInfos[i - 1].TextSpan.End == spanInfos[i].TextSpan.Start); int linePosition = spanInfos[i - 1].TextSpan.End - 1; var kind = i % 2 == 1 ? LineElementKind.Group0 : LineElementKind.Group1; yield return(new KeyValuePair <LineElementKind, int>(kind, linePosition)); } } }
public bool HasSameValueAs(HexBufferLine line, HexCell cell) { var index = (long)(cell.BufferStart - line.BufferStart).ToUInt64(); if (line.HexBytes.AllValid == true) { // Nothing to do } else if (line.HexBytes.AllValid == false) { // Never mark non-existent data return(false); } else { for (long i = 0; i < cell.BufferSpan.Length; i++) { if (!line.HexBytes.IsValid(index + i)) { return(false); } } } line.HexBytes.ReadBytes(index, TempData, 0, TempData.Length); return(CompareArrays(TempData, Data)); }
public bool TryUpdate(HexCellPosition cellPosition, HexBufferLine line, HexCell cell) { if (cell == null) { return(false); } var oldBufferSpan = BufferSpan; Debug.Assert(cell.BufferSpan.Length <= Data.Length); BufferSpan = cell.BufferSpan; bool dataDifferent; if (oldBufferSpan != BufferSpan) { BufferSpan.Buffer.ReadBytes(BufferSpan.Start, TempData); dataDifferent = !CompareArrays(TempData, Data); if (dataDifferent) { Array.Copy(TempData, Data, Data.Length); } } else { dataDifferent = false; } return(dataDifferent); }
/// <summary> /// Constructor /// </summary> /// <param name="line">Line info</param> /// <param name="lineSpan">Line span to classify</param> public HexClassificationContext(HexBufferLine line, VST.Span lineSpan) { if (line == null) throw new ArgumentNullException(nameof(line)); if (!line.TextSpan.Contains(lineSpan)) throw new ArgumentOutOfRangeException(nameof(lineSpan)); Line = line; LineSpan = lineSpan; }
/// <summary> /// Adds an adornment. Returns true if the adornment was added. /// </summary> /// <param name="behavior">Positioning behavior</param> /// <param name="line">Line</param> /// <param name="tag">Tag</param> /// <param name="adornment">Adornment</param> /// <param name="removedCallback">Called when the adornment is removed</param> /// <returns></returns> public bool AddAdornment(VSTE.AdornmentPositioningBehavior behavior, HexBufferLine line, object tag, UIElement adornment, VSTE.AdornmentRemovedCallback removedCallback) { if (line == null) { throw new ArgumentNullException(nameof(line)); } return(AddAdornment(behavior, line.BufferSpan, tag, adornment, removedCallback)); }
/// <summary> /// Constructor /// </summary> /// <param name="view">Hex view</param> /// <param name="line">Line</param> /// <param name="textPosition">Text position</param> public HexMouseHoverEventArgs(HexView view, HexBufferLine line, int textPosition) { if (textPosition < 0) { throw new ArgumentOutOfRangeException(nameof(textPosition)); } View = view ?? throw new ArgumentNullException(nameof(view)); Line = line ?? throw new ArgumentNullException(nameof(line)); TextPosition = textPosition; }
public override HexFormattedLine FormatLineInVisualBuffer(HexBufferLine line) { if (line == null) { throw new ArgumentNullException(nameof(line)); } var seqColl = HexAndAdornmentSequencer.CreateHexAndAdornmentCollection(line); var linePartsCollection = CreateLinePartsCollection(seqColl, line); var textSource = new HexLinePartsTextSource(linePartsCollection); TextLineBreak previousLineBreak = null; double autoIndent = BaseIndentation; int column = 0; int linePartsIndex = 0; var lineParts = linePartsCollection.LineParts; textSource.SetMaxLineLength(MAX_LINE_LENGTH); var textLine = textFormatter.FormatLine(textSource, column, 0, defaultTextParagraphProperties, previousLineBreak); int startColumn = column; int length = TF.TextLineExtensions.GetLength(textLine, textSource.EndOfLine); column += length; int linePartsEnd = linePartsIndex; Debug.Assert(lineParts.Count == 0 || linePartsEnd < lineParts.Count); while (linePartsEnd < lineParts.Count) { var part = lineParts[linePartsEnd]; linePartsEnd++; if (column <= part.Column + part.ColumnLength) { break; } } linePartsEnd--; var startPos = textSource.ConvertColumnToLinePosition(startColumn); var endPos = textSource.ConvertColumnToLinePosition(column); if (column >= textSource.Length) { endPos = line.TextSpan.End; linePartsEnd = lineParts.Count - 1; } var lineSpan = VST.Span.FromBounds(startPos, endPos); var formattedLine = new HexFormattedLineImpl(linePartsCollection, linePartsIndex, linePartsEnd - linePartsIndex + 1, startColumn, column, line, lineSpan, textLine, autoIndent, ColumnWidth); Debug.Assert(column == textSource.Length); return(formattedLine); }
/// <summary> /// Constructor /// </summary> /// <param name="view">Hex view</param> /// <param name="line">Line</param> /// <param name="textPosition">Text position</param> public HexMouseHoverEventArgs(HexView view, HexBufferLine line, int textPosition) { if (view == null) throw new ArgumentNullException(nameof(view)); if (line == null) throw new ArgumentNullException(nameof(line)); if (textPosition < 0) throw new ArgumentOutOfRangeException(nameof(textPosition)); View = view; Line = line; TextPosition = textPosition; }
static bool EqualLines(HexBufferLine a, HexBufferLine b) { if ((object)a == b) { return(true); } if ((object)a == null || (object)b == null) { return(false); } return(a.LineProvider == b.LineProvider && a.BufferSpan.Equals(b.BufferSpan)); }
public override void EnsureSpanVisible(HexBufferLine line, VST.Span span, VSTE.EnsureSpanVisibleOptions options) { if (line == null) { throw new ArgumentNullException(nameof(line)); } if (line.Buffer != hexView.Buffer) { throw new ArgumentException(); } EnsureSpanVisibleCore(new HexLineSpan(line, span), options); }
/// <summary> /// Removes all matching adornments /// </summary> /// <param name="line">Line</param> /// <param name="match">Returns true if the adornment should be removed</param> public void RemoveMatchingAdornments(HexBufferLine line, Predicate <HexAdornmentLayerElement> match) { if (line == null) { throw new ArgumentNullException(nameof(line)); } if (match == null) { throw new ArgumentNullException(nameof(match)); } RemoveMatchingAdornments(line.BufferSpan, match); }
protected override void DisposeCore() { isValid = false; foreach (var t in textLines) { t.Dispose(); } bufferLine = null !; linePartsCollection = null !; textLines = null !; drawingVisual = null !; }
/// <summary> /// Constructor /// </summary> /// <param name="line">Line info</param> /// <param name="lineSpan">Line span to classify</param> public HexClassificationContext(HexBufferLine line, VST.Span lineSpan) { if (line == null) { throw new ArgumentNullException(nameof(line)); } if (!line.TextSpan.Contains(lineSpan)) { throw new ArgumentOutOfRangeException(nameof(lineSpan)); } Line = line; LineSpan = lineSpan; }
static bool IsValid(HexCell cell, HexBufferLine line) { long len = checked ((long)cell.BufferSpan.Length.ToUInt64()); long b = checked ((long)(cell.BufferStart - line.BufferStart).ToUInt64()); for (long i = 0; i < len; i++) { if (!line.HexBytes.IsValid(b + i)) { return(false); } } return(true); }
static int?GetLinePosition(HexBufferLine line, HexColumnPosition position) { HexCell cell; switch (position.ActiveColumn) { case HexColumnType.Values: cell = line.ValueCells.GetCell(position.ActivePosition.BufferPosition); return(cell?.CellSpan.Start + position.ActivePosition.CellPosition); case HexColumnType.Ascii: cell = line.AsciiCells.GetCell(position.ActivePosition.BufferPosition); return(cell?.CellSpan.Start + position.ActivePosition.CellPosition); case HexColumnType.Offset: default: throw new InvalidOperationException(); } }
public HexFormattedLineImpl(HexLinePartsCollection linePartsCollection, int linePartsIndex, int linePartsLength, int startColumn, int endColumn, HexBufferLine bufferLine, VST.Span lineSpan, TextLine textLine, double indentation, double virtualSpaceWidth) { if (linePartsCollection is null) { throw new ArgumentNullException(nameof(linePartsCollection)); } if (linePartsIndex < 0) { throw new ArgumentOutOfRangeException(nameof(linePartsIndex)); } if (linePartsLength < 0) { throw new ArgumentOutOfRangeException(nameof(linePartsLength)); } if (linePartsIndex + linePartsLength > linePartsCollection.LineParts.Count) { throw new ArgumentOutOfRangeException(nameof(linePartsLength)); } if (textLine is null) { throw new ArgumentNullException(nameof(textLine)); } this.bufferLine = bufferLine ?? throw new ArgumentNullException(nameof(bufferLine)); isValid = true; this.linePartsIndex = linePartsIndex; this.linePartsLength = linePartsLength; this.linePartsCollection = linePartsCollection; this.startColumn = startColumn; this.endColumn = endColumn; textLines = new ReadOnlyCollection <TextLine>(new[] { textLine }); Debug.Assert(textLines.Count == 1); // Assumed by all code accessing TextLine prop realTopSpace = 0; realBottomSpace = 0; realBaseline = TextLine.Baseline; double baseLineHeight = TextLine.TextHeight - TextLine.Baseline; var lineParts = linePartsCollection.LineParts; for (int i = 0; i < linePartsLength; i++) { var adornmentElement = lineParts[linePartsIndex + i].AdornmentElement; if (adornmentElement is null) { continue; } double adornmentBaseLineHeight = adornmentElement.TextHeight - adornmentElement.Baseline; if (adornmentBaseLineHeight > baseLineHeight) { baseLineHeight = adornmentBaseLineHeight; } if (adornmentElement.Baseline > realBaseline) { realBaseline = adornmentElement.Baseline; } if (adornmentElement.TopSpace > realTopSpace) { realTopSpace = adornmentElement.TopSpace; } if (adornmentElement.BottomSpace > realBottomSpace) { realBottomSpace = adornmentElement.BottomSpace; } } realTextHeight = Math.Ceiling(baseLineHeight + realBaseline); IsLastVisualLine = bufferLine.LineNumber + 1 == bufferLine.LineProvider.LineCount; this.virtualSpaceWidth = virtualSpaceWidth; textLeft = indentation; textWidth = TextLine.WidthIncludingTrailingWhitespace; lineExtent = lineSpan; endOfLineWidth = Math.Floor(realTextHeight * 0.58333333333333337); // Same as VS width = textWidth; change = VSTF.TextViewLineChange.NewOrReformatted; SetLineTransform(DefaultLineTransform); }
/// <summary> /// Scrolls a line into view /// </summary> /// <param name="line">Line</param> /// <param name="span">Line span</param> /// <param name="options">Options</param> public abstract void EnsureSpanVisible(HexBufferLine line, VST.Span span, VSTE.EnsureSpanVisibleOptions options);
/// <summary> /// Scrolls a line into view /// </summary> /// <param name="line">Line</param> /// <param name="span">Line span</param> public void EnsureSpanVisible(HexBufferLine line, VST.Span span) => EnsureSpanVisible(line, span, VSTE.EnsureSpanVisibleOptions.None);
/// <summary> /// Creates a <see cref="HexAndAdornmentCollection"/> /// </summary> /// <param name="line">Line</param> /// <returns></returns> public abstract HexAndAdornmentCollection CreateHexAndAdornmentCollection(HexBufferLine line);
/// <summary> /// Removes an adornment /// </summary> /// <param name="line">Line</param> public void RemoveAdornmentsByVisualSpan(HexBufferLine line) => RemoveMatchingAdornments(line, returnTruePredicate);
HexLinePartsCollection CreateLinePartsCollection(HexAndAdornmentCollection coll, HexBufferLine bufferLine) { var lineExtent = bufferLine.TextSpan; if (coll.Count == 0) { return(new HexLinePartsCollection(emptyLineParts, lineExtent, bufferLine.Text)); } var list = new List <HexLinePart>(); int column = 0; int startOffs = lineExtent.Start; foreach (var seqElem in coll) { if (seqElem.ShouldRenderText) { var cspans = new List <HexClassificationSpan>(); var textSpan = bufferLine.TextSpan.Intersection(seqElem.Span) ?? new VST.Span(bufferLine.TextSpan.End, 0); aggregateClassifier.GetClassificationSpans(cspans, new HexClassificationContext(bufferLine, textSpan)); int lastOffs = seqElem.Span.Start; for (int i = 0; i < cspans.Count; i++) { var cspan = cspans[i]; int otherSize = cspan.Span.Start - lastOffs; if (otherSize != 0) { Debug.Assert(otherSize > 0); list.Add(new HexLinePart(list.Count, column, new VST.Span(lastOffs - startOffs, otherSize), DefaultTextProperties)); column += otherSize; } Add(list, column, cspan, lineExtent); column += cspan.Span.Length; lastOffs = cspan.Span.End; } int lastSize = seqElem.Span.End - lastOffs; if (lastSize != 0) { list.Add(new HexLinePart(list.Count, column, new VST.Span(lastOffs - startOffs, lastSize), DefaultTextProperties)); column += lastSize; } } else { var adornmentElement = seqElem as HexAdornmentElement; if (adornmentElement != null) { var span = seqElem.Span; list.Add(new HexLinePart(list.Count, column, new VST.Span(span.Start - startOffs, span.Length), adornmentElement, DefaultTextProperties)); column += list[list.Count - 1].ColumnLength; } } } Debug.Assert(list.Sum(a => a.ColumnLength) == column); return(new HexLinePartsCollection(list, lineExtent, bufferLine.Text)); }
/// <summary> /// Updates a popup agent /// </summary> /// <param name="agent">Popup agent created by <see cref="CreatePopupAgent(HexLineSpan, VSTA.PopupStyles, UIElement)"/></param> /// <param name="line">Line</param> /// <param name="span">Line span</param> /// <param name="styles">New popup style</param> public void UpdatePopupAgent(HexSpaceReservationAgent agent, HexBufferLine line, VST.Span span, VSTA.PopupStyles styles) => UpdatePopupAgent(agent, new HexLineSpan(line, span), styles);
/// <summary> /// Creates a popup agent /// </summary> /// <param name="line">Line</param> /// <param name="span">Line span</param> /// <param name="style">Popup style</param> /// <param name="content">Popup content</param> /// <returns></returns> public HexSpaceReservationAgent CreatePopupAgent(HexBufferLine line, VST.Span span, VSTA.PopupStyles style, UIElement content) => CreatePopupAgent(new HexLineSpan(line, span), style, content);
/// <summary> /// Adds an adornment. Returns true if the adornment was added. /// </summary> /// <param name="line">Line</param> /// <param name="tag">Tag</param> /// <param name="adornment">Adornment</param> /// <returns></returns> public bool AddAdornment(HexBufferLine line, object tag, UIElement adornment) => AddAdornment(VSTE.AdornmentPositioningBehavior.TextRelative, line, tag, adornment, null);
public override HexAndAdornmentCollection CreateHexAndAdornmentCollection(HexBufferLine line) { if (line == null) { throw new ArgumentNullException(nameof(line)); } if (line.Buffer != hexView.Buffer) { throw new ArgumentException(); } var lineSpan = line.TextSpan; List <AdornmentElementAndSpan> adornmentList = null; foreach (var tagSpan in hexTagAggregator.GetAllTags(new HexTaggerContext(line, lineSpan))) { if (adornmentList == null) { adornmentList = new List <AdornmentElementAndSpan>(); } adornmentList.Add(new AdornmentElementAndSpan(new HexAdornmentElementImpl(tagSpan), tagSpan.Span)); } // Common case if (adornmentList == null) { var elem = new HexSequenceElementImpl(lineSpan); return(new HexAndAdornmentCollectionImpl(this, new[] { elem })); } var sequenceList = new List <HexSequenceElement>(); adornmentList.Sort(AdornmentElementAndSpanComparer.Instance); int start = lineSpan.Start; int end = lineSpan.End; int curr = start; AdornmentElementAndSpan?lastAddedAdornment = null; for (int i = 0; i < adornmentList.Count; i++) { var info = adornmentList[i]; int spanStart = info.Span.Length == 0 && info.AdornmentElement.Affinity == VST.PositionAffinity.Predecessor ? info.Span.Start - 1 : info.Span.Start; if (spanStart < start) { continue; } if (info.Span.Start > end) { break; } var textSpan = VST.Span.FromBounds(curr, info.Span.Start); if (!textSpan.IsEmpty) { sequenceList.Add(new HexSequenceElementImpl(textSpan)); } if (info.Span.Start != end || (info.Span.Length == 0 && info.AdornmentElement.Affinity == VST.PositionAffinity.Predecessor)) { bool canAppend = true; if (lastAddedAdornment != null && lastAddedAdornment.Value.Span.End > info.Span.Start) { canAppend = false; } if (canAppend) { sequenceList.Add(info.AdornmentElement); lastAddedAdornment = info; } } curr = info.Span.End; } if (curr < end) { var textSpan = VST.Span.FromBounds(curr, end); Debug.Assert(!textSpan.IsEmpty); sequenceList.Add(new HexSequenceElementImpl(textSpan)); } return(new HexAndAdornmentCollectionImpl(this, sequenceList.ToArray())); }
/// <summary> /// Formats a line /// </summary> /// <param name="line">Buffer line</param> /// <returns></returns> public abstract HexFormattedLine FormatLineInVisualBuffer(HexBufferLine line);
/// <summary> /// Removes all matching adornments /// </summary> /// <param name="line">Line</param> /// <param name="match">Returns true if the adornment should be removed</param> public void RemoveMatchingAdornments(HexBufferLine line, Predicate<HexAdornmentLayerElement> match) { if (line == null) throw new ArgumentNullException(nameof(line)); if (match == null) throw new ArgumentNullException(nameof(match)); RemoveMatchingAdornments(line.BufferSpan, match); }
/// <summary> /// Adds an adornment. Returns true if the adornment was added. /// </summary> /// <param name="behavior">Positioning behavior</param> /// <param name="line">Line</param> /// <param name="tag">Tag</param> /// <param name="adornment">Adornment</param> /// <param name="removedCallback">Called when the adornment is removed</param> /// <returns></returns> public bool AddAdornment(VSTE.AdornmentPositioningBehavior behavior, HexBufferLine line, object tag, UIElement adornment, VSTE.AdornmentRemovedCallback removedCallback) { if (line == null) throw new ArgumentNullException(nameof(line)); return AddAdornment(behavior, line.BufferSpan, tag, adornment, removedCallback); }
public LinePosition(HexBufferLine line, int column) { Line = line; Column = column; }