/// <summary> /// Creates a <see cref="HexLinePositionInfo"/> /// </summary> /// <param name="linePosition">Line position</param> /// <returns></returns> public HexLinePositionInfo GetLinePositionInfo(int linePosition) { if (linePosition >= Text.Length) { return(HexLinePositionInfo.CreateVirtualSpace(linePosition, Text.Length)); } if (IsOffsetColumnPresent) { var span = GetOffsetSpan(); if (span.Contains(linePosition)) { return(HexLinePositionInfo.CreateOffset(linePosition, linePosition - span.Start)); } } if (IsValuesColumnPresent) { var valuesSpan = GetValuesSpan(onlyVisibleCells: false); if (valuesSpan.Contains(linePosition)) { int cellIndex = (linePosition - valuesSpan.Start) / LineProvider.GetCharsPerCellIncludingSeparator(HexColumnType.Values); var cell = ValueCells[cellIndex]; if (cell.SeparatorSpan.Contains(linePosition)) { return(HexLinePositionInfo.CreateValueCellSeparator(linePosition, cell)); } return(HexLinePositionInfo.CreateValue(linePosition, cell)); } } if (IsAsciiColumnPresent) { var asciiSpan = GetAsciiSpan(onlyVisibleCells: false); if (asciiSpan.Contains(linePosition)) { int cellIndex = linePosition - asciiSpan.Start; var cell = AsciiCells[cellIndex]; return(HexLinePositionInfo.CreateAscii(linePosition, cell)); } } foreach (var column in ColumnOrder) { var span = GetSpan(column, onlyVisibleCells: false); if (span.End == linePosition) { return(HexLinePositionInfo.CreateColumnSeparator(linePosition)); } } throw new InvalidOperationException(); }
HexLinePositionInfo?GetClosestCellPosition(int linePosition) { (HexColumnType columnType, HexCell cell)? closest = null; int cellPosition = -1; foreach (var info in GetCells()) { var cell = info.cell; if (closest == null || Compare(linePosition, cell, closest.Value.cell) < 0) { closest = info; cellPosition = linePosition - info.cell.CellSpan.Start; if (cellPosition < 0) { cellPosition = 0; } else if (cellPosition >= info.cell.CellSpan.Length) { cellPosition = info.cell.CellSpan.Length - 1; } } } if (closest == null) { return(null); } if (cellPosition < 0 || cellPosition >= closest.Value.cell.CellSpan.Length) { throw new InvalidOperationException(); } int pos = closest.Value.cell.CellSpan.Start + cellPosition; if (closest.Value.columnType == HexColumnType.Values) { return(HexLinePositionInfo.CreateValue(pos, closest.Value.cell)); } if (closest.Value.columnType == HexColumnType.Ascii) { return(HexLinePositionInfo.CreateAscii(pos, closest.Value.cell)); } throw new InvalidOperationException(); }
/// <summary> /// Gets the closest cell position /// </summary> /// <param name="position">Position</param> /// <param name="onlyVisibleCells">true to only return cells with data</param> /// <returns></returns> public HexCellPosition?GetClosestCellPosition(HexLinePositionInfo position, bool onlyVisibleCells) { switch (position.Type) { case HexLinePositionInfoType.ValueCell: case HexLinePositionInfoType.AsciiCell: break; case HexLinePositionInfoType.ValueCellSeparator: Debug.Assert(position.Cell.CellSpan.End == position.Position); position = HexLinePositionInfo.CreateValue(position.Cell.CellSpan.End - 1, position.Cell); break; case HexLinePositionInfoType.Offset: case HexLinePositionInfoType.ColumnSeparator: case HexLinePositionInfoType.VirtualSpace: var closestPos = GetClosestCellPosition(position.Position); if (closestPos == null) { return(null); } Debug.Assert(closestPos.Value.IsAsciiCell || closestPos.Value.IsValueCell); position = closestPos.Value; break; default: throw new InvalidOperationException(); } var cell = position.Cell; int cellPosition = position.CellPosition; switch (position.Type) { case HexLinePositionInfoType.AsciiCell: if (!IsAsciiColumnPresent) { return(null); } if (onlyVisibleCells && !cell.HasData) { var visible = GetVisible(AsciiCells, cell); if (visible == null) { return(null); } cell = visible.Value.cell; cellPosition = visible.Value.cellPosition; } return(new HexCellPosition(HexColumnType.Ascii, cell.BufferStart, cellPosition)); case HexLinePositionInfoType.ValueCell: if (!IsValuesColumnPresent) { return(null); } if (onlyVisibleCells && !cell.HasData) { var visible = GetVisible(ValueCells, cell); if (visible == null) { return(null); } cell = visible.Value.cell; cellPosition = visible.Value.cellPosition; } return(new HexCellPosition(HexColumnType.Values, LineProvider.GetValueBufferSpan(cell, cellPosition).Start, cellPosition)); case HexLinePositionInfoType.Offset: case HexLinePositionInfoType.ValueCellSeparator: case HexLinePositionInfoType.ColumnSeparator: case HexLinePositionInfoType.VirtualSpace: default: throw new InvalidOperationException(); } }
/// <summary> /// Gets the closest cell position /// </summary> /// <param name="position">Position</param> /// <param name="onlyVisibleCells">true to only return cells with data</param> /// <returns></returns> public HexCellPosition? GetClosestCellPosition(HexLinePositionInfo position, bool onlyVisibleCells) { switch (position.Type) { case HexLinePositionInfoType.ValueCell: case HexLinePositionInfoType.AsciiCell: break; case HexLinePositionInfoType.ValueCellSeparator: Debug.Assert(position.Cell.CellSpan.End == position.Position); position = HexLinePositionInfo.CreateValue(position.Cell.CellSpan.End - 1, position.Cell); break; case HexLinePositionInfoType.Offset: case HexLinePositionInfoType.ColumnSeparator: case HexLinePositionInfoType.VirtualSpace: var closestPos = GetClosestCellPosition(position.Position); if (closestPos == null) return null; Debug.Assert(closestPos.Value.IsAsciiCell || closestPos.Value.IsValueCell); position = closestPos.Value; break; default: throw new InvalidOperationException(); } var cell = position.Cell; int cellPosition = position.CellPosition; switch (position.Type) { case HexLinePositionInfoType.AsciiCell: if (!IsAsciiColumnPresent) return null; if (onlyVisibleCells && !cell.HasData) { var visible = GetVisible(AsciiCells, cell); if (visible == null) return null; cell = visible.Value.Key; cellPosition = visible.Value.Value; } return new HexCellPosition(HexColumnType.Ascii, cell.BufferStart, cellPosition); case HexLinePositionInfoType.ValueCell: if (!IsValuesColumnPresent) return null; if (onlyVisibleCells && !cell.HasData) { var visible = GetVisible(ValueCells, cell); if (visible == null) return null; cell = visible.Value.Key; cellPosition = visible.Value.Value; } return new HexCellPosition(HexColumnType.Values, LineProvider.GetValueBufferSpan(cell, cellPosition).Start, cellPosition); case HexLinePositionInfoType.Offset: case HexLinePositionInfoType.ValueCellSeparator: case HexLinePositionInfoType.ColumnSeparator: case HexLinePositionInfoType.VirtualSpace: default: throw new InvalidOperationException(); } }