blob: e84766fed20c3ec0dba5d9ae41b5bba396363805 [file] [log] [blame]
Jack Jansen42218ce1997-01-31 16:15:11 +00001/***********************************************************
2Copyright 1991-1997 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
4
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI or Corporation for National Research Initiatives or
13CNRI not be used in advertising or publicity pertaining to
14distribution of the software without specific, written prior
15permission.
16
17While CWI is the initial source for this software, a modified version
18is made available by the Corporation for National Research Initiatives
19(CNRI) at the Internet address ftp://ftp.python.org.
20
21STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28PERFORMANCE OF THIS SOFTWARE.
29
30******************************************************************/
31
Jack Jansen12fce3e1995-08-14 12:31:44 +000032#include "Python.h"
33#include "osdefs.h"
Jack Jansen3f7d2b41996-09-06 22:21:07 +000034#include "macglue.h"
Jack Jansen12fce3e1995-08-14 12:31:44 +000035#include "pythonresources.h"
36
37
38/* Return the initial python search path. This is called once from
39** initsys() to initialize sys.path.
40**
41** If USE_BUILTIN_PATH is defined the path defined here is used
42** (after prepending the python home dir to each item).
43** If it is not defined the path is gotten from a resource in the
44** Preferences file.
45**
46** XXXX This code needs cleaning up. The routines here have moved
47** around quite a bit, and they're pretty messy for that reason.
48*/
49
50#include <Files.h>
51#include <Aliases.h>
52#include <Folders.h>
53#include <Resources.h>
54#include <TextUtils.h>
Jack Jansenb39be211995-09-01 11:48:10 +000055#include <Dialogs.h>
Jack Jansen12fce3e1995-08-14 12:31:44 +000056
Jack Jansen3f7d2b41996-09-06 22:21:07 +000057#ifdef USE_GUSI
58#include <GUSI.h>
59#endif
60
Jack Jansen12fce3e1995-08-14 12:31:44 +000061#define PYTHONPATH "\
62:\n\
63:Lib\n\
64:Lib:stdwin\n\
65:Lib:test\n\
66:Lib:mac"
67
Jack Jansenac82b6a1998-07-13 13:38:29 +000068static int
Jack Jansen83c74df1996-10-22 15:25:42 +000069getpreffilefss(FSSpec *fssp)
70{
71 static int diditbefore=0;
Jack Jansenac82b6a1998-07-13 13:38:29 +000072 static int rv = 1;
Jack Jansen83c74df1996-10-22 15:25:42 +000073 static FSSpec fss;
Jack Jansenabdf93c1998-07-31 09:33:28 +000074 short prefdirRefNum;
75 long prefdirDirID;
76 Handle namehandle;
77
78 if ( !diditbefore ) {
79 if ( FindFolder(kOnSystemDisk, 'pref', kDontCreateFolder, &prefdirRefNum,
80 &prefdirDirID) != noErr ) {
81 /* Something wrong with preferences folder */
82 (void)StopAlert(NOPREFDIR_ID, NULL);
83 exit(1);
84 }
85
86 if ( (namehandle=GetNamedResource('STR ', PREFFILENAME_NAME)) == NULL ) {
87 (void)StopAlert(NOPREFNAME_ID, NULL);
88 exit(1);
89 }
90
91 HLock(namehandle);
92 if ( **namehandle == '\0' ) {
93 /* Empty string means don't use preferences file */
94 rv = 0;
95 } else {
96 /* There is a filename, construct the fsspec */
Jack Jansenac82b6a1998-07-13 13:38:29 +000097 (void)FSMakeFSSpec(prefdirRefNum, prefdirDirID, (unsigned char *)*namehandle, &fss);
98 }
Jack Jansen83c74df1996-10-22 15:25:42 +000099 HUnlock(namehandle);
100 ReleaseResource(namehandle);
101 diditbefore = 1;
102 }
103 *fssp = fss;
Jack Jansenac82b6a1998-07-13 13:38:29 +0000104 return rv;
Jack Jansen83c74df1996-10-22 15:25:42 +0000105}
Jack Jansen12fce3e1995-08-14 12:31:44 +0000106
107char *
Jack Jansena547dca1996-07-10 15:48:25 +0000108Py_GetPath()
Jack Jansen12fce3e1995-08-14 12:31:44 +0000109{
110 /* Modified by Jack to do something a bit more sensible:
111 ** - Prepend the python home-directory (which is obtained from a Preferences
112 ** resource)
113 ** - Add :
114 */
115 static char *pythonpath;
Jack Jansen12fce3e1995-08-14 12:31:44 +0000116 char *p, *endp;
117 int newlen;
Jack Jansen83c74df1996-10-22 15:25:42 +0000118 char *curwd;
Jack Jansen12fce3e1995-08-14 12:31:44 +0000119#ifndef USE_BUILTIN_PATH
Jack Jansen01fbc681996-02-28 15:42:47 +0000120 staticforward char *PyMac_GetPythonPath();
Jack Jansen12fce3e1995-08-14 12:31:44 +0000121#endif
122
123 if ( pythonpath ) return pythonpath;
Jack Jansen12fce3e1995-08-14 12:31:44 +0000124#ifndef USE_BUILTIN_PATH
Jack Jansen83c74df1996-10-22 15:25:42 +0000125 if ( pythonpath = PyMac_GetPythonPath() )
Jack Jansen12fce3e1995-08-14 12:31:44 +0000126 return pythonpath;
127 printf("Warning: No pythonpath resource found, using builtin default\n");
128#endif
Jack Jansen83c74df1996-10-22 15:25:42 +0000129 curwd = PyMac_GetPythonDir();
Jack Jansen12fce3e1995-08-14 12:31:44 +0000130 p = PYTHONPATH;
131 endp = p;
132 pythonpath = malloc(2);
133 if ( pythonpath == NULL ) return PYTHONPATH;
134 strcpy(pythonpath, ":");
135 while (*endp) {
136 endp = strchr(p, '\n');
137 if ( endp == NULL )
138 endp = p + strlen(p);
139 newlen = strlen(pythonpath) + 1 + strlen(curwd) + (endp-p);
140 pythonpath = realloc(pythonpath, newlen+1);
141 if ( pythonpath == NULL ) return PYTHONPATH;
142 strcat(pythonpath, "\n");
143 if ( *p == ':' ) {
144 p++;
145 strcat(pythonpath, curwd);
146 strncat(pythonpath, p, (endp-p));
147 newlen--; /* Ok, ok, we've allocated one byte too much */
148 } else {
149 /* We've allocated too much in this case */
150 newlen -= strlen(curwd);
151 pythonpath = realloc(pythonpath, newlen+1);
152 if ( pythonpath == NULL ) return PYTHONPATH;
153 strncat(pythonpath, p, (endp-p));
154 }
155 pythonpath[newlen] = '\0';
156 p = endp + 1;
157 }
158 return pythonpath;
159}
160
Jack Jansen83c74df1996-10-22 15:25:42 +0000161
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000162/*
163** Open/create the Python Preferences file, return the handle
164*/
Jack Jansen01fbc681996-02-28 15:42:47 +0000165static short
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000166PyMac_OpenPrefFile()
167{
Jack Jansenabdf93c1998-07-31 09:33:28 +0000168 AliasHandle handle;
169 FSSpec dirspec;
170 short prefrh;
171 OSErr err;
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000172
Jack Jansenac82b6a1998-07-13 13:38:29 +0000173 if ( !getpreffilefss(&dirspec))
174 return -1;
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000175 prefrh = FSpOpenResFile(&dirspec, fsRdWrShPerm);
176 if ( prefrh < 0 ) {
Jack Jansen83c74df1996-10-22 15:25:42 +0000177#if 0
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000178 action = CautionAlert(NOPREFFILE_ID, NULL);
179 if ( action == NOPREFFILE_NO )
180 exit(1);
Jack Jansen83c74df1996-10-22 15:25:42 +0000181#endif
Jack Jansen532e3c21996-02-21 15:36:26 +0000182 FSpCreateResFile(&dirspec, 'Pyth', 'pref', 0);
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000183 prefrh = FSpOpenResFile(&dirspec, fsRdWrShPerm);
184 if ( prefrh == -1 ) {
185 /* This "cannot happen":-) */
Jack Jansenb39be211995-09-01 11:48:10 +0000186 printf("Cannot create preferences file, error %d\n", ResError());
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000187 exit(1);
188 }
Jack Jansen26ee1261996-11-09 18:45:18 +0000189 if ( (err=PyMac_init_process_location()) != 0 ) {
190 printf("Cannot get application location, error %d\n", err);
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000191 exit(1);
192 }
Jack Jansen26ee1261996-11-09 18:45:18 +0000193 dirspec = PyMac_ApplicationFSSpec;
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000194 dirspec.name[0] = 0;
Jack Jansenb39be211995-09-01 11:48:10 +0000195 if ((err=NewAlias(NULL, &dirspec, &handle)) != 0 ) {
196 printf("Cannot make alias to application directory, error %d\n", err);
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000197 exit(1);
198 }
Jack Jansenabdf93c1998-07-31 09:33:28 +0000199 AddResource((Handle)handle, 'alis', PYTHONHOME_ID, "\p");
200 UpdateResFile(prefrh);
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000201
202 } else {
203 UseResFile(prefrh);
204 }
205 return prefrh;
206}
Jack Jansen12fce3e1995-08-14 12:31:44 +0000207
208/*
209** Return the name of the Python directory
210*/
Jack Jansen5b3c9711997-09-08 13:22:49 +0000211char *
Jack Jansen12fce3e1995-08-14 12:31:44 +0000212PyMac_GetPythonDir()
213{
Jack Jansen83c74df1996-10-22 15:25:42 +0000214 static int diditbefore = 0;
Jack Jansenabdf93c1998-07-31 09:33:28 +0000215 static char name[256] = {':', '\0'};
216 AliasHandle handle;
217 FSSpec dirspec;
218 Boolean modified = 0;
219 short oldrh, prefrh = -1, homerh;
220
221 if ( diditbefore )
222 return name;
223
224 oldrh = CurResFile();
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000225
Jack Jansenabdf93c1998-07-31 09:33:28 +0000226 /* First look for an override in the application file */
227 UseResFile(PyMac_AppRefNum);
228 handle = (AliasHandle)Get1Resource('alis', PYTHONHOMEOVERRIDE_ID);
229 UseResFile(oldrh);
230 if ( handle != NULL ) {
231 homerh = PyMac_AppRefNum;
232 } else {
233 /* Try to open preferences file in the preferences folder. */
234 prefrh = PyMac_OpenPrefFile();
235 handle = (AliasHandle)Get1Resource('alis', PYTHONHOME_ID);
236 if ( handle == NULL ) {
237 /* (void)StopAlert(BADPREFFILE_ID, NULL); */
238 diditbefore=1;
239 return ":";
240 }
241 homerh = prefrh;
242 }
243 /* It exists. Resolve it (possibly updating it) */
244 if ( ResolveAlias(NULL, handle, &dirspec, &modified) != noErr ) {
245 (void)StopAlert(BADPREFFILE_ID, NULL);
246 diditbefore=1;
247 return ":";
248 }
249 if ( modified ) {
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000250 ChangedResource((Handle)handle);
Jack Jansenabdf93c1998-07-31 09:33:28 +0000251 UpdateResFile(homerh);
252 }
253 if ( prefrh != -1 ) CloseResFile(prefrh);
254 UseResFile(oldrh);
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000255
Jack Jansen26ee1261996-11-09 18:45:18 +0000256 if ( PyMac_GetFullPath(&dirspec, name) == 0 ) {
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000257 strcat(name, ":");
Jack Jansenabdf93c1998-07-31 09:33:28 +0000258 } else {
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000259 /* If all fails, we return the current directory */
260 printf("Python home dir exists but I cannot find the pathname!!\n");
Jack Jansen12fce3e1995-08-14 12:31:44 +0000261 name[0] = 0;
262 (void)getwd(name);
263 }
Jack Jansen83c74df1996-10-22 15:25:42 +0000264 diditbefore = 1;
Jack Jansen12fce3e1995-08-14 12:31:44 +0000265 return name;
266}
267
268#ifndef USE_BUILTIN_PATH
Jack Jansen5b3c9711997-09-08 13:22:49 +0000269char *
Jack Jansen83c74df1996-10-22 15:25:42 +0000270PyMac_GetPythonPath()
Jack Jansen12fce3e1995-08-14 12:31:44 +0000271{
Jack Jansenabdf93c1998-07-31 09:33:28 +0000272 short oldrh, prefrh = -1;
273 char *rv;
274 int i, newlen;
275 Str255 pathitem;
276 int resource_id;
277 OSErr err;
278 Handle h;
279
280 oldrh = CurResFile();
281 /*
282 ** This is a bit tricky. We check here whether the application file
283 ** contains an override. This is to forestall us finding another STR# resource
284 ** with "our" id and using that for path initialization
285 */
286 UseResFile(PyMac_AppRefNum);
287 SetResLoad(0);
288 if ( (h=Get1Resource('STR#', PYTHONPATHOVERRIDE_ID)) ) {
289 ReleaseResource(h);
290 resource_id = PYTHONPATHOVERRIDE_ID;
291 } else {
292 resource_id = PYTHONPATH_ID;
293 }
294 SetResLoad(1);
295 UseResFile(oldrh);
296
297 /* Open the preferences file only if there is no override */
298 if ( resource_id != PYTHONPATHOVERRIDE_ID )
299 prefrh = PyMac_OpenPrefFile();
300 /* At this point, we may or may not have the preferences file open, and it
301 ** may or may not contain a sys.path STR# resource. We don't care, if it doesn't
302 ** exist we use the one from the application (the default).
303 ** We put an initial '\n' in front of the path that we don't return to the caller
304 */
305 if( (rv = malloc(2)) == NULL )
306 goto out;
307 strcpy(rv, "\n");
Jack Jansenf12e7091996-09-05 15:19:24 +0000308
Jack Jansenabdf93c1998-07-31 09:33:28 +0000309 for(i=1; ; i++) {
310 GetIndString(pathitem, resource_id, i);
311 if( pathitem[0] == 0 )
312 break;
313 if ( pathitem[0] >= 9 && strncmp((char *)pathitem+1, "$(PYTHON)", 9) == 0 ) {
314 /* We have to put the directory in place */
315 char *dir = PyMac_GetPythonDir();
316
317 newlen = strlen(rv) + strlen(dir) + (pathitem[0]-9) + 2;
318 if( (rv=realloc(rv, newlen)) == NULL)
319 goto out;
320 strcat(rv, dir);
321 /* Skip a colon at the beginning of the item */
322 if ( pathitem[0] > 9 && pathitem[1+9] == ':' ) {
Jack Jansen12fce3e1995-08-14 12:31:44 +0000323 memcpy(rv+strlen(rv), pathitem+1+10, pathitem[0]-10);
324 newlen--;
325 } else {
326 memcpy(rv+strlen(rv), pathitem+1+9, pathitem[0]-9);
327 }
Jack Jansenabdf93c1998-07-31 09:33:28 +0000328 rv[newlen-2] = '\n';
329 rv[newlen-1] = 0;
330 } else if ( pathitem[0] >= 14 && strncmp((char *)pathitem+1, "$(APPLICATION)", 14) == 0 ) {
331 /* This is the application itself */
Jack Jansena486a551996-04-04 15:39:18 +0000332
Jack Jansenabdf93c1998-07-31 09:33:28 +0000333 if ( (err=PyMac_init_process_location()) != 0 ) {
Jack Jansen26ee1261996-11-09 18:45:18 +0000334 printf("Cannot get application location, error %d\n", err);
Jack Jansena486a551996-04-04 15:39:18 +0000335 exit(1);
336 }
Jack Jansen26ee1261996-11-09 18:45:18 +0000337
338 newlen = strlen(rv) + strlen(PyMac_ApplicationPath) + 2;
Jack Jansenabdf93c1998-07-31 09:33:28 +0000339 if( (rv=realloc(rv, newlen)) == NULL)
340 goto out;
341 strcpy(rv+strlen(rv), PyMac_ApplicationPath);
342 rv[newlen-2] = '\n';
343 rv[newlen-1] = 0;
Jack Jansena486a551996-04-04 15:39:18 +0000344
Jack Jansenabdf93c1998-07-31 09:33:28 +0000345 } else {
346 /* Use as-is */
347 newlen = strlen(rv) + (pathitem[0]) + 2;
348 if( (rv=realloc(rv, newlen)) == NULL)
349 goto out;
350 memcpy(rv+strlen(rv), pathitem+1, pathitem[0]);
351 rv[newlen-2] = '\n';
352 rv[newlen-1] = 0;
353 }
Jack Jansen12fce3e1995-08-14 12:31:44 +0000354 }
355 if( strlen(rv) == 1) {
356 free(rv);
357 rv = NULL;
358 }
359 if ( rv ) {
360 rv[strlen(rv)-1] = 0;
361 rv++;
362 }
363out:
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000364 if ( prefrh != -1) CloseResFile(prefrh);
365 UseResFile(oldrh);
Jack Jansen12fce3e1995-08-14 12:31:44 +0000366 return rv;
367}
368#endif /* !USE_BUILTIN_PATH */
369
Jack Jansena4b7e141996-02-21 16:46:57 +0000370void
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000371PyMac_PreferenceOptions(PyMac_PrefRecord *pr)
Jack Jansena4b7e141996-02-21 16:46:57 +0000372{
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000373 short oldrh, prefrh = -1;
Jack Jansena4b7e141996-02-21 16:46:57 +0000374 Handle handle;
375 int size;
Jack Jansen5b3c9711997-09-08 13:22:49 +0000376 PyMac_PrefRecord *p;
377 int action;
Jack Jansena4b7e141996-02-21 16:46:57 +0000378
379
Jack Jansenabdf93c1998-07-31 09:33:28 +0000380 oldrh = CurResFile();
381
382 /* Attempt to load overrides from application */
383 UseResFile(PyMac_AppRefNum);
384 handle = Get1Resource('Popt', PYTHONOPTIONSOVERRIDE_ID);
385 UseResFile(oldrh);
386
387 /* Otherwise get options from prefs file or any other open resource file */
388 if ( handle == NULL ) {
389 prefrh = PyMac_OpenPrefFile();
390 handle = GetResource('Popt', PYTHONOPTIONS_ID);
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000391 }
Jack Jansenabdf93c1998-07-31 09:33:28 +0000392 if ( handle == NULL ) {
393 return;
394 }
395 HLock(handle);
396 size = GetHandleSize(handle);
397 p = (PyMac_PrefRecord *)*handle;
398 if ( p->version == POPT_VERSION_CURRENT && size == sizeof(PyMac_PrefRecord) ) {
399 *pr = *p;
400 } else {
401 action = CautionAlert(BADPREFERENCES_ID, NULL);
402 if ( action == BADPREF_DELETE ) {
403 OSErr err;
404
405 RemoveResource(handle);
406 if ( (err=ResError()) ) printf("RemoveResource: %d\n", err);
407 if ( prefrh != -1 ) {
408 UpdateResFile(prefrh);
409 if ( (err=ResError()) ) printf("UpdateResFile: %d\n", err);
410 }
411 } else if ( action == BADPREF_QUIT )
412 exit(1);
413 }
414 HUnlock(handle);
Jack Jansena4b7e141996-02-21 16:46:57 +0000415
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000416 if ( prefrh != -1) CloseResFile(prefrh);
Jack Jansenabdf93c1998-07-31 09:33:28 +0000417 UseResFile(oldrh);
Jack Jansena4b7e141996-02-21 16:46:57 +0000418}
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000419
420#ifdef USE_GUSI
421void
422PyMac_SetGUSIOptions()
423{
424 Handle h;
425 short oldrh, prefrh = -1;
426
427 oldrh = CurResFile();
428
429 /* Try override from the application resource fork */
430 UseResFile(PyMac_AppRefNum);
431 h = Get1Resource('GU\267I', GUSIOPTIONSOVERRIDE_ID);
432 UseResFile(oldrh);
433
434 /* If that didn't work try nonoverride from anywhere */
435 if ( h == NULL ) {
436 prefrh = PyMac_OpenPrefFile();
437 h = GetResource('GU\267I', GUSIOPTIONS_ID);
438 }
439 if ( h ) GUSILoadConfiguration(h);
440 if ( prefrh != -1) CloseResFile(prefrh);
Jack Jansenabdf93c1998-07-31 09:33:28 +0000441 UseResFile(oldrh);
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000442}
443#endif /* USE_GUSI */