jacobslusser / ScintillaNET

A Windows Forms control, wrapper, and bindings for the Scintilla text editor.
MIT License
963 stars 242 forks source link

Display binary data #398

Open jvkaam opened 6 years ago

jvkaam commented 6 years ago

Hi,

When I read a file in Notepad++ the representation sometimes shows some NUL, SCH or SUB (white letters on a black background) codes of characters that cannot be shown. In Scintilla the representation stops at the first character (that has an ASCII 0). Is there a setting that can change this behavior?

jacobslusser commented 5 years ago

Yes, this is supported, but I can't recall what API it is off the top of my head.

craiovea commented 3 years ago

I have been struggling to find the answer to this question as well. I cannot tell from the source code of Notepadd ++ and Scintilla.NET which is the API that makes this happen. @jacobslusser, if you have recalled in the meantime, can you please share? Thank you.

AlbertBecker commented 3 years ago

Use Scintilla.AppendText instead assigning Scintilla.Text. You can try the following snipped code:

var scintilla = new ScintillaNET.Scintilla();
byte[] buffer = null;
using (FileStream fs = File.OpenRead("YourFileName"))
{
    long size = fs.Length;
    buffer = new byte[size];
    size = fs.Read(buffer, 0, (int)size);
}
// Do not use: scintilla.Text = Encoding.Default.GetString(buffer); 
// Use instead:
scintilla.Text = "";
scintilla.AppendText(Encoding.Default.GetString(buffer));
cyber960 commented 3 years ago

The AppendText method that AlbertBecker mentioned works properly since SCI_APPENDTEXT does not take a null terminated string whereas SCI_SETTEXT does. The Text property should be overridden to support this by adding a simple else if statement in the setter. VPKSoft can you please merge this fix into your unofficial.ScintillaNET fork?

public unsafe override string Text
{
    get
    {
        var length = DirectMessage(NativeMethods.SCI_GETTEXTLENGTH).ToInt32();
        var ptr = DirectMessage(NativeMethods.SCI_GETRANGEPOINTER, new IntPtr(0), new IntPtr(length));
        if (ptr == IntPtr.Zero)
            return string.Empty;

        // Assumption is that moving the gap will always be equal to or less expensive
        // than using one of the APIs which requires an intermediate buffer.
        var text = new string((sbyte*)ptr, 0, length, Encoding);
        return text;
    }
    set
    {
        if (string.IsNullOrEmpty(value))
        {
            DirectMessage(NativeMethods.SCI_CLEARALL);
        }
        else if (value.Contains('\0'))
        {
            DirectMessage(NativeMethods.SCI_CLEARALL);
            AppendText(value);
        }
        else
        {

            fixed (byte* bp = Helpers.GetBytes(value, Encoding, zeroTerminated: true))
                DirectMessage(NativeMethods.SCI_SETTEXT, IntPtr.Zero, new IntPtr(bp));
        }
    }
}
VPKSoft commented 3 years ago

Version 3.8.5 should now include the change - thank you 👍