Jeremy White wrote:
Seems like that should suffice, assuming that MSDN's definition of "character" is a 32-bit UCS-2 character. I have no clue if MS supports UCS-2 characters that use multiple 32-bit numbers to represent a single character, but I believe such are legal. And if they do support them, I don't know if they call them one character or two, or if they are even consistent about their counts, or their definition of "character" ("That depends on what you mean by 'is'.")

That's a good point - more research would be needed. At least with one function doing all the string memory allocation we've only got one place to change.

I haven't really checked this out fully, but looked into some of the quite recently (I'm still thinking in the background about what we would need to do to get a Unicode version of Win32::GUI).

The return value is the number of TCHARs required, where a TCHAR is one byte (char) or 2 bytes (w_char?) depending on the setting of the _UNICODE pre-processor symbol at compile time, so the right way to do this is:
safemalloc((num_bytes_required + 1) * sizeof(TCHAR));

I don't believe that we need to worry about the 4-byte representations (surrogate pairs), as these are accounted for in the return value.

I think, that there's a better implementation though; what we seem to currenlty have is:
(1) safealloc some bytes
(2) get SendMessage to copy the text into those byte
(3) return a pointer (which is then converted by xsubpp (via typemap) into code that creates a mortalised PV, which in turn must do a malloc and copy)
(4) free the bytes we safealloc'd

It would save a malloc, copy and free if we created the mortalised PV at the right size ourselves, passed the string pointer to SendMessage() and returned the PV.

This would lead to a more complex macro/function, but would, I think be worth it.

I'm not sure I got all this right, but I think you'll get the idea (there may be a better way to create the SV and grow it than I've shown here):

void
GetLBText(handle,index)
    HWND handle
    WPARAM index
PREINIT:
    STRLEN cbString;
    SV * text;
CODE:
    cbString = SendMessage(handle, CB_GETLBTEXTLEN, index, 0);
    if(cbString != LB_ERR) {
        text = newSVpvn((char *)NULL, 0);
        
        if(SendMessage(handle, CB_GETLBTEXT,
                       index,
                       (LPARAM) SvGROW(text, cdString+1) ) != LB_ERR) {
            PUSHs(text);
            XSRETURN(1);
        } else {
            XSRETURN_UNDEF;
        }
    } else {
        XSRETURN_UNDEF;
    }

This works nicely for the ANSI versions of the call, which return th ANSI encoded string of bytes that is suitable for directly inserting into the PV, but this doesn't address the Unicode issue at all, where the string copied by CB_GETLBTEXT would have to be converted from UCS-2 to utf-8 and then copied into the SV, setting the SVf_utf8 flag appropriately.

Regards,
Rob.

Reply via email to