summaryrefslogtreecommitdiffstats
path: root/macosx/tkMacOSXServices.c
diff options
context:
space:
mode:
authorKevin Walzer <kw@codebykevin.com>2019-02-27 04:07:05 (GMT)
committerKevin Walzer <kw@codebykevin.com>2019-02-27 04:07:05 (GMT)
commit930a9c0ad615486a65f23ed38729f06e1dfee051 (patch)
tree3aec75b96fdb678d5a825aa0f1ced7cf9c706a29 /macosx/tkMacOSXServices.c
parentcfb164ce628c937458881b4ebe5a81362a709086 (diff)
parentc4097257d9d12d9e735ee2e1ff368e982e97c770 (diff)
downloadtk-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.c197
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;
+
+}
+
+
+