/* * tkMacOSXServices.c -- *\ * This file allows the integration of Tk and the Cocoa NSServices API. * * Copyright © 2010-2019 Kevin Walzer/WordTech Communications LLC. * Copyright © 2019 Marc Culler. * Copyright © 2010 Adrian Robert. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include #include /* * Event proc which calls the PerformService procedure. */ static int ServicesEventProc( TCL_UNUSED(Tcl_Event *), TCL_UNUSED(int)) { TkMainInfo *info = TkGetMainInfoList(); Tcl_GlobalEval(info->interp, "::tk::mac::PerformService"); return 1; } /* * The Wish application can send the current selection in the Tk clipboard * to other applications which accept messages of type NSString. The TkService * object provides this service via its provideService method. (The method * must be specified in the application's Info.plist file for this to work.) */ @interface TkService : NSObject { } + (void) initialize; - (void) provideService:(NSPasteboard *)pboard userData:(NSString *)data error:(NSString **)error; - (BOOL) writeSelectionToPasteboard:(NSPasteboard *)pboard types:(NSArray *)types; @end /* * Class methods. */ @implementation TkService + (void) initialize { NSArray *sendTypes = [NSArray arrayWithObjects:@"NSStringPboardType", @"NSPasteboardTypeString", nil]; [NSApp registerServicesMenuSendTypes:sendTypes returnTypes:sendTypes]; return; } /* * Get the current Tk selection and copy it to the system pasteboard. */ - (BOOL)writeSelectionToPasteboard:(NSPasteboard *)pboard types:(NSArray *)types { NSArray *typesDeclared = nil; NSString *pboardType = nil; TkMainInfo *info = TkGetMainInfoList(); for (NSString *typeString in types) { if ([typeString isEqualToString:@"NSStringPboardType"] || [typeString isEqualToString:@"NSPasteboardTypeString"]) { typesDeclared = [NSArray arrayWithObject:typeString]; pboardType = typeString; break; } } if (!typesDeclared) { return NO; } Tcl_Eval(info->interp, "selection get"); char *copystring = Tcl_GetString(Tcl_GetObjResult(info->interp)); NSString *writestring = [NSString stringWithUTF8String:copystring]; [pboard declareTypes:typesDeclared owner:nil]; return [pboard setString:writestring forType:pboardType]; } /* * This is the method that actually calls the Tk service; it must be specified * in Info.plist. */ - (void)provideService:(NSPasteboard *)pboard userData:(NSString *)data error:(NSString **)error { NSString *pboardString = nil, *pboardType = nil; NSArray *types = [pboard types]; Tcl_Event *event; (void)data; (void)error; /* * Get a string from the private pasteboard and copy it to the general * pasteboard to make it available to other applications. */ for (NSString *typeString in types) { if ([typeString isEqualToString:@"NSStringPboardType"] || [typeString isEqualToString:@"NSPasteboardTypeString"]) { pboardString = [pboard stringForType:typeString]; pboardType = typeString; break; } } if (pboardString) { NSPasteboard *generalpasteboard = [NSPasteboard generalPasteboard]; [generalpasteboard declareTypes:[NSArray arrayWithObjects:pboardType, nil] owner:nil]; [generalpasteboard setString:pboardString forType:pboardType]; event = (Tcl_Event *)ckalloc(sizeof(Tcl_Event)); event->proc = ServicesEventProc; Tcl_QueueEvent((Tcl_Event *)event, TCL_QUEUE_TAIL); } } @end /* * Instantiate a TkService object and register it with the NSApplication. * This is called exactly one time from TkpInit. */ int TkMacOSXServices_Init( TCL_UNUSED(Tcl_Interp *)) { /* * Initialize an instance of TkService and register it with the NSApp. */ TkService *service = [[TkService alloc] init]; [NSApp setServicesProvider:service]; return TCL_OK; } /* * Local Variables: * mode: objc * c-basic-offset: 4 * fill-column: 79 * coding: utf-8 * End: */