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
|
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 |
> This looks good; one question though: Do you know whether the windows > clipboard automatically provides the CF_UNICODETEXT -> CF_TEXT > translation? I suppose you are asking if IsClipboardFormatAvailable(CF_TEXT) returns TRUE when we have CF_UNICODETEXT on the clipboard... Well... from what i saw it does...even the vice versa is again evaluated to TRUE. Actually i couldn' see any difference in asking IsClipboardFormatAvailable(CF_TEXT) from IsClipboardFormatAvailable(CF_UNICODETEXT) when transporting UTF-8 chars to/from the clipboard. Christos. |
Free forum by Nabble | Edit this page |