[Mono-bugs] [Bug 386528] New: Character input with the Carbon backend has endian ( and other) problems

bugzilla_noreply at novell.com bugzilla_noreply at novell.com
Sun May 4 16:43:20 EDT 2008


https://bugzilla.novell.com/show_bug.cgi?id=386528


           Summary: Character input with the Carbon backend has endian (and
                    other) problems
           Product: Mono: Class Libraries
           Version: 1.9.0
          Platform: Macintosh
        OS/Version: Mac OS X 10.4
            Status: NEW
          Severity: Major
          Priority: P5 - None
         Component: Windows.Forms
        AssignedTo: mono-bugs at lists.ximian.com
        ReportedBy: jesjones at mindspring.com
         QAContact: mono-bugs at lists.ximian.com
          Found By: ---


KeyboardHandler::ProcessText has the following problems:

1) kEventParamTextInputSendText returns a Unicode string using the native
endian. This means bdata[0] may return either the low or high byte of the
code-point depending on if you are running on an Intel or a PowerPC mac.

2) The key_filter_table is only checked using a single byte from the
code-point. It should instead check to see if the high byte is zero and then
use the low byte.

3) wParam is only assigned a byte from the code point instead of the entire
code point.

Here's a fix for these issues (tested on a PowerPC mac). Note that with these
fixes stuff like option-p can be used to enter the pi character even on Intel.

internal const uint typeUTF16ExternalRepresentation = 0x75743136; /* 'ut16' 
big-endian 16 bit unicode with optional byte-order-mark, or little-endian 16
bit unicode with required byte-order-mark. */

public void ProcessText (IntPtr eventref, ref MSG msg) 
{
        // Get the size of the unicode buffer. Note that unlike typeUnicodeText
typeUTF16ExternalRepresentation
        // provides enough information to determine the endian of the text we
get back. TODO: we should really be checking the results of all Carbon calls
for errors...
        UInt32 size = 0;
        GetEventParameter (eventref, kEventParamTextInputSendText,
typeUTF16ExternalRepresentation, IntPtr.Zero, 0, ref size, IntPtr.Zero);

        // get the actual text buffer
        IntPtr buffer = Marshal.AllocHGlobal ((int) size);
        GetEventParameter (eventref, kEventParamTextInputSendText,
typeUTF16ExternalRepresentation, IntPtr.Zero, size, IntPtr.Zero, buffer);

        byte[] bdata = new byte [size];
        Marshal.Copy (buffer, bdata, 0, (int) size);
        Marshal.FreeHGlobal (buffer);

        int cp = GetCodePoint(bdata);
        int high = cp >> 8;
        int low = cp & 0xFF;

        if (high != 0 || key_filter_table [low] == 0x00) {        
                msg.message = Msg.WM_CHAR;
                msg.wParam = (IntPtr) cp;
                msg.lParam = IntPtr.Zero;
                msg.hwnd = XplatUICarbon.FocusWindow;
        }
}

private static int GetCodePoint(byte[] data)
{
        int index = 0;

        // Check for a byte-order-mark (if the BOM is missing the text
        // will be big endian).
        bool bigEndian = true;
        if (data.Length >= 2)
        {
                if (data[0] == 0xFE && data[1] == 0xFF)
                {
                        index = 2;
                }
                else if (data[0] == 0xFF && data[1] == 0xFE)
                {
                        bigEndian = false;
                        index = 2;
                }
        }

        // We should now have at least two bytes of data.
        int cp;
        int bytes = data.Length - index;
        if (bytes == 2)
        {
                if (bigEndian)
                        cp = (data[index] << 8) | data[index + 1];
                else
                        cp = (data[index + 1] << 8) | data[index];
        }
        else if (bytes > 2)
        {    
                // TODO: This can definitely happen and we should handle it.
For now
                // we'll replace whatever the user typed with an ellipsis so
they know
                // something bad happened.
                cp = 0x2027;
        }
        else
        {
                // This should not happen.
                throw new Exception(string.Format("Got {0} bytes of data from
kEventParamTextInputSendText", bytes));
        }

        return cp;
}


-- 
Configure bugmail: https://bugzilla.novell.com/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the QA contact for the bug.
You are the assignee for the bug.


More information about the mono-bugs mailing list