/* Copyright (C) 2014-2019 de4dot@gmail.com This file is part of dnSpy dnSpy is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. dnSpy is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with dnSpy. If not, see . */ using System; using System.Collections.ObjectModel; using VST = Microsoft.VisualStudio.Text; namespace dnSpy.Contracts.Hex { /// /// Creates s /// public abstract class HexBufferLineFormatter { /// /// Constructor /// protected HexBufferLineFormatter() { } /// /// Gets the buffer /// public abstract HexBuffer Buffer { get; } /// /// Gets the buffer span /// public abstract HexBufferSpan BufferSpan { get; } /// /// Gets the start position /// public HexBufferPoint BufferStart => BufferSpan.Start; /// /// Gets the end position /// public HexBufferPoint BufferEnd => BufferSpan.End; /// /// Number of lines. There's always at least one line. /// public abstract HexPosition LineCount { get; } /// /// Gets the span of the offset column. This is empty if the column isn't present. /// public abstract VST.Span OffsetSpan { get; } /// /// Gets the span of the values column. This is empty if the column isn't present. /// public abstract VST.Span ValuesSpan { get; } /// /// Gets the span of the ASCII column. This is empty if the column isn't present. /// public abstract VST.Span AsciiSpan { get; } /// /// Gets the span of a column. This is empty if the column isn't present. /// /// Column /// public VST.Span GetColumnSpan(HexColumnType column) { switch (column) { case HexColumnType.Offset: return OffsetSpan; case HexColumnType.Values: return ValuesSpan; case HexColumnType.Ascii: return AsciiSpan; default: throw new ArgumentOutOfRangeException(nameof(column)); } } /// /// Values group collection. It's empty if the values column isn't present. /// public abstract ReadOnlyCollection ValuesGroup { get; } /// /// ASCII group collection. It's empty if the ASCII column isn't present. /// public abstract ReadOnlyCollection AsciiGroup { get; } /// /// Number of characters per line /// public abstract int CharsPerLine { get; } /// /// Number of bytes per line or 0 to fit to width /// public abstract int BytesPerLine { get; } /// /// Number of bytes per group /// public abstract int GroupSizeInBytes { get; } /// /// true to show the offset /// public abstract bool ShowOffset { get; } /// /// true to use lower case hex /// public abstract bool OffsetLowerCaseHex { get; } /// /// Offset format /// public abstract HexOffsetFormat OffsetFormat { get; } /// /// First position to show /// public abstract HexPosition StartPosition { get; } /// /// End position /// public abstract HexPosition EndPosition { get; } /// /// Base position /// public abstract HexPosition BasePosition { get; } /// /// true if all visible positions are relative to /// public abstract bool UseRelativePositions { get; } /// /// true to show the values /// public abstract bool ShowValues { get; } /// /// true to use lower case hex /// public abstract bool ValuesLowerCaseHex { get; } /// /// Number of bits of the offset to show /// public abstract int OffsetBitSize { get; } /// /// Values format /// public abstract HexValuesDisplayFormat ValuesFormat { get; } /// /// Number of bytes per value in the values column /// public abstract int BytesPerValue { get; } /// /// true to show ASCII chars /// public abstract bool ShowAscii { get; } /// /// Column order /// public abstract ReadOnlyCollection ColumnOrder { get; } /// /// Gets the number of characters per cell value. This value doesn't include any cell separators /// /// public abstract int GetCharsPerCell(HexColumnType column); /// /// Gets the total number of characters per cell. This includes cell separators if any. /// /// public abstract int GetCharsPerCellIncludingSeparator(HexColumnType column); /// /// Gets the buffer position of a line /// /// Line number /// public abstract HexBufferPoint GetBufferPositionFromLineNumber(HexPosition lineNumber); /// /// Returns a line /// /// Line number /// public abstract HexBufferLine GetLineFromLineNumber(HexPosition lineNumber); /// /// Creates a line /// /// Position /// public abstract HexBufferLine GetLineFromPosition(HexBufferPoint position); /// /// Gets the line number /// /// Position /// public abstract HexPosition GetLineNumberFromPosition(HexBufferPoint position); /// /// Converts a physical (stream) position to a logical position /// /// Physical (stream) position /// public abstract HexPosition ToLogicalPosition(HexPosition physicalPosition); /// /// Converts a logical position to a physical (stream) position /// /// Logical position /// public abstract HexPosition ToPhysicalPosition(HexPosition logicalPosition); /// /// Returns true if is a valid position that can be passed to /// methods expecting a (physical) position. /// /// Position /// public bool IsValidPosition(HexBufferPoint position) { if (position.Buffer != Buffer) return false; // Allow the last position since it's so easy to accidentally pass in the end position. // The text editor API also allows this so to make everything easier, also allow it here, // but treat it as Max(StartPosition, EndPosition - 1) (treating them as signed integers) return BufferStart <= position && position <= BufferEnd; } /// /// Filters the position so it's less than if it equals . /// It will throw if returns false. /// /// Position /// public HexBufferPoint FilterAndVerify(HexBufferPoint position) { if (!IsValidPosition(position)) throw new ArgumentOutOfRangeException(nameof(position)); if (position != BufferEnd) return position; return BufferStart == BufferEnd ? position : position - 1; } /// /// Gets a buffer span within a cell /// /// Cell /// Position within the cell /// public abstract HexBufferSpan GetValueBufferSpan(HexCell cell, int cellPosition); /// /// true if can be called /// public abstract bool CanEditValueCell { get; } /// /// Edits a value cell. Returns null if editing isn't supported or if the character /// isn't a valid input character (eg. it's not a hex digit character), else it /// returns the position in the buffer and new value. /// /// Cell /// Position within the cell /// Character /// public abstract PositionAndData? EditValueCell(HexCell cell, int cellPosition, char c); /// /// Returns the offset as a string /// /// Position /// public abstract string GetFormattedOffset(HexPosition position); } }