Files
CMLeonOS/shell/Commands/Utility/HexEditor.cs
2026-02-28 19:24:02 +08:00

259 lines
8.8 KiB
C#

using System;
using System.IO;
namespace CMLeonOS.Commands.Utility
{
public class HexEditor
{
private byte[] data;
private int cursorPosition;
private int viewOffset;
private int bytesPerLine = 16;
private int bytesPerGroup = 2;
private string filePath;
private bool modified;
private bool running;
public HexEditor(string path)
{
filePath = path;
if (File.Exists(path))
{
data = File.ReadAllBytes(path);
}
else
{
data = new byte[256];
}
cursorPosition = 0;
viewOffset = 0;
modified = false;
running = true;
}
public void Run()
{
Console.Clear();
Console.WriteLine("====================================");
Console.WriteLine(" Hex Editor");
Console.WriteLine("====================================");
Console.WriteLine();
Console.WriteLine("File: " + filePath);
Console.WriteLine("Size: " + data.Length + " bytes");
Console.WriteLine();
Console.WriteLine("Controls:");
Console.WriteLine(" Arrow Keys - Move cursor");
Console.WriteLine(" Page Up/Down - Scroll view");
Console.WriteLine(" 0-9, A-F - Edit byte");
Console.WriteLine(" S - Save file");
Console.WriteLine(" Q - Quit");
Console.WriteLine();
Console.WriteLine("Press any key to continue...");
Console.ReadKey(true);
while (running)
{
Display();
HandleInput();
}
}
private void Display()
{
Console.Clear();
Console.WriteLine("====================================");
Console.WriteLine(" Hex Editor");
Console.WriteLine("====================================");
Console.WriteLine();
Console.WriteLine("File: " + filePath);
Console.WriteLine("Size: " + data.Length + " bytes");
if (modified)
{
Console.Write(" [MODIFIED]");
}
Console.WriteLine();
Console.WriteLine();
int lines = (int)Math.Ceiling((double)data.Length / bytesPerLine);
int startLine = viewOffset / bytesPerLine;
int endLine = Math.Min(startLine + 20, lines);
for (int line = startLine; line < endLine; line++)
{
int offset = line * bytesPerLine;
if (offset >= data.Length) break;
Console.Write(offset.ToString("X8") + " ");
for (int i = 0; i < bytesPerLine; i++)
{
int byteOffset = offset + i;
if (byteOffset >= data.Length)
{
Console.Write(" ");
}
else
{
byte b = data[byteOffset];
bool isCursor = (byteOffset == cursorPosition);
if (isCursor)
{
Console.BackgroundColor = ConsoleColor.White;
Console.ForegroundColor = ConsoleColor.Black;
}
Console.Write(b.ToString("X2") + " ");
if (isCursor)
{
Console.ResetColor();
}
if ((i + 1) % bytesPerGroup == 0)
{
Console.Write(" ");
}
}
}
Console.Write(" |");
for (int i = 0; i < bytesPerLine; i++)
{
int byteOffset = offset + i;
if (byteOffset >= data.Length)
{
Console.Write(" ");
}
else
{
byte b = data[byteOffset];
bool isCursor = (byteOffset == cursorPosition);
if (isCursor)
{
Console.BackgroundColor = ConsoleColor.White;
Console.ForegroundColor = ConsoleColor.Black;
}
char c = (b >= 32 && b <= 126) ? (char)b : '.';
Console.Write(c);
if (isCursor)
{
Console.ResetColor();
}
}
}
Console.WriteLine("|");
}
Console.WriteLine();
Console.WriteLine("Cursor: 0x" + cursorPosition.ToString("X8") + " (" + cursorPosition + ")");
Console.WriteLine("Value: 0x" + data[cursorPosition].ToString("X2"));
Console.WriteLine();
Console.WriteLine("Controls:");
Console.WriteLine(" Arrow Keys - Move cursor");
Console.WriteLine(" Page Up/Down - Scroll view");
Console.WriteLine(" 0-9, A-F - Edit byte");
Console.WriteLine(" S - Save file");
Console.WriteLine(" Q - Quit");
}
private void HandleInput()
{
var key = Console.ReadKey(true);
switch (key.Key)
{
case ConsoleKey.UpArrow:
cursorPosition = Math.Max(0, cursorPosition - bytesPerLine);
break;
case ConsoleKey.DownArrow:
cursorPosition = Math.Min(data.Length - 1, cursorPosition + bytesPerLine);
break;
case ConsoleKey.LeftArrow:
cursorPosition = Math.Max(0, cursorPosition - 1);
break;
case ConsoleKey.RightArrow:
cursorPosition = Math.Min(data.Length - 1, cursorPosition + 1);
break;
case ConsoleKey.PageUp:
viewOffset = Math.Max(0, viewOffset - (bytesPerLine * 20));
break;
case ConsoleKey.PageDown:
viewOffset = Math.Min(data.Length - 1, viewOffset + (bytesPerLine * 20));
break;
case ConsoleKey.D0:
case ConsoleKey.D1:
case ConsoleKey.D2:
case ConsoleKey.D3:
case ConsoleKey.D4:
case ConsoleKey.D5:
case ConsoleKey.D6:
case ConsoleKey.D7:
case ConsoleKey.D8:
case ConsoleKey.D9:
int digit = key.KeyChar - '0';
EditByte(digit);
break;
case ConsoleKey.A:
EditByte(10);
break;
case ConsoleKey.B:
EditByte(11);
break;
case ConsoleKey.C:
EditByte(12);
break;
case ConsoleKey.D:
EditByte(13);
break;
case ConsoleKey.E:
EditByte(14);
break;
case ConsoleKey.F:
EditByte(15);
break;
case ConsoleKey.S:
SaveFile();
break;
case ConsoleKey.Q:
running = false;
break;
}
}
private void EditByte(int value)
{
if (cursorPosition >= 0 && cursorPosition < data.Length)
{
data[cursorPosition] = (byte)value;
modified = true;
}
}
private void SaveFile()
{
try
{
File.WriteAllBytes(filePath, data);
modified = false;
Console.WriteLine();
Console.WriteLine("File saved successfully!");
Console.WriteLine("Press any key to continue...");
Console.ReadKey(true);
}
catch (Exception ex)
{
Console.WriteLine();
Console.WriteLine("Error saving file: " + ex.Message);
Console.WriteLine("Press any key to continue...");
Console.ReadKey(true);
}
}
}
}