Tk Source Code

Check-in [a7e34ff9]
Login
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2019 Conference, Houston/TX, US, Nov 4-8
Send your abstracts to [email protected]
or submit via the online form by Sep 9.

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Code and data type cleanup, thanks to Marc Culler for patch
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | mac_services
Files: files | file ages | folders
SHA3-256: a7e34ff9cec93f6354d6de80aa0c9d674a2c2d3ffb12fbf4920a605801239a9a
User & Date: kevin_walzer 2019-05-17 03:13:34
Context
2019-05-18
13:05
Finally got timing of initializing NSServices object correct; code cleanup; merge in 8.6 to pick up changes in Tk initialization code check-in: f126b00e user: kevin_walzer tags: mac_services
2019-05-17
03:13
Code and data type cleanup, thanks to Marc Culler for patch check-in: a7e34ff9 user: kevin_walzer tags: mac_services
2019-05-12
02:03
Restore deprecated call to NSPasteboardTypeString in writeSelectiontoPasteboard because it breaks sending data to the services menu. Data type must be identical in this call and in the NSSendTypes key in info.plist; we cannot do a clever mapping here of the old type to a new one because the info.plist does not have this kind of conditional reading on different versions of macOS. We will have to live with the deprecated call until it is obsolete/removed altogether by Apple. check-in: 42577ce4 user: kevin_walzer tags: mac_services
Changes
Hide Diffs Unified Diffs Show Whitespace Changes Patch

Changes to macosx/Wish-Info.plist.in.

102
103
104
105
106
107
108

109
110
111
112
113
114
115
            <key>NSMessage</key>
            <string>provideService</string>
            <key>NSPortName</key>
            <string>Wish</string>

            <key>NSSendTypes</key>
            <array>

                <string>NSPasteboardTypeString</string>
            </array>
        </dict>
    </array>

</dict>
</plist>






>







102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
            <key>NSMessage</key>
            <string>provideService</string>
            <key>NSPortName</key>
            <string>Wish</string>

            <key>NSSendTypes</key>
            <array>
                <string>NSStringPboardType</string>
                <string>NSPasteboardTypeString</string>
            </array>
        </dict>
    </array>

</dict>
</plist>

Changes to macosx/tkMacOSXInit.c.

112
113
114
115
116
117
118

119
120
121
122
123
124
125
...
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
...
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
     */
    TkMacOSXUseAntialiasedText(_eventInterp, -1);
    TkMacOSXInitCGDrawing(_eventInterp, TRUE, 0);
}

-(void)applicationDidFinishLaunching:(NSNotification *)notification
{

    /*
     * It is not safe to force activation of the NSApp until this method is
     * called. Activating too early can cause the menu bar to be unresponsive.
     */

    [NSApp activateIgnoringOtherApps: YES];

................................................................................
     * ticket 56a1823c73.
     */

    [NSApp _lockAutoreleasePool];
    while (Tcl_DoOneEvent(TCL_WINDOW_EVENTS| TCL_DONT_WAIT)) {}
    [NSApp _unlockAutoreleasePool];

    Tk_MacOSXServices_Init(_eventInterp);
}

- (void) _setup: (Tcl_Interp *) interp
{
    /*
     * Remember our interpreter.
     */
................................................................................
  /* Convert the URL reference into a string reference. */
  CFStringRef appPath = CFURLCopyFileSystemPath(mainBundleURL, kCFURLPOSIXPathStyle);
 
  /* Get the system encoding method. */
  CFStringEncoding encodingMethod = CFStringGetSystemEncoding();
 
  /* Convert the string reference into a C string. */
  char *path = CFStringGetCStringPtr(appPath, encodingMethod);

  Tcl_SetResult(ip, path, NULL);

  CFRelease(mainBundleURL);
  CFRelease(appPath);
  return TCL_OK;







>







 







|







 







|







112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
...
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
...
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
     */
    TkMacOSXUseAntialiasedText(_eventInterp, -1);
    TkMacOSXInitCGDrawing(_eventInterp, TRUE, 0);
}

-(void)applicationDidFinishLaunching:(NSNotification *)notification
{

    /*
     * It is not safe to force activation of the NSApp until this method is
     * called. Activating too early can cause the menu bar to be unresponsive.
     */

    [NSApp activateIgnoringOtherApps: YES];

................................................................................
     * ticket 56a1823c73.
     */

    [NSApp _lockAutoreleasePool];
    while (Tcl_DoOneEvent(TCL_WINDOW_EVENTS| TCL_DONT_WAIT)) {}
    [NSApp _unlockAutoreleasePool];
    
    TkMacOSXServices_Init(_eventInterp);
}

- (void) _setup: (Tcl_Interp *) interp
{
    /*
     * Remember our interpreter.
     */
................................................................................
  /* Convert the URL reference into a string reference. */
  CFStringRef appPath = CFURLCopyFileSystemPath(mainBundleURL, kCFURLPOSIXPathStyle);
 
  /* Get the system encoding method. */
  CFStringEncoding encodingMethod = CFStringGetSystemEncoding();
 
  /* Convert the string reference into a C string. */
  char *path = (char *) CFStringGetCStringPtr(appPath, encodingMethod);

  Tcl_SetResult(ip, path, NULL);

  CFRelease(mainBundleURL);
  CFRelease(appPath);
  return TCL_OK;

Changes to macosx/tkMacOSXPrivate.h.

229
230
231
232
233
234
235



236
237
238
239
240
241
242
...
333
334
335
336
337
338
339

340
341
342
343
344
345
346
			    NSWindow *macWindow);
MODULE_SCOPE int	TkMacOSXStandardAboutPanelObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TkMacOSXIconBitmapObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);



MODULE_SCOPE int	TkMacOSXRegisterServiceWidgetObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);

#pragma mark Private Objective-C Classes

#define VISIBILITY_HIDDEN __attribute__((visibility("hidden")))
................................................................................
- (void)handleURLEvent:                (NSAppleEventDescriptor*)event
	           withReplyEvent:     (NSAppleEventDescriptor*)replyEvent;
@end

VISIBILITY_HIDDEN
@interface TKContentView : NSView <NSTextInput>
{

    NSString *privateWorkingText;
    #ifdef __i386__
    /* The Objective C runtime used on i386 requires this. */
    Bool _needsRedisplay;
#endif
}
@property Bool needsRedisplay;






>
>
>







 







>







229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
...
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
			    NSWindow *macWindow);
MODULE_SCOPE int	TkMacOSXStandardAboutPanelObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TkMacOSXIconBitmapObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE void       TkMacOSXDrawSolidBorder(Tk_Window tkwin, GC gc,
			    int inset, int thickness);
MODULE_SCOPE int 	TkMacOSXServices_Init(Tcl_Interp *interp);
MODULE_SCOPE int	TkMacOSXRegisterServiceWidgetObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);

#pragma mark Private Objective-C Classes

#define VISIBILITY_HIDDEN __attribute__((visibility("hidden")))
................................................................................
- (void)handleURLEvent:                (NSAppleEventDescriptor*)event
	           withReplyEvent:     (NSAppleEventDescriptor*)replyEvent;
@end

VISIBILITY_HIDDEN
@interface TKContentView : NSView <NSTextInput>
{
@private
    NSString *privateWorkingText;
#ifdef __i386__
    /* The Objective C runtime used on i386 requires this. */
    Bool _needsRedisplay;
#endif
}
@property Bool needsRedisplay;

Changes to macosx/tkMacOSXServices.c.

46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

65
66
67
68
69
70
71
..
83
84
85
86
87
88
89
90
91
92





93
94



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124


125


126


127
128
129

130
131
132
133
134
135
136
137
138
139
140
141
142
143
...
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
/*
 * Class methods.
 */

@implementation TkService

+ (void) initialize {
    NSArray *sendTypes = [NSArray arrayWithObjects:NSPasteboardTypeString, 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.
................................................................................
/*
 * 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,"selection 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:NSPasteboardTypeString];
}


/*
 * 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];
    Tcl_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: NSPasteboardTypeString];
	event = ckalloc(sizeof(Tcl_Event));
	event->proc = ServicesEventProc;
	Tcl_QueueEvent((Tcl_Event *)event, TCL_QUEUE_TAIL);
    }
}

@end


/*
 * Register a specific widget to access the Services menu.
 */

................................................................................
    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];






|
|
|








|
>







 







|
|
|
>
>
>
>
>
|
|
>
>
>





<

|












|








|
>
>
|
>
>
|
>
>

|
<
>
|





<







 







|







46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
..
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108

109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142

143
144
145
146
147
148
149

150
151
152
153
154
155
156
...
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
/*
 * Class methods.
 */

@implementation TkService

+ (void) initialize {
    NSArray *sendTypes = [NSArray arrayWithObjects:@"NSStringPboardType",
				  @"NSPasteboardTypeString", nil];
    [NSApp registerServicesMenuSendTypes:sendTypes returnTypes:sendTypes];
    NSUpdateDynamicServices();
    return;
}


- (id)validRequestorForSendType:(NSString *)sendType
		     returnType:(NSString *)returnType
{
    if ([sendType isEqualToString:@"NSStringPboardType"] ||
	[sendType isEqualToString:@"NSPasteboardTypeString"]) {
	return self;
    }
    return [super validRequestorForSendType:sendType returnType:returnType];
}

/*
 * Make sure the view accepts events.
................................................................................
/*
 * Get selected text, copy to pasteboard.
 */

- (BOOL)writeSelectionToPasteboard:(NSPasteboard *)pboard
			     types:(NSArray *)types
{
    NSArray *typesDeclared = nil;
    NSString *pboardType = nil;
    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(ServicesInterp,"selection get");
    char *copystring;
    copystring = Tcl_GetString(Tcl_GetObjResult(ServicesInterp));

    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; this is the method
 * that must be defined in info.plist.
 */

- (void)provideService:(NSPasteboard *)pboard
	      userData:(NSString *)data
		 error:(NSString **)error
{
    NSString *pboardString, *pboardType;
    NSArray *types = [pboard types];
    Tcl_Event *event;

    /*
     * Get string from private pasteboard, write to general pasteboard to make
     * available to Tcl service.
     */

    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 = ckalloc(sizeof(Tcl_Event));
	event->proc = ServicesEventProc;
	Tcl_QueueEvent((Tcl_Event *)event, TCL_QUEUE_TAIL);
    }
}

@end


/*
 * Register a specific widget to access the Services menu.
 */

................................................................................
    return TCL_OK;
}

/*
 * Initalize the package in the tcl interpreter, create tcl commands.
 */

int TkMacOSXServices_Init(
    Tcl_Interp *interp)
{
    /*
     * Set up an autorelease pool.
     */

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];