HexBox now support multi encoding

This commit is contained in:
fangrong 2024-08-02 18:30:11 +08:00
parent 2e81fd5bae
commit 94dcf781da
5 changed files with 206 additions and 71 deletions

View File

@ -21,7 +21,9 @@ namespace Be.Windows.Forms
/// </summary>
/// <param name="c"></param>
/// <returns></returns>
byte ToByte(char c);
byte[] ToByte(char c);
Encoding ToEncoding();
}
/// <summary>
@ -44,9 +46,11 @@ namespace Be.Windows.Forms
/// </summary>
/// <param name="c"></param>
/// <returns></returns>
public virtual byte ToByte(char c)
public virtual byte[] ToByte(char c)
{
return (byte)c;
byte[] bytes = new byte[1];
bytes[0] = (byte)c;
return bytes;
}
/// <summary>
@ -57,6 +61,11 @@ namespace Be.Windows.Forms
{
return "ANSI (Default)";
}
public Encoding ToEncoding()
{
return Encoding.Default;
}
}
/// <summary>
@ -86,10 +95,10 @@ namespace Be.Windows.Forms
/// </summary>
/// <param name="c"></param>
/// <returns></returns>
public virtual byte ToByte(char c)
public virtual byte[] ToByte(char c)
{
byte[] decoded = _ebcdicEncoding.GetBytes(new char[] { c });
return decoded.Length > 0 ? decoded[0] : (byte)0;
return decoded.Length > 0 ? decoded : (new byte[1] { 0 });
}
/// <summary>
@ -100,5 +109,10 @@ namespace Be.Windows.Forms
{
return "EBCDIC (Code Page 500)";
}
public Encoding ToEncoding()
{
return this._ebcdicEncoding;
}
}
}

View File

@ -1066,11 +1066,13 @@ namespace Be.Windows.Forms
_hexBox.ReleaseSelection();
byte b = _hexBox.ByteCharConverter.ToByte(c);
byte[] b = _hexBox.ByteCharConverter.ToByte(c);
if(isInsertMode)
_hexBox._byteProvider.InsertBytes(pos, new byte[]{b});
else
_hexBox._byteProvider.WriteByte(pos, b);
_hexBox._byteProvider.InsertBytes(pos, b);
else {
foreach (byte bs in b)
_hexBox._byteProvider.WriteByte(pos, bs);
}
PerformPosMoveRightByte();
_hexBox.Invalidate();
@ -1168,15 +1170,15 @@ namespace Be.Windows.Forms
/// </summary>
int _lastThumbtrack;
/// <summary>
/// Contains the border´s left shift
/// Contains the border left shift
/// </summary>
int _recBorderLeft = SystemInformation.Border3DSize.Width;
/// <summary>
/// Contains the border´s right shift
/// Contains the border right shift
/// </summary>
int _recBorderRight = SystemInformation.Border3DSize.Width;
/// <summary>
/// Contains the border´s top shift
/// Contains the border top shift
/// </summary>
int _recBorderTop = SystemInformation.Border3DSize.Height;
/// <summary>
@ -2149,7 +2151,8 @@ namespace Be.Windows.Forms
DataObject da = new DataObject();
// set string buffer clipbard data
string sBuffer = System.Text.Encoding.ASCII.GetString(buffer, 0, buffer.Length);
Encoding encoding = ByteCharConverter.ToEncoding();
string sBuffer = encoding.GetString(buffer, 0, buffer.Length);
da.SetData(typeof(string), sBuffer);
//set memorystream (BinaryData) clipboard data
@ -2229,7 +2232,8 @@ namespace Be.Windows.Forms
else if(da.GetDataPresent(typeof(string)))
{
string sBuffer = (string)da.GetData(typeof(string));
buffer = System.Text.Encoding.ASCII.GetBytes(sBuffer);
Encoding encoding = ByteCharConverter.ToEncoding();
buffer = encoding.GetBytes(sBuffer);
}
else
{
@ -2581,8 +2585,36 @@ namespace Be.Windows.Forms
g.DrawString(sB.Substring(1,1), Font, brush, bytePointF, _stringFormat);
}
static bool IsCjkCharacter(char ch)
{
int codePoint = ch;
// CJK Unified Ideographs
if (codePoint >= 0x4E00 && codePoint <= 0x9FFF)
return true;
// CJK Unified Ideographs Extension A
if (codePoint >= 0x3400 && codePoint <= 0x4DBF)
return true;
// CJK Compatibility Ideographs
if (codePoint >= 0xF900 && codePoint <= 0xFAFF)
return true;
// Additional ranges for CJK (surrogate pairs)
// Note: Surrogate pairs are required for characters beyond U+FFFF
if (char.IsHighSurrogate(ch) || char.IsLowSurrogate(ch))
{
// Handle surrogate pairs
return false;
}
return false;
}
void PaintHexAndStringView(Graphics g, long startByte, long endByte)
{
System.Diagnostics.Debug.WriteLine(ByteCharConverter.ToString(), "PaintHexAndStringView()", "HexBox");
Brush brush = new SolidBrush(GetDefaultForeColor());
Brush selBrush = new SolidBrush(_selectionForeColor);
Brush selBrushBack = new SolidBrush(_selectionBackColor);
@ -2612,14 +2644,19 @@ namespace Be.Windows.Forms
}
string s = new String(ByteCharConverter.ToChar(b), 1);
float cjk_ofs = 0;
if (IsCjkCharacter(s.ToCharArray()[0]))
cjk_ofs = _charSize.Width / 2;
if (isSelectedByte && isStringKeyInterpreterActive)
{
g.FillRectangle(selBrushBack, byteStringPointF.X, byteStringPointF.Y, _charSize.Width, _charSize.Height);
byteStringPointF.X -= cjk_ofs;
g.DrawString(s, Font, selBrush, byteStringPointF, _stringFormat);
}
else
{
byteStringPointF.X -= cjk_ofs;
g.DrawString(s, Font, brush, byteStringPointF, _stringFormat);
}
}
@ -3318,9 +3355,9 @@ namespace Be.Windows.Forms
} long _lineInfoOffset = 0;
/// <summary>
/// Gets or sets the hex box´s border style.
/// Gets or sets the hex box border style.
/// </summary>
[DefaultValue(typeof(BorderStyle), "Fixed3D"), Category("Hex"), Description("Gets or sets the hex box´s border style.")]
[DefaultValue(typeof(BorderStyle), "Fixed3D"), Category("Hex"), Description("Gets or sets the hex box border style.")]
public BorderStyle BorderStyle
{
get { return _borderStyle;}

View File

@ -93,7 +93,7 @@ namespace Tinke
this.hexBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.hexBox1.Font = new System.Drawing.Font("Courier New", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.hexBox1.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.hexBox1.InfoForeColor = System.Drawing.Color.Empty;
this.hexBox1.LineInfoVisible = true;
this.hexBox1.Location = new System.Drawing.Point(0, 24);
@ -301,10 +301,13 @@ namespace Tinke
this.encodingCombo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.encodingCombo.Items.AddRange(new object[] {
"S0D",
"EBCDIC(CP500)",
"Shift_JIS",
"UTF-7",
"UTF-16LE",
"UTF-16BE",
"UTF-8",
"ASCII"});
"ASCII",
"GBK"});
this.encodingCombo.Name = "encodingCombo";
this.encodingCombo.Size = new System.Drawing.Size(120, 25);
this.encodingCombo.DropDownClosed += new System.EventHandler(this.encodingCombo_DropDownClosed);

View File

@ -145,17 +145,18 @@ namespace Tinke
{
hexBox1.Height = this.Height - 83;
tableGrid.Width = this.Width - 652;
tableGrid.Width = this.Width - 750;
if (tableGrid.Visible) hexBox1.Width = this.Width - (tableGrid.Width + 15);
else hexBox1.Width = this.Width - 16;
}
private void comboBoxEncoding_SelectedIndexChanged(object sender, EventArgs e)
{
if (encodingCombo.SelectedIndex == 0)
bcc = new DefaultByteCharConverter();
else if (encodingCombo.SelectedIndex == 1)
bcc = new EbcdicByteCharProvider();
else
bcc = new ByteCharConveter(encodingCombo.Text);
@ -290,11 +291,12 @@ namespace Tinke
{
hexBox1.Width = this.Width - (tableGrid.Width + 15);
tableGrid.Show();
VisorHex_Resize(null, null);
}
private void tableGrid_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
List<ulong> codes = new List<ulong>();
List<byte> codes = new List<byte>();
List<char> charas = new List<char>();
for (int i = 0; i < tableGrid.RowCount; i++)
@ -303,7 +305,7 @@ namespace Tinke
!(tableGrid.Rows[i].Cells[1].Value is object))
continue;
codes.Add(Convert.ToUInt64((string)tableGrid.Rows[i].Cells[0].Value, 16));
codes.Add(Convert.ToByte((string)tableGrid.Rows[i].Cells[0].Value, 16));
charas.Add(Convert.ToChar(tableGrid.Rows[i].Cells[1].Value));
}
hexBox1.ByteCharConverter = new ByteCharTable(codes.ToArray(), charas.ToArray());
@ -353,13 +355,10 @@ namespace Tinke
for (int i = 0; i < lines.Length; i++)
{
int sign_pos = lines[i].IndexOf('=');
ushort code = Convert.ToUInt16(lines[i].Substring(0, sign_pos), 16);
byte code = Convert.ToByte(lines[i].Substring(0, sign_pos), 16);
char chara = lines[i].Substring(sign_pos + 1)[0];
if (code <= 0x7E)
tableGrid.Rows.Add(code.ToString("x").ToUpper(), chara);
else
tableGrid.Rows.Add(code.ToString("x").ToUpper().PadLeft(4, '0'), chara);
tableGrid.Rows.Add(code.ToString(), chara);
}
tableGrid_CellEndEdit(null, null);
@ -465,29 +464,29 @@ namespace Tinke
public class ByteCharTable : IByteCharConverter
{
Dictionary<ulong, char> tableChar;
Dictionary<char, ulong> tableByte;
Dictionary<byte, char> tableChar;
Dictionary<char, byte> tableByte;
public ByteCharTable(string tablePath)
{
tableChar = new Dictionary<ulong, char>();
tableByte = new Dictionary<char, ulong>();
tableChar = new Dictionary<byte, char>();
tableByte = new Dictionary<char, byte>();
String[] lines = File.ReadAllLines(tablePath);
for (int i = 0; i < lines.Length; i++)
{
int sign_pos = lines[i].IndexOf('=');
ulong code = Convert.ToUInt64(lines[i].Substring(0, sign_pos), 16);
byte code = Convert.ToByte(lines[i].Substring(0, sign_pos), 16);
char chara = lines[i].Substring(sign_pos + 1)[0];
tableChar.Add(code, chara);
tableByte.Add(chara, code);
}
}
public ByteCharTable(ulong[] codes, char[] charas)
public ByteCharTable(byte[] codes, char[] charas)
{
tableByte = new Dictionary<char, ulong>();
tableChar = new Dictionary<ulong, char>();
tableByte = new Dictionary<char, byte>();
tableChar = new Dictionary<byte, char>();
for (int i = 0; i < codes.Length; i++)
{
@ -505,58 +504,136 @@ namespace Tinke
else
return '.';
}
public byte ToByte(char c)
public byte[] ToByte(char c)
{
byte[] bytes = new byte[1];
if (tableByte.ContainsKey(c))
return (byte)tableByte[c];
{
bytes[0] = tableByte[c];
return bytes;
}
else
return 0;
return (new byte[1] { 0 });
}
public Encoding ToEncoding()
{
return Encoding.Default;
}
}
public class ByteCharConveter : IByteCharConverter
{
Encoding encoding;
List<byte> requeridedChar;
List<char> requeridedByte;
List<byte> requiredChar;
List<char> requiredByte;
public ByteCharConveter(string encoding)
{
this.encoding = Encoding.GetEncoding(encoding);
requeridedChar = new List<byte>();
requeridedByte = new List<char>();
requiredChar = new List<byte>();
requiredByte = new List<char>();
}
public byte ToByte(char c)
public byte[] ToByte(char c)
{
if (encoding.WebName == "shift_jis")
return ToByteShiftJis(c);
return (byte)c;
byte[] decoded = encoding.GetBytes(new char[] { c });
return decoded.Length > 0 ? decoded : (new byte[1] { 0 });
}
public char ToChar(byte b)
{
if (encoding.WebName == "shift_jis")
return ToCharShiftJis(b);
if (encoding.WebName == "shift_jis" || encoding.WebName == "gb2312")
return ToCharShiftJisOrGBK(b);
if (encoding.WebName == "utf-8")
return ToCharUtf8(b);
if (encoding.WebName == "utf-16")
return ToCharUtf16Le(b);
if (encoding.WebName == "utf-16BE")
return ToCharUtf16Be(b);
return encoding.GetChars(new byte[] { b })[0];
}
public byte ToByteShiftJis(char c)
public char ToCharShiftJisOrGBK(byte b)
{
return (byte)c;
}
public char ToCharShiftJis(byte b)
if (requiredChar.Count == 0 && b > 0x7F)
{
if (requeridedChar.Count == 0 && b > 0x7F)
{
requeridedChar.Add(b);
requiredChar.Add(b);
return '\x20';
}
requeridedChar.Add(b);
string c = new String(encoding.GetChars(requeridedChar.ToArray()));
requeridedChar.Clear();
requiredChar.Add(b);
string c = new String(encoding.GetChars(requiredChar.ToArray()));
requiredChar.Clear();
return (c[0] > '\x1F' ? c[0] : '.');
}
public char ToCharUtf16Le(byte b)
{
requiredChar.Add(b);
if (requiredChar.Count == 2)
{
char c = BitConverter.ToChar(requiredChar.ToArray(), 0);
requiredChar.Clear();
return (c > '\x1F' ? c : '.');
}
return '\x20';
}
public char ToCharUtf16Be(byte b)
{
requiredChar.Add(b);
if (requiredChar.Count == 2)
{
byte[] bytes = requiredChar.ToArray();
Array.Reverse(bytes);
char c = BitConverter.ToChar(bytes, 0);
requiredChar.Clear();
return (c > '\x1F' ? c : '.');
}
return '\x20';
}
public char ToCharUtf8(byte b)
{
if (requiredChar.Count == 0 && !((b & 0x80) == 0))
{
requiredChar.Add(b);
return '\x20';
}
else if (requiredChar.Count == 1 && !((requiredChar[0] & 0xE0) == 0xC0))
{
requiredChar.Add(b);
return '\x20';
}
else if (requiredChar.Count == 2 && !((requiredChar[0] & 0xF0) == 0xE0))
{
requiredChar.Add(b);
return '\x20';
}
requiredChar.Add(b);
string c = new String(encoding.GetChars(requiredChar.ToArray()));
requiredChar.Clear();
return (c[0] > '\x1F' ? c[0] : '.');
}
public override string ToString()
{
if (encoding.WebName == "utf-16" || encoding.WebName == "utf-16BE")
{
requiredChar.Clear();
return "Unicode";
}
return encoding.WebName;
}
public Encoding ToEncoding()
{
return this.encoding;
}
}
}

View File

@ -5,7 +5,7 @@ TinkeDSi 0.9.5 (Made by R-YaTian)
* Set Topmost for waiting window, add "Please wait..." message
* Special fix for Sonic Classic Collection
* Allow drop files to open
* WIP: Improve Hex Editor
* Improve Hex Editor
* NFTR plugins: Disable zoom when more than 7489 chars, will fix scrolling issue
* Add toolkit: get header crc32 for r4cce/TTdT
* Allow copy info to Clipboard by mouse double click on RomInfo window
@ -19,6 +19,10 @@ TinkeDSi 0.9.5 (Made by R-YaTian)
* 3DModels: Update to OpenTK 3.3.3, fix bug on fullscreen btn
* Improved SF Feather Plugin (By @mn1712trungson)
* Core: Improve Nitrocode check when saving rom
* Saveoptions: Add an option to "Recompress ARM9 binary"
* Saveoptions: Add an option to parse the header of flashcart firmware
* Implement command line support
* Update Be.Windows.Forms.HexBox to 1.6.0
TODO: full i18n support (include plugins)
TinkeDSi 0.9.4