/*
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);
}
}