mirror of
https://github.com/kanjitalk755/macemu.git
synced 2024-12-23 19:29:18 +00:00
Yet another clipboard patch for Basilisk / SheepShaver
This patch introduces a few changes: 1. Data of arbitrary Mac OS types which aren't handled (i.e. non text/picture types) will now be passed through to the host pasteboard, just like in the 32-bit code. 2. Reorganization of a few things. 3. Fixed a memory leak (whoops). I'm basically submitting this patch now because I have a few other changes I'm going to try, but since I'm not sure that they're going to work, I thought it better to flush out the changes I've already made at this point first. Thanks, Charles
This commit is contained in:
parent
77862b2103
commit
23ee14227f
@ -42,9 +42,15 @@
|
||||
#define TYPE_PICT FOURCC('P','I','C','T')
|
||||
#define TYPE_TEXT FOURCC('T','E','X','T')
|
||||
#define TYPE_STYL FOURCC('s','t','y','l')
|
||||
#define TYPE_UTXT FOURCC('u','t','x','t')
|
||||
#define TYPE_UT16 FOURCC('u','t','1','6')
|
||||
#define TYPE_USTL FOURCC('u','s','t','l')
|
||||
#define TYPE_MOOV FOURCC('m','o','o','v')
|
||||
#define TYPE_SND FOURCC('s','n','d',' ')
|
||||
#define TYPE_ICNS FOURCC('i','c','n','s')
|
||||
|
||||
static NSPasteboard *g_pboard;
|
||||
static NSUInteger g_pb_change_count = 0;
|
||||
static NSInteger g_pb_change_count = 0;
|
||||
|
||||
// Flag for PutScrap(): the data was put by GetScrap(), don't bounce it back to the MacOS X side
|
||||
static bool we_put_this_data = false;
|
||||
@ -78,23 +84,52 @@ enum {
|
||||
#define smMacSysScript 18
|
||||
#define smMacRegionCode 40
|
||||
|
||||
static NSString *GetUTIFromFlavor(uint32_t type)
|
||||
static NSString *UTIForFlavor(uint32_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case TYPE_PICT: return (NSString *)kUTTypePICT;
|
||||
case TYPE_TEXT: return TEXT_FLAVOR_NAME;
|
||||
//case TYPE_TEXT: return UTF16_TEXT_FLAVOR_NAME;
|
||||
case TYPE_STYL: return STYL_FLAVOR_NAME;
|
||||
case FOURCC('m','o','o','v'): return (NSString *)kUTTypeQuickTimeMovie;
|
||||
case FOURCC('s','n','d',' '): return (NSString *)kUTTypeAudio;
|
||||
//case FOURCC('u','t','x','t'): return UTF16_TEXT_FLAVOR_NAME;
|
||||
case FOURCC('u','t','1','6'): return UTF16_TEXT_FLAVOR_NAME;
|
||||
//case FOURCC('u','s','t','l'): return @"????";
|
||||
case FOURCC('i','c','n','s'): return (NSString *)kUTTypeAppleICNS;
|
||||
default: return nil;
|
||||
case TYPE_MOOV:
|
||||
return (NSString *)kUTTypeQuickTimeMovie;
|
||||
case TYPE_SND:
|
||||
return (NSString *)kUTTypeAudio;
|
||||
case TYPE_ICNS:
|
||||
return (NSString *)kUTTypeAppleICNS;
|
||||
default: {
|
||||
CFStringRef typeString = UTCreateStringForOSType(type);
|
||||
NSString *uti = (NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassOSType, typeString, NULL);
|
||||
|
||||
CFRelease(typeString);
|
||||
|
||||
if (uti == nil || [uti hasPrefix:@"dyn."]) {
|
||||
// The docs threaten that this may stop working at some unspecified point in the future.
|
||||
// However, it seems to work on Lion and Mountain Lion, and there's no other way to do this
|
||||
// that I can see. Most likely, whichever release eventually breaks this will probably also
|
||||
// drop support for the 32-bit applications which typically use these 32-bit scrap types anyway,
|
||||
// making it irrelevant. When this happens, we should include a version check for the version of
|
||||
// OS X that dropped this support, and leave uti alone in that case.
|
||||
|
||||
[uti release];
|
||||
uti = [[NSString alloc] initWithFormat:@"CorePasteboardFlavorType 0x%08x", type];
|
||||
}
|
||||
|
||||
return [uti autorelease];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t FlavorForUTI(NSString *uti)
|
||||
{
|
||||
CFStringRef typeTag = UTTypeCopyPreferredTagWithClass((CFStringRef)uti, kUTTagClassOSType);
|
||||
|
||||
if (!typeTag)
|
||||
return 0;
|
||||
|
||||
uint32_t type = UTGetOSTypeFromString(typeTag);
|
||||
|
||||
CFRelease(typeTag);
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get current system script encoding on Mac
|
||||
*/
|
||||
@ -560,25 +595,25 @@ static NSAttributedString *AttributedStringFromMacTEXTAndStyl(NSData *textData,
|
||||
if (length < elements * elementSize)
|
||||
return nil;
|
||||
|
||||
NSUInteger pointer = 2;
|
||||
NSUInteger cursor = 2;
|
||||
|
||||
for (NSUInteger i = 0; i < elements; i++) AUTORELEASE_POOL {
|
||||
int32_t startChar = CFSwapInt32BigToHost(*(int32_t *)(bytes + pointer)); pointer += 4;
|
||||
int16_t height __attribute__((unused)) = CFSwapInt16BigToHost(*(int16_t *)&bytes[pointer]); pointer += 2;
|
||||
int16_t ascent __attribute__((unused)) = CFSwapInt16BigToHost(*(int16_t *)&bytes[pointer]); pointer += 2;
|
||||
int16_t fontID = CFSwapInt16BigToHost(*(int16_t *)&bytes[pointer]); pointer += 2;
|
||||
uint8_t face = bytes[pointer]; pointer += 2;
|
||||
int16_t size = CFSwapInt16BigToHost(*(int16_t *)&bytes[pointer]); pointer += 2;
|
||||
uint16_t red = CFSwapInt16BigToHost(*(int16_t *)&bytes[pointer]); pointer += 2;
|
||||
uint16_t green = CFSwapInt16BigToHost(*(int16_t *)&bytes[pointer]); pointer += 2;
|
||||
uint16_t blue = CFSwapInt16BigToHost(*(int16_t *)&bytes[pointer]); pointer += 2;
|
||||
int32_t startChar = CFSwapInt32BigToHost(*(int32_t *)(bytes + cursor)); cursor += 4;
|
||||
int16_t height __attribute__((unused)) = CFSwapInt16BigToHost(*(int16_t *)&bytes[cursor]); cursor += 2;
|
||||
int16_t ascent __attribute__((unused)) = CFSwapInt16BigToHost(*(int16_t *)&bytes[cursor]); cursor += 2;
|
||||
int16_t fontID = CFSwapInt16BigToHost(*(int16_t *)&bytes[cursor]); cursor += 2;
|
||||
uint8_t face = bytes[cursor]; cursor += 2;
|
||||
int16_t size = CFSwapInt16BigToHost(*(int16_t *)&bytes[cursor]); cursor += 2;
|
||||
uint16_t red = CFSwapInt16BigToHost(*(int16_t *)&bytes[cursor]); cursor += 2;
|
||||
uint16_t green = CFSwapInt16BigToHost(*(int16_t *)&bytes[cursor]); cursor += 2;
|
||||
uint16_t blue = CFSwapInt16BigToHost(*(int16_t *)&bytes[cursor]); cursor += 2;
|
||||
|
||||
int32_t nextChar;
|
||||
|
||||
if (i + 1 == elements)
|
||||
nextChar = [textData length];
|
||||
else
|
||||
nextChar = CFSwapInt32BigToHost(*(int32_t *)(bytes + pointer));
|
||||
nextChar = CFSwapInt32BigToHost(*(int32_t *)(bytes + cursor));
|
||||
|
||||
NSMutableDictionary *attrs = [[NSMutableDictionary alloc] init];
|
||||
NSColor *color = [NSColor colorWithDeviceRed:(CGFloat)red / 65535.0 green:(CGFloat)green / 65535.0 blue:(CGFloat)blue / 65535.0 alpha:1.0];
|
||||
@ -796,16 +831,7 @@ static NSData *ConvertToMacTEXTAndStyl(NSAttributedString *aStr, NSData **outSty
|
||||
|
||||
static NSData *DataFromPasteboard(NSPasteboard *pboard, NSString *flavor)
|
||||
{
|
||||
NSArray *objs = [pboard readObjectsForClasses:[NSArray arrayWithObject:[NSPasteboardItem class]] options:nil];
|
||||
|
||||
for (NSPasteboardItem *eachItem in objs) {
|
||||
NSData *data = [eachItem dataForType:flavor];
|
||||
|
||||
if ([data length])
|
||||
return data;
|
||||
}
|
||||
|
||||
return nil;
|
||||
return [pboard dataForType:flavor];
|
||||
}
|
||||
|
||||
/*
|
||||
@ -831,6 +857,8 @@ static void WriteMacTEXTAndStylToPasteboard(NSPasteboard *pboard, NSData *textDa
|
||||
[[aStr mutableString] replaceOccurrencesOfString:@"\r" withString:@"\n" options:NSLiteralSearch range:NSMakeRange(0, [aStr length])];
|
||||
|
||||
[pboard writeObjects:[NSArray arrayWithObject:aStr]];
|
||||
|
||||
[aStr release];
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1011,6 +1039,8 @@ static void ZeroMacClipboard()
|
||||
Host2Mac_memcpy(proc_area, proc, sizeof(proc));
|
||||
Execute68k(proc_area, &r);
|
||||
|
||||
[g_macScrap removeAllObjects];
|
||||
|
||||
r.a[0] = proc_area;
|
||||
Execute68kTrap(0xa01f, &r); // DisposePtr
|
||||
}
|
||||
@ -1025,6 +1055,16 @@ static void WriteDataToMacClipboard(NSData *pbData, uint32_t type)
|
||||
D(bug("Writing data %s to Mac clipboard with type '%c%c%c%c'\n", [[pbData description] UTF8String],
|
||||
(type >> 24) & 0xff, (type >> 16) & 0xff, (type >> 8) & 0xff, type & 0xff));
|
||||
|
||||
if ([pbData length] == 0)
|
||||
return;
|
||||
|
||||
NSNumber *typeNum = [NSNumber numberWithInteger:type];
|
||||
|
||||
if ([g_macScrap objectForKey:typeNum]) {
|
||||
// the classic Mac OS can't have more than one object of the same type on the clipboard
|
||||
return;
|
||||
}
|
||||
|
||||
// Allocate space for new scrap in MacOS side
|
||||
M68kRegisters r;
|
||||
r.d[0] = [pbData length];
|
||||
@ -1062,7 +1102,7 @@ static void WriteDataToMacClipboard(NSData *pbData, uint32_t type)
|
||||
r.a[0] = proc_area;
|
||||
Execute68kTrap(0xa01f, &r); // DisposePtr
|
||||
|
||||
[g_macScrap setObject:pbData forKey:[NSNumber numberWithInteger:type]];
|
||||
[g_macScrap setObject:pbData forKey:typeNum];
|
||||
}
|
||||
|
||||
r.a[0] = scrap_area;
|
||||
@ -1076,6 +1116,8 @@ static void WriteDataToMacClipboard(NSData *pbData, uint32_t type)
|
||||
|
||||
static void ConvertHostPasteboardToMacScrap()
|
||||
{
|
||||
D(bug("ConvertHostPasteboardToMacScrap\n"));
|
||||
|
||||
ZeroMacClipboard();
|
||||
|
||||
NSData *stylData = nil;
|
||||
@ -1092,6 +1134,26 @@ static void ConvertHostPasteboardToMacScrap()
|
||||
|
||||
if (pictData)
|
||||
WriteDataToMacClipboard(pictData, TYPE_PICT);
|
||||
|
||||
for (NSString *eachType in [g_pboard types]) {
|
||||
if (UTTypeConformsTo((CFStringRef)eachType, kUTTypeText)) {
|
||||
// text types are already handled
|
||||
continue;
|
||||
}
|
||||
|
||||
if (UTTypeConformsTo((CFStringRef)eachType, kUTTypeImage)) {
|
||||
// image types are already handled
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t type = FlavorForUTI(eachType);
|
||||
|
||||
// skip styl and ustl as well; those fall under text, which is handled already
|
||||
if (!type || type == TYPE_STYL || type == TYPE_USTL)
|
||||
continue;
|
||||
|
||||
WriteDataToMacClipboard(DataFromPasteboard(g_pboard, eachType), type);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1100,6 +1162,8 @@ static void ConvertHostPasteboardToMacScrap()
|
||||
|
||||
static void ConvertMacScrapToHostPasteboard()
|
||||
{
|
||||
D(bug("ConvertMacScrapToHostPasteboard\n"));
|
||||
|
||||
BOOL wroteText = NO;
|
||||
|
||||
[g_pboard clearContents];
|
||||
@ -1107,8 +1171,8 @@ static void ConvertMacScrapToHostPasteboard()
|
||||
for (NSNumber *eachTypeNum in g_macScrap) AUTORELEASE_POOL {
|
||||
uint32_t eachType = [eachTypeNum integerValue];
|
||||
|
||||
if (eachType == TYPE_TEXT || eachType == TYPE_STYL) {
|
||||
if(wroteText)
|
||||
if (eachType == TYPE_TEXT || eachType == TYPE_STYL || eachType == TYPE_UTXT || eachType == TYPE_UT16 || eachType == TYPE_USTL) {
|
||||
if (wroteText)
|
||||
continue;
|
||||
|
||||
NSData *textData;
|
||||
@ -1122,28 +1186,39 @@ static void ConvertMacScrapToHostPasteboard()
|
||||
wroteText = YES;
|
||||
}
|
||||
|
||||
// sometime, it might be interesting to write a converter for utxt/ustl if possible
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
NSData *pbData = [g_macScrap objectForKey:eachTypeNum];
|
||||
|
||||
if (pbData) {
|
||||
NSString *typeStr = GetUTIFromFlavor(eachType);
|
||||
NSString *typeStr = UTIForFlavor(eachType);
|
||||
|
||||
if(!typeStr)
|
||||
if (!typeStr)
|
||||
continue;
|
||||
|
||||
NSPasteboardItem *pbItem = [[NSPasteboardItem alloc] init];
|
||||
|
||||
[pbItem setData:pbData forType:typeStr];
|
||||
|
||||
[g_pboard writeObjects:[NSArray arrayWithObject:pbItem]];
|
||||
|
||||
[pbItem release];
|
||||
[g_pboard setData:pbData forType:typeStr];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether the pasteboard has changed since our last check; if it has, write it to the emulated pasteboard
|
||||
*/
|
||||
|
||||
static void ConvertHostPasteboardToMacScrapIfChanged()
|
||||
{
|
||||
if (!g_pboard)
|
||||
return;
|
||||
|
||||
if ([g_pboard changeCount] > g_pb_change_count) {
|
||||
ConvertHostPasteboardToMacScrap();
|
||||
g_pb_change_count = [g_pboard changeCount];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Mac application reads clipboard
|
||||
*/
|
||||
@ -1153,13 +1228,7 @@ void GetScrap(void **handle, uint32_t type, int32_t offset)
|
||||
D(bug("GetScrap handle %p, type %4.4s, offset %d\n", handle, (char *)&type, offset));
|
||||
|
||||
AUTORELEASE_POOL {
|
||||
if (!g_pboard)
|
||||
return;
|
||||
|
||||
if ([g_pboard changeCount] > g_pb_change_count) {
|
||||
ConvertHostPasteboardToMacScrap();
|
||||
g_pb_change_count = [g_pboard changeCount];
|
||||
}
|
||||
ConvertHostPasteboardToMacScrapIfChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user