[squeak-dev] Re: Pasting unicode (was Re: Pharo:: Re: Cuis update)

Andreas Raab andreas.raab at gmx.de
Fri Apr 17 20:35:22 UTC 2009


Bert Freudenberg wrote:
> Below that the paste from ru.wikipedia. These are actual question marks 
> (ASCII 63), the Mac VM does not paste Unicode even if setting 
> SqueakEncodingType to UTF-8 (only the extended clipboard plugin does this).

Fortunately, at least that part is very easy to fix. I asked our CEO if 
we could release our clipboard support code back to the community and he 
agreed, so find attched an sqMacUIClipBoard.c version which does support 
Unicode copy/paste properly via UTF-8 (this should work as a drop-in 
replacement to the existing sqMacUIClipBoard.c). Brought to you by the 
friendly folks at Qwaq.

Cheers,
   - Andreas
-------------- next part --------------
Copyright (c) 2008-2009 Qwaq Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-------------- next part --------------
/****************************************************************************
 *   PROJECT: Mac clipboard interface.
 *   FILE:    sqMacUIClipBoard.c
 *   CONTENT: 
 *
 *   AUTHOR:  John Maloney, John McIntosh, and others.
 *   ADDRESS: 
 *   EMAIL:   johnmci at smalltalkconsulting.com
 *   RCSID:   $Id: sqMacUIClipBoard.c 1344 2006-03-05 21:07:15Z johnmci $
 *
 *   NOTES: 
 *  Feb 22nd, 2002, JMM moved code into 10 other files, see sqMacMain.c for comments
 3.8.11b1 Mar 4th, 2006 JMM refactor, cleanup and add headless support
 *
 *  Aug 2008 - BGF changed to Pasteboard API's for UTF-8 compatibility;
 *			  was using deprecated Scrap Manager.
 *****************************************************************************/
#include "sq.h"
#include "sqMacUIClipBoard.h"

int clipboardSize(void);

/*** Clipboard Support (text only for now) ***/

void SetUpClipboard(void) {
}

void FreeClipboard(void) {
}

/**
 * Implementation straight out of Apple's pasteboard guide. 
 * Assumes the image treats Macintosh as having UTF-8 clipboard.
 * Puts both UTF-8 and UTF-16 flavors into the scrap,
 * to reach the widest variety of applications.
 */
sqInt clipboardWriteFromAt(sqInt count, sqInt byteArrayIndex, sqInt startIndex) {
	
	OSStatus err;
	PasteboardRef pb;
	CFDataRef data;
	CFStringRef str;
	CFRange range;
	CFIndex converted, needed;
	UInt8 * bytes;
	
	err = PasteboardCreate (kPasteboardClipboard, & pb);
	if (err) return 0;
	
	err = PasteboardClear(pb);
	if (err) return 0;
	
	PasteboardSynchronize (pb);
	data = CFDataCreate (kCFAllocatorDefault, (UInt8*) (byteArrayIndex+startIndex), count);
	if (! data) return 0;
 	
	err = PasteboardPutItemFlavor( pb, (PasteboardItemID)1, kUTTypeUTF8PlainText, data, 0);
	if (err) return 0;
	
	/** To get the UTF-16 form most apps (e.g. Word, Thunderbird) need, use an intermediate CFString **/
	str = CFStringCreateWithBytes(kCFAllocatorDefault, (UInt8*) (byteArrayIndex+startIndex), count, kCFStringEncodingUTF8, false);
	if (! str) { return 0; }
	
	range.length = CFStringGetLength( str );
	range.location = 0;
	/** First call just gives us the needed size **/
	converted = CFStringGetBytes( 
								 str,
								 range,
								 kCFStringEncodingUTF16,
								 '?',
								 false,
								 NULL,		/** Meaning, tell me how many bytes are needed **/
								 0,
								 & needed);
	if (converted > 0) {
		bytes = malloc(needed);
		converted = CFStringGetBytes( 
									 str,
									 range,
									 kCFStringEncodingUTF16,
									 '?',
									 false,
									 bytes,		/** This time, we're really encoding **/
									 needed,
									 NULL);
		if (converted > 0) {
			data = CFDataCreateWithBytesNoCopy (kCFAllocatorDefault, bytes, needed, kCFAllocatorMalloc);
			err = PasteboardPutItemFlavor (pb, (PasteboardItemID)1, kUTTypeUTF16PlainText, data, 0);
			CFRelease (str);
			return (err = 0);	
		} else {
			free (bytes);
		}
	}
	CFRelease (str);
	return 0;
}

/**
 * Implementation straight out of Apple's pasteboard guide.
 * Just look for the first Pasteboard item whose data flavor conforms to utf-16,
 * and convert it into a UTF-8 string for the VM.
 * (UTF-16 seems the pasteboard lingua-franca.)
 */
sqInt clipboardSize(void) {
	ItemCount itemCount;
	OSStatus err;
	CFRange range;
	CFIndex itemIndex;
	CFIndex flavorIndex;
	CFIndex converted, needed;
	CFStringRef str;
	PasteboardRef pb;
	
	err = PasteboardCreate (kPasteboardClipboard, & pb);
	if (err) return 0;
	PasteboardSynchronize (pb);
	err = PasteboardGetItemCount (pb, &itemCount);	
	if (err) return 0;
	
	for (itemIndex = 1; itemIndex <= itemCount; itemIndex++) {
		
        PasteboardItemID    itemID;
        CFArrayRef          flavorTypeArray;
        CFIndex             flavorCount;
		
        err = PasteboardGetItemIdentifier( pb, itemIndex, &itemID );
		if (err) continue;
		err = PasteboardCopyItemFlavors( pb, itemID, &flavorTypeArray );
		
		if (err) continue;
        flavorCount = CFArrayGetCount( flavorTypeArray );
        for( flavorIndex = 0; flavorIndex < flavorCount; flavorIndex++ )
        {
			
			CFStringRef             flavorType;
			CFDataRef               flavorData;
			
			flavorType = (CFStringRef) CFArrayGetValueAtIndex (flavorTypeArray, flavorIndex);
			if (err) continue;
			
			/** We have to search for UTF-16 as that seems to be the lingua franca;
			 if this is done looking for UTF-8, various paste-sources (Thunderbird, Microsoft Office)
			 seem not to yield conforming scraps.
			 **/
			
			if (UTTypeConformsTo(flavorType, kUTTypeUTF16PlainText))
            {
                err = PasteboardCopyItemFlavorData(pb, itemID, flavorType, &flavorData );
				if (! err) {
					
					/** Convert the UTF-16 to UTF-8 by making an intermediate CFString **/
					str = CFStringCreateWithBytes(kCFAllocatorDefault, CFDataGetBytePtr(flavorData), CFDataGetLength(flavorData), kCFStringEncodingUTF16, false);
					if (! str) {
						CFRelease (flavorData);
						CFRelease (flavorTypeArray);
						return 0;
					}
					range.length = CFStringGetLength(str);
					range.location = 0;
					
					converted = CFStringGetBytes( 
												 str,
												 range,
												 kCFStringEncodingUTF8,
												 '?',
												 false,
												 NULL,		/** Meaning, tell me how many bytes are needed **/
												 0,
												 & needed);
					CFRelease (str);
					CFRelease (flavorData);
					CFRelease (flavorTypeArray);
					if (converted > 0) {	/* Meaning, conversion is possible */
						return needed;
					}
					return 0;
				}
			}
		}
		CFRelease (flavorTypeArray);
	}
	return 0;
}

/*
 * Implementation straight out of Apple's pasteboard guide.
 * Just look for the first Pasteboard item whose data flavor is conforms to utf-8.
 */
sqInt clipboardReadIntoAt(sqInt count, sqInt byteArrayPtr, sqInt startIndex) {
	
	ItemCount itemCount;
	CFIndex itemIndex;
	CFIndex flavorIndex;
	OSStatus err;
	
	PasteboardRef pb;
	err = PasteboardCreate (kPasteboardClipboard, & pb);
	if (err) return 0;
	
	PasteboardSynchronize (pb);
	err = PasteboardGetItemCount (pb, &itemCount);	
	if (err) return 0;
	
	for (itemIndex = 1; itemIndex <= itemCount; itemIndex++) 	{
		
        PasteboardItemID    itemID;
        CFArrayRef          flavorTypeArray;
        CFIndex             flavorCount;
		
        err = PasteboardGetItemIdentifier( pb, itemIndex, &itemID );
		if (err) continue;
        err = PasteboardCopyItemFlavors( pb, itemID, &flavorTypeArray );
		if (err) continue;
		
        flavorCount = CFArrayGetCount( flavorTypeArray );
        for( flavorIndex = 0; flavorIndex < flavorCount; flavorIndex++ )
        {
			CFStringRef flavorType;
			CFDataRef   flavorData;
			
			flavorType = (CFStringRef) CFArrayGetValueAtIndex(flavorTypeArray, flavorIndex);
			
			/** We have to search for UTF-16 as that seems to be the lingua franca;
			 if this is done looking for UTF-8, various paste-sources (Thunderbird, Microsoft Office)
			 seem not to yield conforming scraps.
			 **/
			if (UTTypeConformsTo(flavorType, kUTTypeUTF16PlainText))
       		{
				CFRange range;
				CFIndex converted, bytesUsed;
				CFStringRef str;
				err = PasteboardCopyItemFlavorData (pb, itemID,  flavorType, &flavorData);
				if (!err) {
					
					/** Convert the UTF-16 to UTF-8 by making an intermediate CFString **/
					str = CFStringCreateWithBytes (kCFAllocatorDefault, CFDataGetBytePtr(flavorData), CFDataGetLength(flavorData), kCFStringEncodingUTF16, false);
					if (! str) {
						CFRelease (flavorData);
						CFRelease (flavorTypeArray);
						return 0;
					}
					range.length = CFStringGetLength (str);
					range.location = 0;
					
					converted = CFStringGetBytes( 
												 str,
												 range,
												 kCFStringEncodingUTF8,
												 '?',
												 false,
												 (UInt8*) (byteArrayPtr+startIndex),
												 count,
												 & bytesUsed);
					CFRelease (str);
					CFRelease (flavorData);
					CFRelease (flavorTypeArray);
					return (converted > 0) ? bytesUsed : 0;
				}
			}
		}
		CFRelease (flavorTypeArray);
	}
	return 0;
}



More information about the Squeak-dev mailing list