[Vm-dev] Unicode clipboard in Windows VM...
Andreas Raab
andreas.raab at gmx.de
Fri Jun 1 21:04:32 UTC 2007
Hi Chris -
This looks good; one question though: Do you know whether the windows
clipboard automatically provides the CF_UNICODETEXT -> CF_TEXT translation?
Cheers,
- Andreas
Chris Petsos wrote:
>
>
>
> ------------------------------------------------------------------------
>
> 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
More information about the Vm-dev
mailing list