diff options
author | Kevin Walzer <kw@codebykevin.com> | 2019-02-27 04:07:05 (GMT) |
---|---|---|
committer | Kevin Walzer <kw@codebykevin.com> | 2019-02-27 04:07:05 (GMT) |
commit | 930a9c0ad615486a65f23ed38729f06e1dfee051 (patch) | |
tree | 3aec75b96fdb678d5a825aa0f1ced7cf9c706a29 /macosx/tkMacOSXServices.c | |
parent | cfb164ce628c937458881b4ebe5a81362a709086 (diff) | |
parent | c4097257d9d12d9e735ee2e1ff368e982e97c770 (diff) | |
download | tk-930a9c0ad615486a65f23ed38729f06e1dfee051.zip tk-930a9c0ad615486a65f23ed38729f06e1dfee051.tar.gz tk-930a9c0ad615486a65f23ed38729f06e1dfee051.tar.bz2 |
Update mac_services branch, intend to submit a TIP
Diffstat (limited to 'macosx/tkMacOSXServices.c')
-rw-r--r-- | macosx/tkMacOSXServices.c | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/macosx/tkMacOSXServices.c b/macosx/tkMacOSXServices.c new file mode 100644 index 0000000..9d04d14 --- /dev/null +++ b/macosx/tkMacOSXServices.c @@ -0,0 +1,197 @@ +/* + * tkMacOSXServices.c -- + * + * This file allows the integration of Tk and the Cocoa NSServices API. + * + * Copyright (c) 2010-2018 Kevin Walzer/WordTech Communications LLC. + * Copyright (c) 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 <CoreFoundation/CoreFoundation.h> +#include <CoreServices/CoreServices.h> +#define Cursor FooFoo +#include <Carbon/Carbon.h> +#undef Cursor +#include <tcl.h> +#include <tk.h> +#include <tkInt.h> +#include <tkMacOSXInt.h> +#include <Cocoa/Cocoa.h> +#include <stdio.h> +#include <string.h> + +static Tcl_Interp *ServicesInterp; + + +/* These two assist with asynchronous Tcl proc calling. */ +typedef struct Services_Event { + Tcl_Event header; + char script[50000]; +} Services_Event; + +int ServicesEventProc(Tcl_Event *event, int flags) { + Tcl_GlobalEval(ServicesInterp, ((Services_Event *)event)->script); + return 1; +} + + +/* Class declarations for TkService class. */ +@interface TkService : NSView { + +} + ++ (void) initialize; +- (void)provideService:(NSPasteboard *)pboard userData:(NSString *)data error:(NSString **)error; +- (id)validRequestorForSendType:(NSString *)sendType returnType:(NSString *)returnType; +- (BOOL)writeSelectionToPasteboard:(NSPasteboard *)pboard types:(NSArray *)types; + +@end + +/* Class methods. */ +@implementation TkService + ++ (void) initialize { + + NSArray *sendTypes = [NSArray arrayWithObjects:NSStringPboardType, nil]; + [NSApp registerServicesMenuSendTypes:sendTypes returnTypes:nil]; + NSUpdateDynamicServices(); + return; +} + + +- (id)validRequestorForSendType:(NSString *)sendType returnType:(NSString *)returnType { + + if ([sendType isEqual:NSStringPboardType]) { + return self; + } + return [super validRequestorForSendType:sendType returnType:returnType]; +} + +/* Make sure the view accepts events. */ +- (BOOL)acceptsFirstResponder { + return YES; +} +- (BOOL)becomeFirstResponder { + return YES; +} + +//get selected text, copy to pasteboard +- (BOOL)writeSelectionToPasteboard:(NSPasteboard *)pboard types:(NSArray *)types { + NSArray *typesDeclared; + if ([types containsObject:NSStringPboardType] == NO) { + return NO; + } + + Tcl_Eval(ServicesInterp,"clipboard get"); + char *copystring; + copystring = Tcl_GetString(Tcl_GetObjResult(ServicesInterp)); + + NSString *writestring = [NSString stringWithUTF8String:copystring]; + typesDeclared = [NSArray arrayWithObject:NSStringPboardType]; + [pboard declareTypes:typesDeclared owner:nil]; + return [pboard setString:writestring forType:NSStringPboardType]; +} + + +/* This is the method that actually calls the Tk service; this is the method that must be defined in info.plist */ + +- (void)provideService:(NSPasteboard *)pboard userData:(NSString *)data error:(NSString **)error { + + NSString *pboardString; + NSArray *types = [pboard types]; + Services_Event *event; + + /* Get string from private pasteboard, write to general pasteboard to make available to Tcl service. */ + if ([types containsObject:NSStringPboardType] && + (pboardString = [pboard stringForType:NSStringPboardType])) { + + NSPasteboard *generalpasteboard = [NSPasteboard generalPasteboard]; + [generalpasteboard declareTypes:[NSArray arrayWithObjects:NSStringPboardType, nil] owner:nil]; + [generalpasteboard setString:pboardString forType:NSStringPboardType]; + event = (Services_Event *)ckalloc(sizeof(Services_Event)); + event->header.proc = ServicesEventProc; + strcpy(event->script, "::tk::mac::PerformService"); + Tcl_QueueEvent((Tcl_Event *)event, TCL_QUEUE_TAIL); + } else { + return; + } + return; +} + +@end + + +/* Register a specific widget to access the Services menu. */ +int TkMacOSXRegisterServiceWidgetObjCmd (ClientData cd, Tcl_Interp *ip, int objc, Tcl_Obj *CONST objv[]) { + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + /* Need proper number of args. */ + if(objc != 2) { + Tcl_WrongNumArgs(ip, 1, objv, "path?"); + return TCL_ERROR; + } + + /* Get the object that holds this Tk Window... */ + Rect bounds; + NSRect frame; + Tk_Window path; + path = Tk_NameToWindow(ip, Tcl_GetString(objv[1]), Tk_MainWindow(ip)); + if (path == NULL) { + return TCL_ERROR; + } + + Tk_MakeWindowExist(path); + Tk_MapWindow(path); + Drawable d = Tk_WindowId(path); + + /* Get NSView from Tk window and add subview. */ + TkService *serviceview = [[TkService alloc] init]; + NSView *view = TkMacOSXGetRootControl(d); + if ([serviceview superview] != view) { + [view addSubview:serviceview]; + } + + TkMacOSXWinBounds((TkWindow*)path, &bounds); + + /* Hack to make sure subview is set to take up entire geometry of window. */ + frame = NSMakeRect(bounds.left, bounds.top, 100000, 100000); + frame.origin.y = 0; + + if (!NSEqualRects(frame, [serviceview frame])) { + [serviceview setFrame:frame]; + } + + [serviceview release]; + [pool release]; + + return TCL_OK; + +} + + +//initalize the package in the tcl interpreter, create tcl commands +int Tk_MacOSXServices_Init (Tcl_Interp *interp) { + + /* Set up an autorelease pool. */ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + + /* Initialize instance of TclServices to provide service functionality. */ + TkService *service = [[TkService alloc] init]; + ServicesInterp = interp; + [NSApp setServicesProvider:service]; + + [pool release]; + + return TCL_OK; + +} + + + |