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.