[Vm-dev] Unicode clipboard in Windows VM...
Chris Petsos
chrispetsos at sch.gr
Fri Jun 1 20:03:09 UTC 2007
Ok guys... this is my solution for unicode clipboard support in Windows VM... It works fine... I can make some improvements in memory management but it's ok for now...
/****************************************************************************/
/* Clipboard */
/****************************************************************************/
int clipboardSize(void)
{ HANDLE h, h2;
WCHAR *src;
unsigned char *csrc;
int len, bytesNeeded;
// Do we have text in the clipboard?
if(!IsClipboardFormatAvailable(CF_TEXT))
return 0;
if(!OpenClipboard(stWindow))
return 0;
// Get it in unicode format.
h = GetClipboardData(CF_UNICODETEXT);
src = GlobalLock(h);
// How many bytes do we want to store those unicode chars in UTF8 format?
bytesNeeded = WideCharToMultiByte( CP_UTF8, 0, src, -1,
NULL, 0, NULL, NULL );
h2 = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, bytesNeeded);
csrc = GlobalLock(h2);
// Convert Unicode text to UTF8.
WideCharToMultiByte( CP_UTF8, 0, src, -1,
csrc, bytesNeeded, NULL, NULL );
// Consider CrLf as a 1-byte character.
len = bytesNeeded;
while(len--)
if(((*csrc == 13) && (csrc[1] == 10)))
{
bytesNeeded--;
csrc++;
}
else
{
csrc++;
}
// Clipboard size is bytesNeeded excluding the terminating character.
len = bytesNeeded - 1;
GlobalUnlock(h);
GlobalUnlock(h2);
return len;
}
/* send the given string to the clipboard */
int clipboardWriteFromAt(int count, int byteArrayIndex, int startIndex)
{ HANDLE h, h2;
unsigned char *src;
int wcharsNeeded, len;
WCHAR *out, *tmp;
if(!OpenClipboard(stWindow))
return 0;
// Get the pointer to the byte array.
src = (unsigned char *)byteArrayIndex + startIndex;
// How many WCHARs do we need to store the UTF8 represented bytes from Squeak?
wcharsNeeded = MultiByteToWideChar( CP_UTF8, 0, src,
count+1, NULL,
0 );
// If we have Cr only "returns" then we will need another character for Lf.
len = wcharsNeeded * sizeof(WCHAR);
while(len--)
if ((*src++ == 13) && (*src != 10))
wcharsNeeded++;
// Point to start of byte aray.
src = (unsigned char *)byteArrayIndex + startIndex;
// Allocate needed memory for wcharsNeeded WCHARs.
h = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, wcharsNeeded * sizeof(WCHAR));
out = GlobalLock(h);
// Convert them to Unicode UTF16.
MultiByteToWideChar( CP_UTF8, 0, src,
count+1, out,
wcharsNeeded );
// Allocate needed memory for intermediate buffer.
// OK, i could do some more work here in order to avoid a whole new buffer just for
// fixing the CrLf thing, but it's ok for now...
h2 = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, wcharsNeeded * sizeof(WCHAR));
tmp = GlobalLock(h2);
// Add missing Lf characters...
len = wcharsNeeded;
while(len--)
if((*out == 13))
{ /* special case: crlf translation */
*tmp = 13;
tmp++;
*tmp = 10;
tmp++;
out++;
}
else
{ /* regular case: lookup translation */
*tmp = *out;
tmp++;
out++;
}
EmptyClipboard();
GlobalUnlock(h);
GlobalUnlock(h2);
// Send the Unicode text to the clipboard.
SetClipboardData(CF_UNICODETEXT, h2);
*src=0;
*tmp=0;
/* Note: After setting clipboard data,
the memory block previously allocated belongs to
the clipboard - not to the app. */
CloseClipboard();
return 1;
}
/* transfer the clipboard data into the given byte array */
int clipboardReadIntoAt(int count, int byteArrayIndex, int startIndex)
{ HANDLE h, h2;
unsigned char *dst, *tmp;
WCHAR *src;
int tel,len, bytesNeeded;
if(!IsClipboardFormatAvailable(CF_TEXT)) /* check for format CF_TEXT */
return 0;
if(!OpenClipboard(stWindow))
return 0;
// Get clipboard data in Unicode format
h = GetClipboardData(CF_UNICODETEXT);
src = GlobalLock(h);
// How many bytes do we want to store the Unicode chars to UTF8 representation?
bytesNeeded = WideCharToMultiByte( CP_UTF8, 0, src, -1,
tmp, 0, NULL, NULL ) + 1;
h2 = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, bytesNeeded);
tmp = GlobalLock(h2);
// Convert Unicode text to UTF8.
WideCharToMultiByte( CP_UTF8, 0, src, -1,
tmp, bytesNeeded, NULL, NULL);
len = bytesNeeded;
// Get the pointer to the byte array.
dst= (unsigned char *)byteArrayIndex + startIndex;
while(len--)
if(((*tmp == 13) && (tmp[1] == 10)))
{ /* RvL 17-04-1998
drop the line feed after a carriage return
but leave lone line feeds alone
may transfer less than 'len' bytes but who cares
i.e. if they use the clipboardSize there should
be no problem.*/
*dst = 13;
dst++;
tmp++;
tmp++;
}
else
{ /* regular case: lookup translation */
*dst = *tmp;
dst++;
tmp++;
}
GlobalUnlock(h);
GlobalUnlock(h2);
CloseClipboard();
return bytesNeeded;
}
The only thing is that in the image side you need a UTF8TextConverter before sending text to the clipboard or getting from it...so, my unicode clipboard interpreter has these methods...
fromSystemClipboard: aString
^ aString convertFromWithConverter: (UTF8TextConverter new).
toSystemClipboard: aString
| result utfString |
" aString isOctetString ifTrue: [^ aString asOctetString]."
utfString := aString convertToWithConverter: (UTF8TextConverter new).
result _ WriteStream on: (String new: utfString size).
utfString do: [:each | result nextPut: each].
^ result contents.
I am pretty sure it will need some minor fixes...
I'll post links to ready made builds of this version so others can try it too, soon.
Any comments, suggestions, C-related fixes are most welcome...
Christos
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20070601/15685f9f/attachment.htm
More information about the Vm-dev
mailing list