Tk-Components

Check-in [5da1731fb5]
Login

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

Overview
Comment:Updates to launcher module
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:5da1731fb52793f96a454db3346051066fd96e71
User & Date: kevin 2015-07-12 03:42:59
Context
2015-07-12
04:09
More updates to aem check-in: 19a8a45d31 user: kevin tags: trunk
03:42
Updates to launcher module check-in: 5da1731fb5 user: kevin tags: trunk
2015-07-10
02:52
Add aem package check-in: 38182a035f user: kevin tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Added aem/macosx/aem.c.







































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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
73
74
75
76
77
78
79
80
81
82
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
/*
 * aem.c --
 * Provides a basic mechanism for Tcl apps to respond to arbitrary Apple Events with Tcl commands.
 * Copyright (c) 2015 Kevin Walzer/WordTech Communications LLC.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */

#include <tcl.h>
#include <tk.h>
#undef panic
#include <CoreFoundation/CoreFoundation.h>
#include <CoreServices/CoreServices.h>
#include <Carbon/Carbon.h>
#include <ApplicationServices/ApplicationServices.h>
#define panic Tcl_Panic


/*Global values.*/
static Tcl_Interp *AS_Interp;
CFStringRef stringeventClass;
CFStringRef stringeventID;    
CFStringRef eventFunction;
CFMutableDictionaryRef aeDict;


/* Prototypes of functions called later. */
int InstallAEEventHandler(ClientData cd, Tcl_Interp *ip, int objc, Tcl_Obj *CONST objv[]);
OSErr TclAEHandler(const AppleEvent *theAppleEvent,
		   AppleEvent *reply, long refCon);

/*Install Apple Event handlers and map to Tcl commands.*/
int InstallAEEventHandler(ClientData cd, Tcl_Interp *ip, int objc, Tcl_Obj *CONST objv[]) {

  if(objc != 4) {
    Tcl_WrongNumArgs(ip, 1, objv, "eventClass eventID command");
    return TCL_ERROR;
  }

  OSErr err;
  OSType eventClass;
  OSType eventID;
  
  /* Convert chars to CFStringRefs. */
  stringeventClass = CFStringCreateWithCString(kCFAllocatorDefault, Tcl_GetString(objv[1]), kCFStringEncodingUTF8);
  stringeventID = CFStringCreateWithCString(kCFAllocatorDefault, Tcl_GetString(objv[2]), kCFStringEncodingUTF8);
  eventFunction = CFStringCreateWithCString(kCFAllocatorDefault, Tcl_GetString(objv[3]), kCFStringEncodingUTF8);
 
  /* Convert CFStringRefs to OSTypes, which are integers. */
  eventClass = UTGetOSTypeFromString(stringeventClass);
  eventID = UTGetOSTypeFromString(stringeventID);

  /* Map event ID's to Tcl commands in CFDictionary. */		       	
  CFDictionarySetValue(aeDict, stringeventID, eventFunction);
	
  /* Finally, install the Apple Event handlers.  */
  err = AEInstallEventHandler(eventClass, eventID, NewAEEventHandlerUPP(TclAEHandler), 0, false);
  if (err != noErr) {
    fprintf(stdout, "Unable to install custom Apple Event handlers.\n");
  } else {
    fprintf(stdout, "Installation successful.\n");
  }
  return TCL_OK;
}

/* AppleEvent handler for Tcl interpreter.*/
OSErr TclAEHandler(const AppleEvent *theAppleEvent,
		   AppleEvent *reply, long refCon) {


  OSErr err = noErr;
  AEEventID	eventID;
  AEDesc directParameter;
  Tcl_DString as_arg;

  /* Get event ID to look up in CFDictionary. */
  err = AEGetAttributePtr(theAppleEvent, keyEventIDAttr, typeType, NULL, &eventID, sizeof(eventID), NULL );

  /* Get direct parameter, convert to char. */
  err = AEGetKeyDesc(theAppleEvent, keyDirectObject, typeUTF8Text, &directParameter);
  long size = AEGetDescDataSize(&directParameter);
  //  char *paramstring[size];
  UInt8 paramstring[size];
  if (size == 0) {
    paramstring[0] = "";
  }
			   
  AEGetDescData(&directParameter, paramstring, size);
  AEDisposeDesc(&directParameter);

  /*Need to convert paramstring to something Tcl can handle gracefully. Direct conversion of AE params to char does not seem to work well, produces garbage.*/

  CFStringRef arg = CFStringCreateWithBytes(0, paramstring, sizeof(paramstring),
					    kCFStringEncodingUTF8, false);
  int len; 
  len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(arg), kCFStringEncodingUTF8);
  Tcl_DStringInit(&as_arg);
  Tcl_DStringSetLength(&as_arg, len);

  Tcl_DStringValue(&as_arg) = CFStringGetCStringPtr(arg,kCFStringEncodingUTF8);
   
  /*  Get command keyed to eventID from dict and pass to Tcl for execution. */
  CFTypeRef scriptName;
  stringeventID = UTCreateStringForOSType(eventID);
  scriptName = CFDictionaryGetValue(aeDict, stringeventID);
  CFStringRef cfcmd;
  if (scriptName == NULL) {
    fprintf(stdout, "Unable to look up Apple Event id\n");
    return NULL;
  }
  
  if (CFGetTypeID(scriptName) == CFStringGetTypeID()) {
    cfcmd = scriptName;
  } else {
    fprintf(stderr, "Unable to get datatype of Apple Event\n");
    return NULL;
  }
 
  char *applescript_tcl_cmd;
  
  /* Convert the string reference into a C string. */
  applescript_tcl_cmd = CFStringGetCStringPtr(cfcmd, kCFStringEncodingUTF8);
  
  /* Eval the Tcl command. */
  Tcl_VarEval(AS_Interp, applescript_tcl_cmd, " ", Tcl_DStringValue(&as_arg), NULL);
 
  char *output;
  output = Tcl_GetString(Tcl_GetObjResult(AS_Interp));
  Tcl_SetResult(AS_Interp, output, NULL);
 
 
  /*  Pass results back to AppleScript, clean up. */
  err= AEPutParamPtr(reply, keyDirectObject, typeUTF8Text, output, strlen(output));
  if (err !=noErr) {
    fprintf(stderr, "Unable to execute %s\n", applescript_tcl_cmd);
  }
  CFRelease(scriptName);
  CFRelease(arg);
  Tcl_DStringFree(&as_arg);
  return err;
}

  
/*Initalize the package in the tcl interpreter, create Tcl commands. */
int Aem_Init (Tcl_Interp *interp) {

 
  if (Tcl_InitStubs(interp, "8.5", 0) == NULL) {
    return TCL_ERROR;  
  }
  if (Tk_InitStubs(interp, "8.5", 0) == NULL) {
    return TCL_ERROR;
  }

  /* Initialize the interpreter for Apple Event responses and the CFDictionary that will hold the information about the Apple Events. */
					 
  AS_Interp = interp;
  
  aeDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);


  Tcl_CreateObjCommand(interp, "::aem::installeventhandler", InstallAEEventHandler,(ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);

  if (Tcl_PkgProvide(interp, "aem", "1.0") != TCL_OK) {
    return TCL_ERROR;
  }
      
  return TCL_OK;
	
}

int Aem_SafeInit(Tcl_Interp *interp) {
  return Aem_Init(interp);
}



Added launcher/launcher.html.















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<HTML>
<BODY>
<PRE>
<!-- Manpage converted by man2html 3.0.1 -->
package require launcher
.PP
launcher::launchurl url?
.PP
launcher::launchfile file?
.PP
launcher::getapppath
.PP
launcher::getdefaultapp url
.PP
launcher::setdefaultapp url path-to-app
.RE
.PP

.SH DESCRIPTION

This module allows you to launch a URL or a file on the Mac using the system's default application for that URL or file type. It provides similar functionality to the "/usr/bin/open" command-line tool, but works without shelling out to an external program. The package also allows you to query the system for a default app for a particular URL type, i.e. http://, and also to set the default app for a particular URL. Finally, the module provides a convenience function to get the current app path.
.SH EXAMPLES

launcher::launchurl http://www.apple.com
launcher::launch file ~/Desktop/test.txt
launcher::getapppath
launcher::getdefaultapp http
launcher::setdefaultapp x-man-page [launcher::getapppath]
.RE
.PP

</PRE>
<HR>
<ADDRESS>
Man(1) output converted with
<a href="http://www.oac.uci.edu/indiv/ehood/man2html.html">man2html</a>
</ADDRESS>
</BODY>
</HTML>

Added launcher/launcher.n.





































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
.\" Text automatically generated by txt2man
.TH untitled  "11 July 2015" "" ""
.SH NAME
\fBlauncher
\fB
.SH SYNPOSIS

package require launcher
.PP
launcher::launchurl url?
.PP
launcher::launchfile file?
.PP
launcher::getapppath
.PP
launcher::getdefaultapp url
.PP
launcher::setdefaultapp url path-to-app
.RE
.PP

.SH DESCRIPTION

This module allows you to launch a URL or a file on the Mac using the system's default application for that URL or file type. It provides similar functionality to the "/usr/bin/open" command-line tool, but works without shelling out to an external program. The package also allows you to query the system for a default app for a particular URL type, i.e. http://, and also to set the default app for a particular URL. Finally, the module provides a convenience function to get the current app path.
.SH EXAMPLES

launcher::launchurl http://www.apple.com
launcher::launch file ~/Desktop/test.txt
launcher::getapppath
launcher::getdefaultapp http
launcher::setdefaultapp x-man-page [launcher::getapppath]
.RE
.PP

Added launcher/launcher.txt.































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
NAME
launcher

SYNPOSIS

package require launcher

launcher::launchurl url?

launcher::launchfile file?

launcher::getapppath

launcher::getdefaultapp url

launcher::setdefaultapp url path-to-app


DESCRIPTION

This module allows you to launch a URL or a file on the Mac using the system's default application for that URL or file type. It provides similar functionality to the "/usr/bin/open" command-line tool, but works without shelling out to an external program. The package also allows you to query the system for a default app for a particular URL type, i.e. http://, and also to set the default app for a particular URL. Finally, the module provides a convenience function to get the current app path.

EXAMPLES

 launcher::launchurl http://www.apple.com
 launcher::launch file ~/Desktop/test.txt
 launcher::getapppath
 launcher::getdefaultapp http
 launcher::setdefaultapp x-man-page [launcher::getapppath]