mirror of
https://github.com/kanjitalk755/macemu.git
synced 2025-01-11 10:30:09 +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_PICT FOURCC('P','I','C','T')
|
||||||
#define TYPE_TEXT FOURCC('T','E','X','T')
|
#define TYPE_TEXT FOURCC('T','E','X','T')
|
||||||
#define TYPE_STYL FOURCC('s','t','y','l')
|
#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 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
|
// 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;
|
static bool we_put_this_data = false;
|
||||||
@ -78,23 +84,52 @@ enum {
|
|||||||
#define smMacSysScript 18
|
#define smMacSysScript 18
|
||||||
#define smMacRegionCode 40
|
#define smMacRegionCode 40
|
||||||
|
|
||||||
static NSString *GetUTIFromFlavor(uint32_t type)
|
static NSString *UTIForFlavor(uint32_t type)
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case TYPE_PICT: return (NSString *)kUTTypePICT;
|
case TYPE_MOOV:
|
||||||
case TYPE_TEXT: return TEXT_FLAVOR_NAME;
|
return (NSString *)kUTTypeQuickTimeMovie;
|
||||||
//case TYPE_TEXT: return UTF16_TEXT_FLAVOR_NAME;
|
case TYPE_SND:
|
||||||
case TYPE_STYL: return STYL_FLAVOR_NAME;
|
return (NSString *)kUTTypeAudio;
|
||||||
case FOURCC('m','o','o','v'): return (NSString *)kUTTypeQuickTimeMovie;
|
case TYPE_ICNS:
|
||||||
case FOURCC('s','n','d',' '): return (NSString *)kUTTypeAudio;
|
return (NSString *)kUTTypeAppleICNS;
|
||||||
//case FOURCC('u','t','x','t'): return UTF16_TEXT_FLAVOR_NAME;
|
default: {
|
||||||
case FOURCC('u','t','1','6'): return UTF16_TEXT_FLAVOR_NAME;
|
CFStringRef typeString = UTCreateStringForOSType(type);
|
||||||
//case FOURCC('u','s','t','l'): return @"????";
|
NSString *uti = (NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassOSType, typeString, NULL);
|
||||||
case FOURCC('i','c','n','s'): return (NSString *)kUTTypeAppleICNS;
|
|
||||||
default: return nil;
|
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
|
* Get current system script encoding on Mac
|
||||||
*/
|
*/
|
||||||
@ -560,25 +595,25 @@ static NSAttributedString *AttributedStringFromMacTEXTAndStyl(NSData *textData,
|
|||||||
if (length < elements * elementSize)
|
if (length < elements * elementSize)
|
||||||
return nil;
|
return nil;
|
||||||
|
|
||||||
NSUInteger pointer = 2;
|
NSUInteger cursor = 2;
|
||||||
|
|
||||||
for (NSUInteger i = 0; i < elements; i++) AUTORELEASE_POOL {
|
for (NSUInteger i = 0; i < elements; i++) AUTORELEASE_POOL {
|
||||||
int32_t startChar = CFSwapInt32BigToHost(*(int32_t *)(bytes + pointer)); pointer += 4;
|
int32_t startChar = CFSwapInt32BigToHost(*(int32_t *)(bytes + cursor)); cursor += 4;
|
||||||
int16_t height __attribute__((unused)) = CFSwapInt16BigToHost(*(int16_t *)&bytes[pointer]); pointer += 2;
|
int16_t height __attribute__((unused)) = CFSwapInt16BigToHost(*(int16_t *)&bytes[cursor]); cursor += 2;
|
||||||
int16_t ascent __attribute__((unused)) = CFSwapInt16BigToHost(*(int16_t *)&bytes[pointer]); pointer += 2;
|
int16_t ascent __attribute__((unused)) = CFSwapInt16BigToHost(*(int16_t *)&bytes[cursor]); cursor += 2;
|
||||||
int16_t fontID = CFSwapInt16BigToHost(*(int16_t *)&bytes[pointer]); pointer += 2;
|
int16_t fontID = CFSwapInt16BigToHost(*(int16_t *)&bytes[cursor]); cursor += 2;
|
||||||
uint8_t face = bytes[pointer]; pointer += 2;
|
uint8_t face = bytes[cursor]; cursor += 2;
|
||||||
int16_t size = CFSwapInt16BigToHost(*(int16_t *)&bytes[pointer]); pointer += 2;
|
int16_t size = CFSwapInt16BigToHost(*(int16_t *)&bytes[cursor]); cursor += 2;
|
||||||
uint16_t red = CFSwapInt16BigToHost(*(int16_t *)&bytes[pointer]); pointer += 2;
|
uint16_t red = CFSwapInt16BigToHost(*(int16_t *)&bytes[cursor]); cursor += 2;
|
||||||
uint16_t green = CFSwapInt16BigToHost(*(int16_t *)&bytes[pointer]); pointer += 2;
|
uint16_t green = CFSwapInt16BigToHost(*(int16_t *)&bytes[cursor]); cursor += 2;
|
||||||
uint16_t blue = CFSwapInt16BigToHost(*(int16_t *)&bytes[pointer]); pointer += 2;
|
uint16_t blue = CFSwapInt16BigToHost(*(int16_t *)&bytes[cursor]); cursor += 2;
|
||||||
|
|
||||||
int32_t nextChar;
|
int32_t nextChar;
|
||||||
|
|
||||||
if (i + 1 == elements)
|
if (i + 1 == elements)
|
||||||
nextChar = [textData length];
|
nextChar = [textData length];
|
||||||
else
|
else
|
||||||
nextChar = CFSwapInt32BigToHost(*(int32_t *)(bytes + pointer));
|
nextChar = CFSwapInt32BigToHost(*(int32_t *)(bytes + cursor));
|
||||||
|
|
||||||
NSMutableDictionary *attrs = [[NSMutableDictionary alloc] init];
|
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];
|
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)
|
static NSData *DataFromPasteboard(NSPasteboard *pboard, NSString *flavor)
|
||||||
{
|
{
|
||||||
NSArray *objs = [pboard readObjectsForClasses:[NSArray arrayWithObject:[NSPasteboardItem class]] options:nil];
|
return [pboard dataForType:flavor];
|
||||||
|
|
||||||
for (NSPasteboardItem *eachItem in objs) {
|
|
||||||
NSData *data = [eachItem dataForType:flavor];
|
|
||||||
|
|
||||||
if ([data length])
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -831,6 +857,8 @@ static void WriteMacTEXTAndStylToPasteboard(NSPasteboard *pboard, NSData *textDa
|
|||||||
[[aStr mutableString] replaceOccurrencesOfString:@"\r" withString:@"\n" options:NSLiteralSearch range:NSMakeRange(0, [aStr length])];
|
[[aStr mutableString] replaceOccurrencesOfString:@"\r" withString:@"\n" options:NSLiteralSearch range:NSMakeRange(0, [aStr length])];
|
||||||
|
|
||||||
[pboard writeObjects:[NSArray arrayWithObject:aStr]];
|
[pboard writeObjects:[NSArray arrayWithObject:aStr]];
|
||||||
|
|
||||||
|
[aStr release];
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1011,6 +1039,8 @@ static void ZeroMacClipboard()
|
|||||||
Host2Mac_memcpy(proc_area, proc, sizeof(proc));
|
Host2Mac_memcpy(proc_area, proc, sizeof(proc));
|
||||||
Execute68k(proc_area, &r);
|
Execute68k(proc_area, &r);
|
||||||
|
|
||||||
|
[g_macScrap removeAllObjects];
|
||||||
|
|
||||||
r.a[0] = proc_area;
|
r.a[0] = proc_area;
|
||||||
Execute68kTrap(0xa01f, &r); // DisposePtr
|
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],
|
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));
|
(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
|
// Allocate space for new scrap in MacOS side
|
||||||
M68kRegisters r;
|
M68kRegisters r;
|
||||||
r.d[0] = [pbData length];
|
r.d[0] = [pbData length];
|
||||||
@ -1062,7 +1102,7 @@ static void WriteDataToMacClipboard(NSData *pbData, uint32_t type)
|
|||||||
r.a[0] = proc_area;
|
r.a[0] = proc_area;
|
||||||
Execute68kTrap(0xa01f, &r); // DisposePtr
|
Execute68kTrap(0xa01f, &r); // DisposePtr
|
||||||
|
|
||||||
[g_macScrap setObject:pbData forKey:[NSNumber numberWithInteger:type]];
|
[g_macScrap setObject:pbData forKey:typeNum];
|
||||||
}
|
}
|
||||||
|
|
||||||
r.a[0] = scrap_area;
|
r.a[0] = scrap_area;
|
||||||
@ -1076,6 +1116,8 @@ static void WriteDataToMacClipboard(NSData *pbData, uint32_t type)
|
|||||||
|
|
||||||
static void ConvertHostPasteboardToMacScrap()
|
static void ConvertHostPasteboardToMacScrap()
|
||||||
{
|
{
|
||||||
|
D(bug("ConvertHostPasteboardToMacScrap\n"));
|
||||||
|
|
||||||
ZeroMacClipboard();
|
ZeroMacClipboard();
|
||||||
|
|
||||||
NSData *stylData = nil;
|
NSData *stylData = nil;
|
||||||
@ -1092,6 +1134,26 @@ static void ConvertHostPasteboardToMacScrap()
|
|||||||
|
|
||||||
if (pictData)
|
if (pictData)
|
||||||
WriteDataToMacClipboard(pictData, TYPE_PICT);
|
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()
|
static void ConvertMacScrapToHostPasteboard()
|
||||||
{
|
{
|
||||||
|
D(bug("ConvertMacScrapToHostPasteboard\n"));
|
||||||
|
|
||||||
BOOL wroteText = NO;
|
BOOL wroteText = NO;
|
||||||
|
|
||||||
[g_pboard clearContents];
|
[g_pboard clearContents];
|
||||||
@ -1107,8 +1171,8 @@ static void ConvertMacScrapToHostPasteboard()
|
|||||||
for (NSNumber *eachTypeNum in g_macScrap) AUTORELEASE_POOL {
|
for (NSNumber *eachTypeNum in g_macScrap) AUTORELEASE_POOL {
|
||||||
uint32_t eachType = [eachTypeNum integerValue];
|
uint32_t eachType = [eachTypeNum integerValue];
|
||||||
|
|
||||||
if (eachType == TYPE_TEXT || eachType == TYPE_STYL) {
|
if (eachType == TYPE_TEXT || eachType == TYPE_STYL || eachType == TYPE_UTXT || eachType == TYPE_UT16 || eachType == TYPE_USTL) {
|
||||||
if(wroteText)
|
if (wroteText)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
NSData *textData;
|
NSData *textData;
|
||||||
@ -1122,28 +1186,39 @@ static void ConvertMacScrapToHostPasteboard()
|
|||||||
wroteText = YES;
|
wroteText = YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sometime, it might be interesting to write a converter for utxt/ustl if possible
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSData *pbData = [g_macScrap objectForKey:eachTypeNum];
|
NSData *pbData = [g_macScrap objectForKey:eachTypeNum];
|
||||||
|
|
||||||
if (pbData) {
|
if (pbData) {
|
||||||
NSString *typeStr = GetUTIFromFlavor(eachType);
|
NSString *typeStr = UTIForFlavor(eachType);
|
||||||
|
|
||||||
if(!typeStr)
|
if (!typeStr)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
NSPasteboardItem *pbItem = [[NSPasteboardItem alloc] init];
|
[g_pboard setData:pbData forType:typeStr];
|
||||||
|
|
||||||
[pbItem setData:pbData forType:typeStr];
|
|
||||||
|
|
||||||
[g_pboard writeObjects:[NSArray arrayWithObject:pbItem]];
|
|
||||||
|
|
||||||
[pbItem release];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
* 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));
|
D(bug("GetScrap handle %p, type %4.4s, offset %d\n", handle, (char *)&type, offset));
|
||||||
|
|
||||||
AUTORELEASE_POOL {
|
AUTORELEASE_POOL {
|
||||||
if (!g_pboard)
|
ConvertHostPasteboardToMacScrapIfChanged();
|
||||||
return;
|
|
||||||
|
|
||||||
if ([g_pboard changeCount] > g_pb_change_count) {
|
|
||||||
ConvertHostPasteboardToMacScrap();
|
|
||||||
g_pb_change_count = [g_pboard changeCount];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user