<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=Content-Type content="text/html; charset=iso-8859-1">
<META content="MSHTML 6.00.6000.16441" name=GENERATOR>
<STYLE></STYLE>
</HEAD>
<BODY bgColor=#ffffff>
<DIV><FONT face=Arial size=2>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...</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT>&nbsp;</DIV><FONT face=Arial size=2>
<DIV><BR>/****************************************************************************/<BR>/*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
Clipboard&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
*/<BR>/****************************************************************************/</DIV>
<DIV>&nbsp;</DIV>
<DIV>int clipboardSize(void)<BR>{ HANDLE h, h2;<BR>&nbsp; WCHAR *src;<BR>&nbsp; 
unsigned char *csrc;<BR>&nbsp; int len, bytesNeeded;</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp; // Do we have text in the clipboard?<BR>&nbsp; 
if(!IsClipboardFormatAvailable(CF_TEXT))<BR>&nbsp;&nbsp;&nbsp; return 
0;<BR>&nbsp; if(!OpenClipboard(stWindow))<BR>&nbsp;&nbsp;&nbsp; return 0;</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp; // Get it in unicode format.<BR>&nbsp; h = 
GetClipboardData(CF_UNICODETEXT);</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp; src = GlobalLock(h);</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp; // How many bytes do we want to store those unicode chars in UTF8 
format?<BR>&nbsp; bytesNeeded = WideCharToMultiByte( CP_UTF8, 0, src, 
-1,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NULL, 0, NULL, NULL );</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp; h2 = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, 
bytesNeeded);<BR>&nbsp; csrc = GlobalLock(h2);</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp; // Convert Unicode text to UTF8.<BR>&nbsp; WideCharToMultiByte( 
CP_UTF8, 0, src, -1,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; csrc, 
bytesNeeded, NULL, NULL );</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp; // Consider CrLf as a 1-byte character.<BR>&nbsp; len = 
bytesNeeded;<BR>&nbsp; while(len--)<BR>&nbsp;&nbsp;&nbsp; if(((*csrc == 13) 
&amp;&amp; (csrc[1] == 10)))<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { 
<BR>&nbsp;bytesNeeded--;<BR>&nbsp;csrc++;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
}<BR>&nbsp;&nbsp;&nbsp; else<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { 
<BR>&nbsp;csrc++;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp; </DIV>
<DIV>&nbsp;</DIV>
<DIV><BR>&nbsp; // Clipboard size is bytesNeeded excluding the terminating 
character.<BR>&nbsp; len = bytesNeeded - 1;</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp; GlobalUnlock(h);<BR>&nbsp; GlobalUnlock(h2);</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp; return len;<BR>}</DIV>
<DIV>&nbsp;</DIV>
<DIV><BR>/* send the given string to the clipboard */<BR>int 
clipboardWriteFromAt(int count, int byteArrayIndex, int startIndex)<BR>{ HANDLE 
h, h2;<BR>&nbsp; unsigned char *src;<BR>&nbsp; int wcharsNeeded, len;<BR>&nbsp; 
WCHAR *out, *tmp;</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp; if(!OpenClipboard(stWindow))<BR>&nbsp;&nbsp;&nbsp; return 0;</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp; // Get the pointer to the byte array.<BR>&nbsp; src = (unsigned char 
*)byteArrayIndex + startIndex;</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp; // How many WCHARs do we need to store the UTF8 represented bytes 
from Squeak?<BR>&nbsp; wcharsNeeded = MultiByteToWideChar( CP_UTF8, 0, 
src,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; count+1, NULL,&nbsp;&nbsp; 
<BR>&nbsp;0 );</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp; // If we have Cr only "returns" then we will need another character 
for Lf.<BR>&nbsp; len = wcharsNeeded * sizeof(WCHAR);<BR>&nbsp; 
while(len--)<BR>&nbsp;&nbsp;&nbsp; if ((*src++ == 13) &amp;&amp; (*src != 
10))<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wcharsNeeded++;&nbsp; </DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp; // Point to start of byte aray.<BR>&nbsp; src = (unsigned char 
*)byteArrayIndex + startIndex;</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp; // Allocate needed memory for wcharsNeeded WCHARs.<BR>&nbsp; h = 
GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, wcharsNeeded * 
sizeof(WCHAR));<BR>&nbsp; out = GlobalLock(h);</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp; // Convert them to Unicode UTF16.<BR>&nbsp; MultiByteToWideChar( 
CP_UTF8, 0, src,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; count+1, 
out,&nbsp;&nbsp; <BR>&nbsp;wcharsNeeded );</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp; // Allocate needed memory for intermediate buffer.<BR>&nbsp; // OK, 
i could do some more work here in order to avoid a whole new buffer just 
for<BR>&nbsp; // fixing the CrLf thing, but it's ok for now...<BR>&nbsp; h2 = 
GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, wcharsNeeded * 
sizeof(WCHAR));<BR>&nbsp; tmp = GlobalLock(h2);</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp; // Add missing Lf characters...<BR>&nbsp; len = 
wcharsNeeded;<BR>&nbsp; while(len--)<BR>&nbsp;&nbsp;&nbsp; if((*out == 
13))<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { /* special case: crlf translation 
*/<BR>&nbsp;*tmp = 13;<BR>&nbsp;tmp++;<BR>&nbsp;*tmp = 
10;<BR>&nbsp;tmp++;<BR>&nbsp;out++;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
}<BR>&nbsp;&nbsp;&nbsp; else<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { /* regular 
case: lookup translation */<BR>&nbsp;*tmp = 
*out;<BR>&nbsp;tmp++;<BR>&nbsp;out++;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp; EmptyClipboard();<BR>&nbsp; GlobalUnlock(h);<BR>&nbsp; 
GlobalUnlock(h2);</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp; // Send the Unicode text to the clipboard.<BR>&nbsp; 
SetClipboardData(CF_UNICODETEXT, h2);</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp; *src=0;<BR>&nbsp; *tmp=0;</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp; /* Note: After setting clipboard data,<BR>&nbsp;&nbsp;&nbsp;&nbsp; 
the memory block previously allocated belongs to<BR>&nbsp;&nbsp;&nbsp;&nbsp; the 
clipboard - not to the app. */<BR>&nbsp; CloseClipboard();<BR>&nbsp; return 
1;<BR>}</DIV>
<DIV>&nbsp;</DIV>
<DIV><BR>/* transfer the clipboard data into the given byte array */<BR>int 
clipboardReadIntoAt(int count, int byteArrayIndex, int startIndex)<BR>{ HANDLE 
h, h2;<BR>&nbsp; unsigned char *dst, *tmp;<BR>&nbsp; WCHAR *src;<BR>&nbsp; int 
tel,len, bytesNeeded;</DIV>
<DIV>&nbsp;</DIV>
<DIV><BR>&nbsp; if(!IsClipboardFormatAvailable(CF_TEXT)) /* check for format 
CF_TEXT */<BR>&nbsp;&nbsp;&nbsp; return 0;</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp; if(!OpenClipboard(stWindow))<BR>&nbsp;&nbsp;&nbsp; return 0;</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp; // Get clipboard data in Unicode format<BR>&nbsp; h = 
GetClipboardData(CF_UNICODETEXT);<BR>&nbsp; src = GlobalLock(h);</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp; // How many bytes do we want to store the Unicode chars to UTF8 
representation?<BR>&nbsp; bytesNeeded = WideCharToMultiByte( CP_UTF8, 0, src, 
-1,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tmp, 0, NULL, NULL ) + 
1;</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp; h2 = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, 
bytesNeeded);<BR>&nbsp; tmp = GlobalLock(h2);</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp; // Convert Unicode text to UTF8.<BR>&nbsp; WideCharToMultiByte( 
CP_UTF8, 0, src, -1,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tmp, 
bytesNeeded, NULL, NULL);</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp; len = bytesNeeded;</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp; // Get the pointer to the byte array.<BR>&nbsp; dst= (unsigned char 
*)byteArrayIndex + startIndex;</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp; while(len--)<BR>&nbsp;&nbsp;&nbsp; if(((*tmp == 13) &amp;&amp; 
(tmp[1] == 10)))<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { /* RvL 
17-04-1998<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; drop 
the line feed after a carriage 
return<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; but leave 
lone line feeds 
alone<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; may 
transfer less than 'len' bytes but who 
cares<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; i.e. if 
they use the clipboardSize there 
should<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; be no 
problem.*/<BR>&nbsp;*dst = 
13;<BR>&nbsp;dst++;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
tmp++;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
tmp++;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; 
else<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { /* regular case: lookup translation 
*/<BR>&nbsp;*dst = 
*tmp;<BR>&nbsp;dst++;<BR>&nbsp;tmp++;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp; 
</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp; GlobalUnlock(h);<BR>&nbsp; GlobalUnlock(h2);<BR>&nbsp; 
CloseClipboard();<BR>&nbsp; return bytesNeeded;<BR>}</DIV>
<DIV>&nbsp;</DIV>
<DIV>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...</DIV>
<DIV>&nbsp;</DIV>
<DIV>fromSystemClipboard: aString</DIV>
<DIV>&nbsp;^ aString convertFromWithConverter: (UTF8TextConverter new).</DIV>
<DIV>&nbsp;</DIV>
<DIV>toSystemClipboard: aString</DIV>
<DIV>&nbsp;| result utfString |<BR>"&nbsp;aString isOctetString ifTrue: [^ 
aString asOctetString]."</DIV>
<DIV>&nbsp;utfString := aString convertToWithConverter: (UTF8TextConverter 
new).</DIV>
<DIV>&nbsp;result _ WriteStream on: (String new: utfString size).</DIV>
<DIV>&nbsp;utfString do: [:each | result nextPut: each].</DIV>
<DIV>&nbsp;^ result contents.</DIV>
<DIV>&nbsp;</DIV>
<DIV>I am pretty sure it will need some minor fixes...</DIV>
<DIV>I'll post links to ready made builds of this version so others can try it 
too, soon.</DIV>
<DIV>&nbsp;</DIV>
<DIV>Any comments, suggestions, C-related fixes are most welcome...</DIV>
<DIV>&nbsp;</DIV>
<DIV>Christos</FONT></DIV></BODY></HTML>