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

View File

@ -1066,11 +1066,13 @@ namespace Be.Windows.Forms
_hexBox.ReleaseSelection(); _hexBox.ReleaseSelection();
byte b = _hexBox.ByteCharConverter.ToByte(c); byte[] b = _hexBox.ByteCharConverter.ToByte(c);
if(isInsertMode) if(isInsertMode)
_hexBox._byteProvider.InsertBytes(pos, new byte[]{b}); _hexBox._byteProvider.InsertBytes(pos, b);
else else {
_hexBox._byteProvider.WriteByte(pos, b); foreach (byte bs in b)
_hexBox._byteProvider.WriteByte(pos, bs);
}
PerformPosMoveRightByte(); PerformPosMoveRightByte();
_hexBox.Invalidate(); _hexBox.Invalidate();
@ -1168,15 +1170,15 @@ namespace Be.Windows.Forms
/// </summary> /// </summary>
int _lastThumbtrack; int _lastThumbtrack;
/// <summary> /// <summary>
/// Contains the border´s left shift /// Contains the border left shift
/// </summary> /// </summary>
int _recBorderLeft = SystemInformation.Border3DSize.Width; int _recBorderLeft = SystemInformation.Border3DSize.Width;
/// <summary> /// <summary>
/// Contains the border´s right shift /// Contains the border right shift
/// </summary> /// </summary>
int _recBorderRight = SystemInformation.Border3DSize.Width; int _recBorderRight = SystemInformation.Border3DSize.Width;
/// <summary> /// <summary>
/// Contains the border´s top shift /// Contains the border top shift
/// </summary> /// </summary>
int _recBorderTop = SystemInformation.Border3DSize.Height; int _recBorderTop = SystemInformation.Border3DSize.Height;
/// <summary> /// <summary>
@ -1807,7 +1809,7 @@ namespace Be.Windows.Forms
System.Diagnostics.Debug.WriteLine("UpdateCaret()", "HexBox"); System.Diagnostics.Debug.WriteLine("UpdateCaret()", "HexBox");
long byteIndex =_bytePos - _startByte; long byteIndex = _bytePos - _startByte;
PointF p = _keyInterpreter.GetCaretPointF(byteIndex); PointF p = _keyInterpreter.GetCaretPointF(byteIndex);
p.X += _byteCharacterPos*_charSize.Width; p.X += _byteCharacterPos*_charSize.Width;
NativeMethods.SetCaretPos((int)p.X, (int)p.Y); NativeMethods.SetCaretPos((int)p.X, (int)p.Y);
@ -2149,7 +2151,8 @@ namespace Be.Windows.Forms
DataObject da = new DataObject(); DataObject da = new DataObject();
// set string buffer clipbard data // 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); da.SetData(typeof(string), sBuffer);
//set memorystream (BinaryData) clipboard data //set memorystream (BinaryData) clipboard data
@ -2229,7 +2232,8 @@ namespace Be.Windows.Forms
else if(da.GetDataPresent(typeof(string))) else if(da.GetDataPresent(typeof(string)))
{ {
string sBuffer = (string)da.GetData(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 else
{ {
@ -2581,9 +2585,37 @@ namespace Be.Windows.Forms
g.DrawString(sB.Substring(1,1), Font, brush, bytePointF, _stringFormat); g.DrawString(sB.Substring(1,1), Font, brush, bytePointF, _stringFormat);
} }
void PaintHexAndStringView(Graphics g, long startByte, long endByte) 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)
{ {
Brush brush = new SolidBrush(GetDefaultForeColor()); System.Diagnostics.Debug.WriteLine(ByteCharConverter.ToString(), "PaintHexAndStringView()", "HexBox");
Brush brush = new SolidBrush(GetDefaultForeColor());
Brush selBrush = new SolidBrush(_selectionForeColor); Brush selBrush = new SolidBrush(_selectionForeColor);
Brush selBrushBack = new SolidBrush(_selectionBackColor); Brush selBrushBack = new SolidBrush(_selectionBackColor);
@ -2612,18 +2644,23 @@ namespace Be.Windows.Forms
} }
string s = new String(ByteCharConverter.ToChar(b), 1); 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) if (isSelectedByte && isStringKeyInterpreterActive)
{ {
g.FillRectangle(selBrushBack, byteStringPointF.X, byteStringPointF.Y, _charSize.Width, _charSize.Height); g.FillRectangle(selBrushBack, byteStringPointF.X, byteStringPointF.Y, _charSize.Width, _charSize.Height);
g.DrawString(s, Font, selBrush, byteStringPointF, _stringFormat); byteStringPointF.X -= cjk_ofs;
g.DrawString(s, Font, selBrush, byteStringPointF, _stringFormat);
} }
else else
{ {
g.DrawString(s, Font, brush, byteStringPointF, _stringFormat); byteStringPointF.X -= cjk_ofs;
g.DrawString(s, Font, brush, byteStringPointF, _stringFormat);
} }
} }
} }
void PaintCurrentBytesSign(Graphics g) void PaintCurrentBytesSign(Graphics g)
{ {
@ -2818,7 +2855,7 @@ namespace Be.Windows.Forms
return; return;
_startByte = (_scrollVpos+1) * _iHexMaxHBytes - _iHexMaxHBytes; _startByte = (_scrollVpos+1) * _iHexMaxHBytes - _iHexMaxHBytes;
_endByte = (long)Math.Min(_byteProvider.Length - 1, _startByte + _iHexMaxBytes); _endByte = (long)Math.Min(_byteProvider.Length - 1, _startByte + _iHexMaxBytes);
} }
#endregion #endregion
@ -3318,9 +3355,9 @@ namespace Be.Windows.Forms
} long _lineInfoOffset = 0; } long _lineInfoOffset = 0;
/// <summary> /// <summary>
/// Gets or sets the hex box´s border style. /// Gets or sets the hex box border style.
/// </summary> /// </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 public BorderStyle BorderStyle
{ {
get { return _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) 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.Left)
| System.Windows.Forms.AnchorStyles.Right))); | 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.InfoForeColor = System.Drawing.Color.Empty;
this.hexBox1.LineInfoVisible = true; this.hexBox1.LineInfoVisible = true;
this.hexBox1.Location = new System.Drawing.Point(0, 24); 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.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.encodingCombo.Items.AddRange(new object[] { this.encodingCombo.Items.AddRange(new object[] {
"S0D", "S0D",
"EBCDIC(CP500)",
"Shift_JIS", "Shift_JIS",
"UTF-7", "UTF-16LE",
"UTF-16BE",
"UTF-8", "UTF-8",
"ASCII"}); "ASCII",
"GBK"});
this.encodingCombo.Name = "encodingCombo"; this.encodingCombo.Name = "encodingCombo";
this.encodingCombo.Size = new System.Drawing.Size(120, 25); this.encodingCombo.Size = new System.Drawing.Size(120, 25);
this.encodingCombo.DropDownClosed += new System.EventHandler(this.encodingCombo_DropDownClosed); this.encodingCombo.DropDownClosed += new System.EventHandler(this.encodingCombo_DropDownClosed);

View File

@ -145,17 +145,18 @@ namespace Tinke
{ {
hexBox1.Height = this.Height - 83; 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); if (tableGrid.Visible) hexBox1.Width = this.Width - (tableGrid.Width + 15);
else hexBox1.Width = this.Width - 16; else hexBox1.Width = this.Width - 16;
} }
private void comboBoxEncoding_SelectedIndexChanged(object sender, EventArgs e) private void comboBoxEncoding_SelectedIndexChanged(object sender, EventArgs e)
{ {
if (encodingCombo.SelectedIndex == 0) if (encodingCombo.SelectedIndex == 0)
bcc = new DefaultByteCharConverter(); bcc = new DefaultByteCharConverter();
else if (encodingCombo.SelectedIndex == 1)
bcc = new EbcdicByteCharProvider();
else else
bcc = new ByteCharConveter(encodingCombo.Text); bcc = new ByteCharConveter(encodingCombo.Text);
@ -290,11 +291,12 @@ namespace Tinke
{ {
hexBox1.Width = this.Width - (tableGrid.Width + 15); hexBox1.Width = this.Width - (tableGrid.Width + 15);
tableGrid.Show(); tableGrid.Show();
VisorHex_Resize(null, null);
} }
private void tableGrid_CellEndEdit(object sender, DataGridViewCellEventArgs e) 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>(); List<char> charas = new List<char>();
for (int i = 0; i < tableGrid.RowCount; i++) for (int i = 0; i < tableGrid.RowCount; i++)
@ -303,7 +305,7 @@ namespace Tinke
!(tableGrid.Rows[i].Cells[1].Value is object)) !(tableGrid.Rows[i].Cells[1].Value is object))
continue; 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)); charas.Add(Convert.ToChar(tableGrid.Rows[i].Cells[1].Value));
} }
hexBox1.ByteCharConverter = new ByteCharTable(codes.ToArray(), charas.ToArray()); hexBox1.ByteCharConverter = new ByteCharTable(codes.ToArray(), charas.ToArray());
@ -353,13 +355,10 @@ namespace Tinke
for (int i = 0; i < lines.Length; i++) for (int i = 0; i < lines.Length; i++)
{ {
int sign_pos = lines[i].IndexOf('='); 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]; char chara = lines[i].Substring(sign_pos + 1)[0];
if (code <= 0x7E) tableGrid.Rows.Add(code.ToString(), chara);
tableGrid.Rows.Add(code.ToString("x").ToUpper(), chara);
else
tableGrid.Rows.Add(code.ToString("x").ToUpper().PadLeft(4, '0'), chara);
} }
tableGrid_CellEndEdit(null, null); tableGrid_CellEndEdit(null, null);
@ -465,29 +464,29 @@ namespace Tinke
public class ByteCharTable : IByteCharConverter public class ByteCharTable : IByteCharConverter
{ {
Dictionary<ulong, char> tableChar; Dictionary<byte, char> tableChar;
Dictionary<char, ulong> tableByte; Dictionary<char, byte> tableByte;
public ByteCharTable(string tablePath) public ByteCharTable(string tablePath)
{ {
tableChar = new Dictionary<ulong, char>(); tableChar = new Dictionary<byte, char>();
tableByte = new Dictionary<char, ulong>(); tableByte = new Dictionary<char, byte>();
String[] lines = File.ReadAllLines(tablePath); String[] lines = File.ReadAllLines(tablePath);
for (int i = 0; i < lines.Length; i++) for (int i = 0; i < lines.Length; i++)
{ {
int sign_pos = lines[i].IndexOf('='); 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]; char chara = lines[i].Substring(sign_pos + 1)[0];
tableChar.Add(code, chara); tableChar.Add(code, chara);
tableByte.Add(chara, code); tableByte.Add(chara, code);
} }
} }
public ByteCharTable(ulong[] codes, char[] charas) public ByteCharTable(byte[] codes, char[] charas)
{ {
tableByte = new Dictionary<char, ulong>(); tableByte = new Dictionary<char, byte>();
tableChar = new Dictionary<ulong, char>(); tableChar = new Dictionary<byte, char>();
for (int i = 0; i < codes.Length; i++) for (int i = 0; i < codes.Length; i++)
{ {
@ -505,58 +504,136 @@ namespace Tinke
else else
return '.'; return '.';
} }
public byte ToByte(char c) public byte[] ToByte(char c)
{ {
byte[] bytes = new byte[1];
if (tableByte.ContainsKey(c)) if (tableByte.ContainsKey(c))
return (byte)tableByte[c]; {
bytes[0] = tableByte[c];
return bytes;
}
else else
return 0; return (new byte[1] { 0 });
}
public Encoding ToEncoding()
{
return Encoding.Default;
} }
} }
public class ByteCharConveter : IByteCharConverter public class ByteCharConveter : IByteCharConverter
{ {
Encoding encoding; Encoding encoding;
List<byte> requeridedChar; List<byte> requiredChar;
List<char> requeridedByte; List<char> requiredByte;
public ByteCharConveter(string encoding) public ByteCharConveter(string encoding)
{ {
this.encoding = Encoding.GetEncoding(encoding); this.encoding = Encoding.GetEncoding(encoding);
requeridedChar = new List<byte>(); requiredChar = new List<byte>();
requeridedByte = new List<char>(); requiredByte = new List<char>();
} }
public byte ToByte(char c) public byte[] ToByte(char c)
{ {
if (encoding.WebName == "shift_jis") byte[] decoded = encoding.GetBytes(new char[] { c });
return ToByteShiftJis(c); return decoded.Length > 0 ? decoded : (new byte[1] { 0 });
return (byte)c;
} }
public char ToChar(byte b) public char ToChar(byte b)
{ {
if (encoding.WebName == "shift_jis") if (encoding.WebName == "shift_jis" || encoding.WebName == "gb2312")
return ToCharShiftJis(b); 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]; return encoding.GetChars(new byte[] { b })[0];
} }
public byte ToByteShiftJis(char c) public char ToCharShiftJisOrGBK(byte b)
{ {
return (byte)c; if (requiredChar.Count == 0 && b > 0x7F)
}
public char ToCharShiftJis(byte b)
{
if (requeridedChar.Count == 0 && b > 0x7F)
{ {
requeridedChar.Add(b); requiredChar.Add(b);
return '\x20'; return '\x20';
} }
requeridedChar.Add(b); requiredChar.Add(b);
string c = new String(encoding.GetChars(requeridedChar.ToArray())); string c = new String(encoding.GetChars(requiredChar.ToArray()));
requeridedChar.Clear(); requiredChar.Clear();
return (c[0] > '\x1F' ? c[0] : '.'); 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 * Set Topmost for waiting window, add "Please wait..." message
* Special fix for Sonic Classic Collection * Special fix for Sonic Classic Collection
* Allow drop files to open * 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 * NFTR plugins: Disable zoom when more than 7489 chars, will fix scrolling issue
* Add toolkit: get header crc32 for r4cce/TTdT * Add toolkit: get header crc32 for r4cce/TTdT
* Allow copy info to Clipboard by mouse double click on RomInfo window * 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 * 3DModels: Update to OpenTK 3.3.3, fix bug on fullscreen btn
* Improved SF Feather Plugin (By @mn1712trungson) * Improved SF Feather Plugin (By @mn1712trungson)
* Core: Improve Nitrocode check when saving rom * 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) TODO: full i18n support (include plugins)
TinkeDSi 0.9.4 TinkeDSi 0.9.4