This commit was manufactured by cvs2svn to create tag 'r221'.
[python/dscho.git] / Mac / Modules / macfsmodule.c
blob9179c3628ad478ed848d07589e0d83293df1c9ad
1 /***********************************************************
2 Copyright 1991-1997 by Stichting Mathematisch Centrum, Amsterdam,
3 The Netherlands.
5 All Rights Reserved
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI not be used in advertising or publicity pertaining to
13 distribution of the software without specific, written prior permission.
15 STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18 FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 ******************************************************************/
25 #include "Python.h"
26 #include "macglue.h"
27 #include "pymactoolbox.h"
29 #ifdef WITHOUT_FRAMEWORKS
30 #include <Memory.h>
31 #include <Files.h>
32 #include <Folders.h>
33 #include <StandardFile.h>
34 #include <Aliases.h>
35 #include <LowMem.h>
36 #else
37 #include <Carbon/Carbon.h>
38 #endif
40 #include "getapplbycreator.h"
42 #ifndef TARGET_API_MAC_OSX
43 #include "pythonresources.h"
44 extern PyMac_PrefRecord PyMac_options;
45 #endif
47 #ifdef USE_TOOLBOX_OBJECT_GLUE
48 extern int _PyMac_GetFSSpec(PyObject *, FSSpec *);
49 extern PyObject *_PyMac_BuildFSSpec(FSSpec *);
50 extern int _PyMac_GetFSRef(PyObject *, FSRef *);
51 extern PyObject *_PyMac_BuildFSRef(FSRef *);
52 #define PyMac_GetFSSpec _PyMac_GetFSSpec
53 #define PyMac_BuildFSSpec _PyMac_BuildFSSpec
54 #define PyMac_GetFSRef _PyMac_GetFSRef
55 #define PyMac_BuildFSRef _PyMac_BuildFSRef
56 #endif
57 static PyObject *ErrorObject;
59 #ifdef TARGET_API_MAC_OSX
60 #define PATHNAMELEN 1024
61 #else
62 #define PATHNAMELEN 256
63 #endif
65 /* ----------------------------------------------------- */
66 /* Declarations for objects of type Alias */
68 typedef struct {
69 PyObject_HEAD
70 AliasHandle alias;
71 } mfsaobject;
73 staticforward PyTypeObject Mfsatype;
75 #define is_mfsaobject(v) ((v)->ob_type == &Mfsatype)
77 /* ---------------------------------------------------------------- */
78 /* Declarations for objects of type FSSpec */
80 typedef struct {
81 PyObject_HEAD
82 FSSpec fsspec;
83 } mfssobject;
85 staticforward PyTypeObject Mfsstype;
87 #define is_mfssobject(v) ((v)->ob_type == &Mfsstype)
89 /* ---------------------------------------------------------------- */
90 /* Declarations for objects of type FSRef */
92 typedef struct {
93 PyObject_HEAD
94 FSRef fsref;
95 } mfsrobject;
97 staticforward PyTypeObject Mfsrtype;
99 #define is_mfsrobject(v) ((v)->ob_type == &Mfsrtype)
102 /* ---------------------------------------------------------------- */
103 /* Declarations for objects of type FInfo */
105 typedef struct {
106 PyObject_HEAD
107 FInfo finfo;
108 } mfsiobject;
110 staticforward PyTypeObject Mfsitype;
112 #define is_mfsiobject(v) ((v)->ob_type == &Mfsitype)
115 staticforward mfssobject *newmfssobject(FSSpec *fss); /* Forward */
116 staticforward mfsrobject *newmfsrobject(FSRef *fsr); /* Forward */
118 /* ---------------------------------------------------------------- */
120 static PyObject *
121 mfsa_Resolve(mfsaobject *self, PyObject *args)
123 FSSpec from, *fromp, result;
124 Boolean changed;
125 OSErr err;
127 from.name[0] = 0;
128 if (!PyArg_ParseTuple(args, "|O&", PyMac_GetFSSpec, &from))
129 return NULL;
130 if (from.name[0] )
131 fromp = &from;
132 else
133 fromp = NULL;
134 err = ResolveAlias(fromp, self->alias, &result, &changed);
135 if ( err && err != fnfErr ) {
136 PyErr_Mac(ErrorObject, err);
137 return NULL;
139 return Py_BuildValue("(Oi)", newmfssobject(&result), (int)changed);
142 static PyObject *
143 mfsa_GetInfo(mfsaobject *self, PyObject *args)
145 Str63 value;
146 int i;
147 OSErr err;
149 if (!PyArg_ParseTuple(args, "i", &i))
150 return NULL;
151 err = GetAliasInfo(self->alias, (AliasInfoType)i, value);
152 if ( err ) {
153 PyErr_Mac(ErrorObject, err);
154 return 0;
156 return PyString_FromStringAndSize((char *)&value[1], value[0]);
159 static PyObject *
160 mfsa_Update(mfsaobject *self, PyObject *args)
162 FSSpec target, fromfile, *fromfilep;
163 OSErr err;
164 Boolean changed;
166 fromfile.name[0] = 0;
167 if (!PyArg_ParseTuple(args, "O&|O&", PyMac_GetFSSpec, &target,
168 PyMac_GetFSSpec, &fromfile))
169 return NULL;
170 if ( fromfile.name[0] )
171 fromfilep = &fromfile;
172 else
173 fromfilep = NULL;
174 err = UpdateAlias(fromfilep, &target, self->alias, &changed);
175 if ( err ) {
176 PyErr_Mac(ErrorObject, err);
177 return 0;
179 return Py_BuildValue("i", (int)changed);
182 static struct PyMethodDef mfsa_methods[] = {
183 {"Resolve", (PyCFunction)mfsa_Resolve, 1},
184 {"GetInfo", (PyCFunction)mfsa_GetInfo, 1},
185 {"Update", (PyCFunction)mfsa_Update, 1},
187 {NULL, NULL} /* sentinel */
190 /* ---------- */
192 static PyObject *
193 mfsa_getattr(mfsaobject *self, char *name)
195 if ( strcmp(name, "data") == 0 ) {
196 int size;
197 PyObject *rv;
199 size = GetHandleSize((Handle)self->alias);
200 HLock((Handle)self->alias);
201 rv = PyString_FromStringAndSize(*(Handle)self->alias, size);
202 HUnlock((Handle)self->alias);
203 return rv;
205 return Py_FindMethod(mfsa_methods, (PyObject *)self, name);
208 static mfsaobject *
209 newmfsaobject(AliasHandle alias)
211 mfsaobject *self;
213 self = PyObject_NEW(mfsaobject, &Mfsatype);
214 if (self == NULL)
215 return NULL;
216 self->alias = alias;
217 return self;
221 static void
222 mfsa_dealloc(mfsaobject *self)
224 #if 0
225 if ( self->alias ) {
226 should we do something here?
228 #endif
230 PyMem_DEL(self);
233 statichere PyTypeObject Mfsatype = {
234 PyObject_HEAD_INIT(&PyType_Type)
235 0, /*ob_size*/
236 "macfs.Alias", /*tp_name*/
237 sizeof(mfsaobject), /*tp_basicsize*/
238 0, /*tp_itemsize*/
239 /* methods */
240 (destructor)mfsa_dealloc, /*tp_dealloc*/
241 (printfunc)0, /*tp_print*/
242 (getattrfunc)mfsa_getattr, /*tp_getattr*/
243 (setattrfunc)0, /*tp_setattr*/
244 (cmpfunc)0, /*tp_compare*/
245 (reprfunc)0, /*tp_repr*/
246 0, /*tp_as_number*/
247 0, /*tp_as_sequence*/
248 0, /*tp_as_mapping*/
249 (hashfunc)0, /*tp_hash*/
252 /* End of code for Alias objects */
253 /* -------------------------------------------------------- */
255 /* ---------------------------------------------------------------- */
257 static struct PyMethodDef mfsi_methods[] = {
259 {NULL, NULL} /* sentinel */
262 /* ---------- */
264 static mfsiobject *
265 newmfsiobject(void)
267 mfsiobject *self;
269 self = PyObject_NEW(mfsiobject, &Mfsitype);
270 if (self == NULL)
271 return NULL;
272 memset((char *)&self->finfo, '\0', sizeof(self->finfo));
273 return self;
276 static void
277 mfsi_dealloc(mfsiobject *self)
279 PyMem_DEL(self);
282 static PyObject *
283 mfsi_getattr(mfsiobject *self, char *name)
285 if ( strcmp(name, "Type") == 0 )
286 return PyMac_BuildOSType(self->finfo.fdType);
287 else if ( strcmp(name, "Creator") == 0 )
288 return PyMac_BuildOSType(self->finfo.fdCreator);
289 else if ( strcmp(name, "Flags") == 0 )
290 return Py_BuildValue("i", (int)self->finfo.fdFlags);
291 else if ( strcmp(name, "Location") == 0 )
292 return PyMac_BuildPoint(self->finfo.fdLocation);
293 else if ( strcmp(name, "Fldr") == 0 )
294 return Py_BuildValue("i", (int)self->finfo.fdFldr);
295 else if ( strcmp(name, "__members__") == 0 )
296 return Py_BuildValue("[sssss]", "Type", "Creator", "Flags", "Location", "Fldr");
297 else
298 return Py_FindMethod(mfsi_methods, (PyObject *)self, name);
302 static int
303 mfsi_setattr(mfsiobject *self, char *name, PyObject *v)
305 int rv;
306 int i;
308 if ( v == NULL ) {
309 PyErr_SetString(PyExc_AttributeError, "Cannot delete attribute");
310 return -1;
312 if ( strcmp(name, "Type") == 0 )
313 rv = PyMac_GetOSType(v, &self->finfo.fdType);
314 else if ( strcmp(name, "Creator") == 0 )
315 rv = PyMac_GetOSType(v, &self->finfo.fdCreator);
316 else if ( strcmp(name, "Flags") == 0 ) {
317 rv = PyArg_Parse(v, "i", &i);
318 self->finfo.fdFlags = (short)i;
319 } else if ( strcmp(name, "Location") == 0 )
320 rv = PyMac_GetPoint(v, &self->finfo.fdLocation);
321 else if ( strcmp(name, "Fldr") == 0 ) {
322 rv = PyArg_Parse(v, "i", &i);
323 self->finfo.fdFldr = (short)i;
324 } else {
325 PyErr_SetString(PyExc_AttributeError, "No such attribute");
326 return -1;
328 if (rv)
329 return 0;
330 return -1;
334 static PyTypeObject Mfsitype = {
335 PyObject_HEAD_INIT(&PyType_Type)
336 0, /*ob_size*/
337 "macfs.FInfo", /*tp_name*/
338 sizeof(mfsiobject), /*tp_basicsize*/
339 0, /*tp_itemsize*/
340 /* methods */
341 (destructor)mfsi_dealloc, /*tp_dealloc*/
342 (printfunc)0, /*tp_print*/
343 (getattrfunc)mfsi_getattr, /*tp_getattr*/
344 (setattrfunc)mfsi_setattr, /*tp_setattr*/
345 (cmpfunc)0, /*tp_compare*/
346 (reprfunc)0, /*tp_repr*/
347 0, /*tp_as_number*/
348 0, /*tp_as_sequence*/
349 0, /*tp_as_mapping*/
350 (hashfunc)0, /*tp_hash*/
353 /* End of code for FInfo object objects */
354 /* -------------------------------------------------------- */
358 ** Helper routines for the FSRef and FSSpec creators in macglue.c
359 ** They return an FSSpec/FSRef if the Python object encapsulating
360 ** either is passed. They return a boolean success indicator.
361 ** Note that they do not set an exception on failure, they're only
362 ** helper routines.
364 static int
365 _mfs_GetFSSpecFromFSSpec(PyObject *self, FSSpec *fssp)
367 if ( is_mfssobject(self) ) {
368 *fssp = ((mfssobject *)self)->fsspec;
369 return 1;
371 return 0;
374 /* Return an FSSpec if this is an FSref */
375 static int
376 _mfs_GetFSSpecFromFSRef(PyObject *self, FSSpec *fssp)
378 #if !TARGET_API_MAC_OS8
379 static FSRef *fsrp;
381 if ( is_mfsrobject(self) ) {
382 fsrp = &((mfsrobject *)self)->fsref;
383 if ( FSGetCatalogInfo(&((mfsrobject *)self)->fsref, kFSCatInfoNone, NULL, NULL, fssp, NULL) == noErr )
384 return 1;
386 #endif
387 return 0;
390 /* Return an FSRef if this is an FSRef */
391 static int
392 _mfs_GetFSRefFromFSRef(PyObject *self, FSRef *fsrp)
394 #if !TARGET_API_MAC_OS8
395 if ( is_mfsrobject(self) ) {
396 *fsrp = ((mfsrobject *)self)->fsref;
397 return 1;
399 #endif
400 return 0;
403 /* Return an FSRef if this is an FSSpec */
404 static int
405 _mfs_GetFSRefFromFSSpec(PyObject *self, FSRef *fsrp)
407 #if !TARGET_API_MAC_OS8
408 if ( is_mfssobject(self) ) {
409 if ( FSpMakeFSRef(&((mfssobject *)self)->fsspec, fsrp) == noErr )
410 return 1;
412 #endif
413 return 0;
417 ** Two generally useful routines
419 static OSErr
420 PyMac_GetFileDates(FSSpec *fss, unsigned long *crdat, unsigned long *mddat,
421 unsigned long *bkdat)
423 CInfoPBRec pb;
424 OSErr error;
426 pb.dirInfo.ioNamePtr = fss->name;
427 pb.dirInfo.ioFDirIndex = 0;
428 pb.dirInfo.ioVRefNum = fss->vRefNum;
429 pb.dirInfo.ioDrDirID = fss->parID;
430 error = PBGetCatInfoSync(&pb);
431 if ( error ) return error;
432 *crdat = pb.hFileInfo.ioFlCrDat;
433 *mddat = pb.hFileInfo.ioFlMdDat;
434 *bkdat = pb.hFileInfo.ioFlBkDat;
435 return 0;
438 static OSErr
439 PyMac_SetFileDates(FSSpec *fss, unsigned long crdat, unsigned long mddat,
440 unsigned long bkdat)
442 CInfoPBRec pb;
443 OSErr error;
445 pb.dirInfo.ioNamePtr = fss->name;
446 pb.dirInfo.ioFDirIndex = 0;
447 pb.dirInfo.ioVRefNum = fss->vRefNum;
448 pb.dirInfo.ioDrDirID = fss->parID;
449 error = PBGetCatInfoSync(&pb);
450 if ( error ) return error;
451 pb.dirInfo.ioNamePtr = fss->name;
452 pb.dirInfo.ioFDirIndex = 0;
453 pb.dirInfo.ioVRefNum = fss->vRefNum;
454 pb.dirInfo.ioDrDirID = fss->parID;
455 pb.hFileInfo.ioFlCrDat = crdat;
456 pb.hFileInfo.ioFlMdDat = mddat;
457 pb.hFileInfo.ioFlBkDat = bkdat;
458 error = PBSetCatInfoSync(&pb);
459 return error;
462 static PyObject *
463 mfss_as_pathname(mfssobject *self, PyObject *args)
465 char strbuf[PATHNAMELEN];
466 OSErr err;
468 if (!PyArg_ParseTuple(args, ""))
469 return NULL;
470 err = PyMac_GetFullPathname(&self->fsspec, strbuf, PATHNAMELEN);
471 if ( err ) {
472 PyErr_Mac(ErrorObject, err);
473 return NULL;
475 return PyString_FromString(strbuf);
478 static PyObject *
479 mfss_as_tuple(mfssobject *self, PyObject *args)
481 if (!PyArg_ParseTuple(args, ""))
482 return NULL;
483 return Py_BuildValue("(iis#)", self->fsspec.vRefNum, self->fsspec.parID,
484 &self->fsspec.name[1], self->fsspec.name[0]);
487 static PyObject *
488 mfss_NewAlias(mfssobject *self, PyObject *args)
490 FSSpec src, *srcp;
491 OSErr err;
492 AliasHandle alias;
494 src.name[0] = 0;
495 if (!PyArg_ParseTuple(args, "|O&", PyMac_GetFSSpec, &src))
496 return NULL;
497 if ( src.name[0] )
498 srcp = &src;
499 else
500 srcp = NULL;
501 err = NewAlias(srcp, &self->fsspec, &alias);
502 if ( err ) {
503 PyErr_Mac(ErrorObject, err);
504 return NULL;
507 return (PyObject *)newmfsaobject(alias);
510 static PyObject *
511 mfss_NewAliasMinimal(mfssobject *self, PyObject *args)
513 OSErr err;
514 AliasHandle alias;
516 if (!PyArg_ParseTuple(args, ""))
517 return NULL;
518 err = NewAliasMinimal(&self->fsspec, &alias);
519 if ( err ) {
520 PyErr_Mac(ErrorObject, err);
521 return NULL;
523 return (PyObject *)newmfsaobject(alias);
526 static PyObject *
527 mfss_FSpMakeFSRef(mfssobject *self, PyObject *args)
529 #if TARGET_API_MAC_OS8
530 PyErr_SetString(PyExc_NotImplementedError, "FSRef objects not supported on this platform");
531 return 0;
532 #else
533 OSErr err;
534 FSRef fsref;
536 if (!PyArg_ParseTuple(args, ""))
537 return NULL;
538 err = FSpMakeFSRef(&self->fsspec, &fsref);
539 if ( err ) {
540 PyErr_Mac(ErrorObject, err);
541 return NULL;
543 return (PyObject *)newmfsrobject(&fsref);
544 #endif
547 /* XXXX These routines should be replaced by a wrapper to the *FInfo routines */
548 static PyObject *
549 mfss_GetCreatorType(mfssobject *self, PyObject *args)
551 OSErr err;
552 FInfo info;
554 if (!PyArg_ParseTuple(args, ""))
555 return NULL;
556 err = FSpGetFInfo(&self->fsspec, &info);
557 if ( err ) {
558 PyErr_Mac(ErrorObject, err);
559 return NULL;
561 return Py_BuildValue("(O&O&)",
562 PyMac_BuildOSType, info.fdCreator, PyMac_BuildOSType, info.fdType);
565 static PyObject *
566 mfss_SetCreatorType(mfssobject *self, PyObject *args)
568 OSErr err;
569 OSType creator, type;
570 FInfo info;
572 if (!PyArg_ParseTuple(args, "O&O&", PyMac_GetOSType, &creator, PyMac_GetOSType, &type))
573 return NULL;
574 err = FSpGetFInfo(&self->fsspec, &info);
575 if ( err ) {
576 PyErr_Mac(ErrorObject, err);
577 return NULL;
579 info.fdType = type;
580 info.fdCreator = creator;
581 err = FSpSetFInfo(&self->fsspec, &info);
582 if ( err ) {
583 PyErr_Mac(ErrorObject, err);
584 return NULL;
586 Py_INCREF(Py_None);
587 return Py_None;
590 static PyObject *
591 mfss_GetFInfo(mfssobject *self, PyObject *args)
593 OSErr err;
594 mfsiobject *fip;
597 if (!PyArg_ParseTuple(args, ""))
598 return NULL;
599 if ( (fip=newmfsiobject()) == NULL )
600 return NULL;
601 err = FSpGetFInfo(&self->fsspec, &fip->finfo);
602 if ( err ) {
603 PyErr_Mac(ErrorObject, err);
604 Py_DECREF(fip);
605 return NULL;
607 return (PyObject *)fip;
610 static PyObject *
611 mfss_SetFInfo(mfssobject *self, PyObject *args)
613 OSErr err;
614 mfsiobject *fip;
616 if (!PyArg_ParseTuple(args, "O!", &Mfsitype, &fip))
617 return NULL;
618 err = FSpSetFInfo(&self->fsspec, &fip->finfo);
619 if ( err ) {
620 PyErr_Mac(ErrorObject, err);
621 return NULL;
623 Py_INCREF(Py_None);
624 return Py_None;
627 static PyObject *
628 mfss_GetDates(mfssobject *self, PyObject *args)
630 OSErr err;
631 unsigned long crdat, mddat, bkdat;
633 if (!PyArg_ParseTuple(args, ""))
634 return NULL;
635 err = PyMac_GetFileDates(&self->fsspec, &crdat, &mddat, &bkdat);
636 if ( err ) {
637 PyErr_Mac(ErrorObject, err);
638 return NULL;
640 return Py_BuildValue("ddd", (double)crdat, (double)mddat, (double)bkdat);
643 static PyObject *
644 mfss_SetDates(mfssobject *self, PyObject *args)
646 OSErr err;
647 double crdat, mddat, bkdat;
649 if (!PyArg_ParseTuple(args, "ddd", &crdat, &mddat, &bkdat))
650 return NULL;
651 err = PyMac_SetFileDates(&self->fsspec, (unsigned long)crdat,
652 (unsigned long)mddat, (unsigned long)bkdat);
653 if ( err ) {
654 PyErr_Mac(ErrorObject, err);
655 return NULL;
657 Py_INCREF(Py_None);
658 return Py_None;
661 static struct PyMethodDef mfss_methods[] = {
662 {"as_pathname", (PyCFunction)mfss_as_pathname, 1},
663 {"as_tuple", (PyCFunction)mfss_as_tuple, 1},
664 {"as_fsref", (PyCFunction)mfss_FSpMakeFSRef, 1},
665 {"FSpMakeFSRef", (PyCFunction)mfss_FSpMakeFSRef, 1},
666 {"NewAlias", (PyCFunction)mfss_NewAlias, 1},
667 {"NewAliasMinimal", (PyCFunction)mfss_NewAliasMinimal, 1},
668 {"GetCreatorType", (PyCFunction)mfss_GetCreatorType, 1},
669 {"SetCreatorType", (PyCFunction)mfss_SetCreatorType, 1},
670 {"GetFInfo", (PyCFunction)mfss_GetFInfo, 1},
671 {"SetFInfo", (PyCFunction)mfss_SetFInfo, 1},
672 {"GetDates", (PyCFunction)mfss_GetDates, 1},
673 {"SetDates", (PyCFunction)mfss_SetDates, 1},
675 {NULL, NULL} /* sentinel */
678 /* ---------- */
680 static PyObject *
681 mfss_getattr(mfssobject *self, char *name)
683 if ( strcmp(name, "data") == 0)
684 return PyString_FromStringAndSize((char *)&self->fsspec, sizeof(FSSpec));
685 return Py_FindMethod(mfss_methods, (PyObject *)self, name);
688 mfssobject *
689 newmfssobject(FSSpec *fss)
691 mfssobject *self;
693 self = PyObject_NEW(mfssobject, &Mfsstype);
694 if (self == NULL)
695 return NULL;
696 self->fsspec = *fss;
697 return self;
700 static void
701 mfss_dealloc(mfssobject *self)
703 PyMem_DEL(self);
706 static PyObject *
707 mfss_repr(mfssobject *self)
709 char buf[512];
711 PyOS_snprintf(buf, sizeof(buf), "FSSpec((%d, %ld, '%.*s'))",
712 self->fsspec.vRefNum,
713 self->fsspec.parID,
714 self->fsspec.name[0], self->fsspec.name+1);
715 return PyString_FromString(buf);
718 static int
719 mfss_compare(mfssobject *v, mfssobject *w)
721 int minlen;
722 int res;
724 if ( v->fsspec.vRefNum < w->fsspec.vRefNum ) return -1;
725 if ( v->fsspec.vRefNum > w->fsspec.vRefNum ) return 1;
726 if ( v->fsspec.parID < w->fsspec.parID ) return -1;
727 if ( v->fsspec.parID > w->fsspec.parID ) return 1;
728 minlen = v->fsspec.name[0];
729 if ( w->fsspec.name[0] < minlen ) minlen = w->fsspec.name[0];
730 res = strncmp((char *)v->fsspec.name+1, (char *)w->fsspec.name+1, minlen);
731 if ( res ) return res;
732 if ( v->fsspec.name[0] < w->fsspec.name[0] ) return -1;
733 if ( v->fsspec.name[0] > w->fsspec.name[0] ) return 1;
734 return res;
737 statichere PyTypeObject Mfsstype = {
738 PyObject_HEAD_INIT(&PyType_Type)
739 0, /*ob_size*/
740 "macfs.FSSpec", /*tp_name*/
741 sizeof(mfssobject), /*tp_basicsize*/
742 0, /*tp_itemsize*/
743 /* methods */
744 (destructor)mfss_dealloc, /*tp_dealloc*/
745 (printfunc)0, /*tp_print*/
746 (getattrfunc)mfss_getattr, /*tp_getattr*/
747 (setattrfunc)0, /*tp_setattr*/
748 (cmpfunc)mfss_compare, /*tp_compare*/
749 (reprfunc)mfss_repr, /*tp_repr*/
750 0, /*tp_as_number*/
751 0, /*tp_as_sequence*/
752 0, /*tp_as_mapping*/
753 (hashfunc)0, /*tp_hash*/
756 /* End of code for FSSpec objects */
757 /* -------------------------------------------------------- */
758 #if !TARGET_API_MAC_OS8
759 static PyObject *
760 mfsr_as_fsspec(mfsrobject *self, PyObject *args)
762 OSErr err;
763 FSSpec fss;
765 if (!PyArg_ParseTuple(args, ""))
766 return NULL;
767 err = FSGetCatalogInfo(&self->fsref, kFSCatInfoNone, NULL, NULL, &fss, NULL);
768 if ( err ) {
769 PyErr_Mac(ErrorObject, err);
770 return NULL;
772 Py_INCREF(Py_None);
773 return (PyObject *)newmfssobject(&fss);
776 static PyObject *
777 mfsr_as_pathname(mfsrobject *self, PyObject *args)
779 unsigned char strbuf[PATHNAMELEN];
780 OSStatus err;
782 if (!PyArg_ParseTuple(args, ""))
783 return NULL;
784 err = FSRefMakePath(&self->fsref, strbuf, PATHNAMELEN);
785 if ( err ) {
786 PyErr_Mac(ErrorObject, err);
787 return NULL;
789 return PyString_FromString((char *)strbuf);
792 static struct PyMethodDef mfsr_methods[] = {
793 {"as_fsspec", (PyCFunction)mfsr_as_fsspec, 1},
794 {"as_pathname", (PyCFunction)mfsr_as_pathname, 1},
795 #if 0
796 {"as_tuple", (PyCFunction)mfss_as_tuple, 1},
797 {"NewAlias", (PyCFunction)mfss_NewAlias, 1},
798 {"NewAliasMinimal", (PyCFunction)mfss_NewAliasMinimal, 1},
799 {"GetCreatorType", (PyCFunction)mfss_GetCreatorType, 1},
800 {"SetCreatorType", (PyCFunction)mfss_SetCreatorType, 1},
801 {"GetFInfo", (PyCFunction)mfss_GetFInfo, 1},
802 {"SetFInfo", (PyCFunction)mfss_SetFInfo, 1},
803 {"GetDates", (PyCFunction)mfss_GetDates, 1},
804 {"SetDates", (PyCFunction)mfss_SetDates, 1},
805 #endif
807 {NULL, NULL} /* sentinel */
810 /* ---------- */
812 static PyObject *
813 mfsr_getattr(mfsrobject *self, char *name)
815 if ( strcmp(name, "data") == 0)
816 return PyString_FromStringAndSize((char *)&self->fsref, sizeof(FSRef));
817 return Py_FindMethod(mfsr_methods, (PyObject *)self, name);
820 mfsrobject *
821 newmfsrobject(FSRef *fsr)
823 mfsrobject *self;
825 self = PyObject_NEW(mfsrobject, &Mfsrtype);
826 if (self == NULL)
827 return NULL;
828 self->fsref = *fsr;
829 return self;
832 static int
833 mfsr_compare(mfsrobject *v, mfsrobject *w)
835 OSErr err;
837 if ( v == w ) return 0;
838 err = FSCompareFSRefs(&v->fsref, &w->fsref);
839 if ( err == 0 )
840 return 0;
841 if (v < w )
842 return -1;
843 return 1;
846 static void
847 mfsr_dealloc(mfsrobject *self)
849 PyMem_DEL(self);
852 statichere PyTypeObject Mfsrtype = {
853 PyObject_HEAD_INIT(&PyType_Type)
854 0, /*ob_size*/
855 "macfs.FSRef", /*tp_name*/
856 sizeof(mfsrobject), /*tp_basicsize*/
857 0, /*tp_itemsize*/
858 /* methods */
859 (destructor)mfsr_dealloc, /*tp_dealloc*/
860 (printfunc)0, /*tp_print*/
861 (getattrfunc)mfsr_getattr, /*tp_getattr*/
862 (setattrfunc)0, /*tp_setattr*/
863 (cmpfunc)mfsr_compare, /*tp_compare*/
864 (reprfunc)0, /*tp_repr*/
865 0, /*tp_as_number*/
866 0, /*tp_as_sequence*/
867 0, /*tp_as_mapping*/
868 (hashfunc)0, /*tp_hash*/
871 /* End of code for FSRef objects */
872 #endif /* !TARGET_API_MAC_OS8 */
873 /* -------------------------------------------------------- */
875 static PyObject *
876 mfs_ResolveAliasFile(PyObject *self, PyObject *args)
878 FSSpec fss;
879 Boolean chain = 1, isfolder, wasaliased;
880 OSErr err;
882 if (!PyArg_ParseTuple(args, "O&|i", PyMac_GetFSSpec, &fss, &chain))
883 return NULL;
884 err = ResolveAliasFile(&fss, chain, &isfolder, &wasaliased);
885 if ( err ) {
886 PyErr_Mac(ErrorObject, err);
887 return NULL;
889 return Py_BuildValue("Oii", newmfssobject(&fss), (int)isfolder, (int)wasaliased);
892 #if !TARGET_API_MAC_CARBON
893 static PyObject *
894 mfs_StandardGetFile(PyObject *self, PyObject *args)
896 SFTypeList list;
897 short numtypes;
898 StandardFileReply reply;
900 list[0] = list[1] = list[2] = list[3] = 0;
901 numtypes = 0;
902 if (!PyArg_ParseTuple(args, "|O&O&O&O&", PyMac_GetOSType, &list[0],
903 PyMac_GetOSType, &list[1], PyMac_GetOSType, &list[2],
904 PyMac_GetOSType, &list[3]) )
905 return NULL;
906 while ( numtypes < 4 && list[numtypes] ) {
907 numtypes++;
909 if ( numtypes == 0 )
910 numtypes = -1;
911 StandardGetFile((FileFilterUPP)0, numtypes, list, &reply);
912 return Py_BuildValue("(Oi)", newmfssobject(&reply.sfFile), reply.sfGood);
915 static PyObject *
916 mfs_PromptGetFile(PyObject *self, PyObject *args)
918 SFTypeList list;
919 short numtypes;
920 StandardFileReply reply;
921 char *prompt = NULL;
923 list[0] = list[1] = list[2] = list[3] = 0;
924 numtypes = 0;
925 if (!PyArg_ParseTuple(args, "s|O&O&O&O&", &prompt, PyMac_GetOSType, &list[0],
926 PyMac_GetOSType, &list[1], PyMac_GetOSType, &list[2],
927 PyMac_GetOSType, &list[3]) )
928 return NULL;
929 while ( numtypes < 4 && list[numtypes] ) {
930 numtypes++;
932 if ( numtypes == 0 )
933 numtypes = -1;
934 PyMac_PromptGetFile(numtypes, list, &reply, prompt);
935 return Py_BuildValue("(Oi)", newmfssobject(&reply.sfFile), reply.sfGood);
938 static PyObject *
939 mfs_StandardPutFile(PyObject *self, PyObject *args)
941 Str255 prompt, dft;
942 StandardFileReply reply;
944 dft[0] = 0;
945 if (!PyArg_ParseTuple(args, "O&|O&", PyMac_GetStr255, &prompt, PyMac_GetStr255, &dft) )
946 return NULL;
947 StandardPutFile(prompt, dft, &reply);
948 return Py_BuildValue("(Oi)",newmfssobject(&reply.sfFile), reply.sfGood);
952 ** Set initial directory for file dialogs */
953 static PyObject *
954 mfs_SetFolder(PyObject *self, PyObject *args)
956 FSSpec spec;
957 FSSpec ospec;
958 short orefnum;
959 long oparid;
961 /* Get old values */
962 orefnum = -LMGetSFSaveDisk();
963 oparid = LMGetCurDirStore();
964 (void)FSMakeFSSpec(orefnum, oparid, "\pplaceholder", &ospec);
966 /* Go to working directory by default */
967 (void)FSMakeFSSpec(0, 0, "\p:placeholder", &spec);
968 if (!PyArg_ParseTuple(args, "|O&", PyMac_GetFSSpec, &spec))
969 return NULL;
970 /* Set standard-file working directory */
971 LMSetSFSaveDisk(-spec.vRefNum);
972 LMSetCurDirStore(spec.parID);
973 return (PyObject *)newmfssobject(&ospec);
975 #endif
977 static PyObject *
978 mfs_FSSpec(PyObject *self, PyObject *args)
980 FSSpec fss;
982 if (!PyArg_ParseTuple(args, "O&", PyMac_GetFSSpec, &fss))
983 return NULL;
984 return (PyObject *)newmfssobject(&fss);
987 static PyObject *
988 mfs_FSRef(PyObject *self, PyObject *args)
990 #if TARGET_API_MAC_OS8
991 PyErr_SetString(PyExc_NotImplementedError, "FSRef objects not supported on this platform");
992 return 0;
993 #else
994 FSRef fsr;
996 if (!PyArg_ParseTuple(args, "O&", PyMac_GetFSRef, &fsr))
997 return NULL;
998 return (PyObject *)newmfsrobject(&fsr);
999 #endif
1002 static PyObject *
1003 mfs_RawFSSpec(PyObject *self, PyObject *args)
1005 FSSpec *fssp;
1006 int size;
1008 if (!PyArg_ParseTuple(args, "s#", &fssp, &size))
1009 return NULL;
1010 if ( size != sizeof(FSSpec) ) {
1011 PyErr_SetString(PyExc_TypeError, "Incorrect size for FSSpec record");
1012 return NULL;
1014 return (PyObject *)newmfssobject(fssp);
1017 static PyObject *
1018 mfs_RawAlias(PyObject *self, PyObject *args)
1020 char *dataptr;
1021 Handle h;
1022 int size;
1024 if (!PyArg_ParseTuple(args, "s#", &dataptr, &size))
1025 return NULL;
1026 h = NewHandle(size);
1027 if ( h == NULL ) {
1028 PyErr_NoMemory();
1029 return NULL;
1031 HLock(h);
1032 memcpy((char *)*h, dataptr, size);
1033 HUnlock(h);
1034 return (PyObject *)newmfsaobject((AliasHandle)h);
1037 #if !TARGET_API_MAC_CARBON
1038 static PyObject *
1039 mfs_GetDirectory(PyObject *self, PyObject *args)
1041 FSSpec fsdir;
1042 int ok;
1043 char *prompt = NULL;
1045 if (!PyArg_ParseTuple(args, "|s", &prompt) )
1046 return NULL;
1048 ok = PyMac_GetDirectory(&fsdir, prompt);
1049 return Py_BuildValue("(Oi)", newmfssobject(&fsdir), ok);
1051 #endif
1053 static PyObject *
1054 mfs_FindFolder(PyObject *self, PyObject *args)
1056 OSErr err;
1057 short where;
1058 OSType which;
1059 int create;
1060 short refnum;
1061 long dirid;
1063 if (!PyArg_ParseTuple(args, "hO&i", &where, PyMac_GetOSType, &which, &create) )
1064 return NULL;
1065 err = FindFolder(where, which, (Boolean)create, &refnum, &dirid);
1066 if ( err ) {
1067 PyErr_Mac(ErrorObject, err);
1068 return NULL;
1070 return Py_BuildValue("(ii)", refnum, dirid);
1073 static PyObject *
1074 mfs_FindApplication(PyObject *self, PyObject *args)
1076 OSErr err;
1077 OSType which;
1078 FSSpec fss;
1080 if (!PyArg_ParseTuple(args, "O&", PyMac_GetOSType, &which) )
1081 return NULL;
1082 err = FindApplicationFromCreator(which, &fss);
1083 if ( err ) {
1084 PyErr_Mac(ErrorObject, err);
1085 return NULL;
1087 return (PyObject *)newmfssobject(&fss);
1090 static PyObject *
1091 mfs_FInfo(PyObject *self, PyObject *args)
1093 return (PyObject *)newmfsiobject();
1096 static PyObject *
1097 mfs_NewAliasMinimalFromFullPath(PyObject *self, PyObject *args)
1099 OSErr err;
1100 char *fullpath;
1101 int fullpathlen;
1102 AliasHandle alias;
1103 Str32 zonename;
1104 Str31 servername;
1106 if (!PyArg_ParseTuple(args, "s#", &fullpath, &fullpathlen) )
1107 return NULL;
1108 zonename[0] = 0;
1109 servername[0] = 0;
1110 err = NewAliasMinimalFromFullPath(fullpathlen, (Ptr)fullpath, zonename,
1111 servername, &alias);
1112 if ( err ) {
1113 PyErr_Mac(ErrorObject, err);
1114 return NULL;
1116 return (PyObject *)newmfsaobject(alias);
1120 /* List of methods defined in the module */
1122 static struct PyMethodDef mfs_methods[] = {
1123 {"ResolveAliasFile", mfs_ResolveAliasFile, 1},
1124 #if !TARGET_API_MAC_CARBON
1125 {"StandardGetFile", mfs_StandardGetFile, 1},
1126 {"PromptGetFile", mfs_PromptGetFile, 1},
1127 {"StandardPutFile", mfs_StandardPutFile, 1},
1128 {"GetDirectory", mfs_GetDirectory, 1},
1129 {"SetFolder", mfs_SetFolder, 1},
1130 #endif
1131 {"FSSpec", mfs_FSSpec, 1},
1132 {"FSRef", mfs_FSRef, 1},
1133 {"RawFSSpec", mfs_RawFSSpec, 1},
1134 {"RawAlias", mfs_RawAlias, 1},
1135 {"FindFolder", mfs_FindFolder, 1},
1136 {"FindApplication", mfs_FindApplication, 1},
1137 {"FInfo", mfs_FInfo, 1},
1138 {"NewAliasMinimalFromFullPath", mfs_NewAliasMinimalFromFullPath, 1},
1140 {NULL, NULL} /* sentinel */
1144 ** Convert a Python object to an FSSpec.
1145 ** The object may either be a full pathname, an FSSpec, an FSRef or a triple
1146 ** (vrefnum, dirid, path).
1149 PyMac_GetFSRef(PyObject *v, FSRef *fsr)
1151 #if TARGET_API_MAC_OS8
1152 PyErr_SetString(PyExc_TypeError, "FSRef objects not supported on this platform");
1153 return 0;
1154 #else
1155 /* If it's an FSRef we're also okay. */
1156 if (_mfs_GetFSRefFromFSRef(v, fsr))
1157 return 1;
1158 /* first check whether it already is an FSSpec */
1159 if ( _mfs_GetFSRefFromFSSpec(v, fsr) )
1160 return 1;
1161 if ( PyString_Check(v) ) {
1162 #if TARGET_API_MAC_OSX
1163 OSStatus err;
1164 if ( (err=FSPathMakeRef(PyString_AsString(v), fsr, NULL)) ) {
1165 PyErr_Mac(ErrorObject, err);
1166 return 0;
1168 return 1;
1169 #else
1170 PyErr_SetString(PyExc_NotImplementedError, "Cannot create an FSRef from a pathname on this platform");
1171 return 0;
1172 #endif
1174 PyErr_SetString(PyExc_TypeError, "FSRef argument should be existing FSRef, FSSpec or (OSX only) pathname");
1175 return 0;
1176 #endif
1179 /* Convert FSSpec to PyObject */
1180 PyObject *PyMac_BuildFSRef(FSRef *v)
1182 #if TARGET_API_MAC_OS8
1183 return NULL;
1184 #else
1185 return (PyObject *)newmfsrobject(v);
1186 #endif
1190 ** Convert a Python object to an FSRef.
1191 ** The object may either be a full pathname (OSX only), an FSSpec or an FSRef.
1194 PyMac_GetFSSpec(PyObject *v, FSSpec *fs)
1196 Str255 path;
1197 short refnum;
1198 long parid;
1199 OSErr err;
1201 /* first check whether it already is an FSSpec */
1202 if ( _mfs_GetFSSpecFromFSSpec(v, fs) )
1203 return 1;
1204 /* If it's an FSRef we're also okay. */
1205 if (_mfs_GetFSSpecFromFSRef(v, fs))
1206 return 1;
1207 if ( PyString_Check(v) ) {
1208 #if TARGET_API_MAC_OSX
1209 FSRef fsr;
1211 if ( !PyMac_GetFSRef(v, &fsr) )
1212 return 0;
1213 if ( FSGetCatalogInfo(&fsr, kFSCatInfoNone, NULL, NULL, fs, NULL) == noErr )
1214 return 1;
1215 return 0;
1216 #else
1217 /* It's a pathname */
1218 if( !PyArg_Parse(v, "O&", PyMac_GetStr255, &path) )
1219 return 0;
1220 refnum = 0; /* XXXX Should get CurWD here?? */
1221 parid = 0;
1222 #endif
1223 } else {
1224 if( !PyArg_Parse(v, "(hlO&); FSSpec should be FSSpec, FSRef, fullpath or (vrefnum,dirid,path)",
1225 &refnum, &parid, PyMac_GetStr255, &path)) {
1226 return 0;
1229 err = FSMakeFSSpec(refnum, parid, path, fs);
1230 if ( err && err != fnfErr ) {
1231 PyMac_Error(err);
1232 return 0;
1234 return 1;
1237 /* Convert FSSpec to PyObject */
1238 PyObject *PyMac_BuildFSSpec(FSSpec *v)
1240 return (PyObject *)newmfssobject(v);
1245 ** Import the macfsn module, which will override the Standard File
1246 ** calls in the macfs builtin module by Navigation Services versions,
1247 ** if available on this machine.
1249 static void
1250 PyMac_InstallNavServicesForSF(void)
1252 #ifndef TARGET_API_MAC_OSX
1253 if ( !PyMac_options.nonavservice ) {
1254 #endif
1255 PyObject *m = PyImport_ImportModule("macfsn");
1257 if ( m == NULL ) {
1258 PySys_WriteStderr("'import macfsn' failed; ");
1259 if (Py_VerboseFlag) {
1260 PySys_WriteStderr("traceback:\n");
1261 PyErr_Print();
1263 else {
1264 PySys_WriteStderr("use -v for traceback\n");
1266 PyErr_Clear();
1268 #ifndef TARGET_API_MAC_OSX
1270 #endif
1274 /* Initialization function for the module (*must* be called initmacfs) */
1276 void
1277 initmacfs(void)
1279 PyObject *m, *d;
1281 PyMac_INIT_TOOLBOX_OBJECT_CONVERT(FSSpec, PyMac_GetFSSpec);
1282 PyMac_INIT_TOOLBOX_OBJECT_CONVERT(FSRef, PyMac_GetFSRef);
1283 PyMac_INIT_TOOLBOX_OBJECT_NEW(FSSpec *, PyMac_BuildFSSpec);
1284 PyMac_INIT_TOOLBOX_OBJECT_NEW(FSRef *, PyMac_BuildFSRef);
1286 /* Create the module and add the functions */
1287 m = Py_InitModule("macfs", mfs_methods);
1289 /* Add some symbolic constants to the module */
1290 d = PyModule_GetDict(m);
1291 ErrorObject = PyMac_GetOSErrException();
1292 PyDict_SetItemString(d, "error", ErrorObject);
1294 Mfsatype.ob_type = &PyType_Type;
1295 Py_INCREF(&Mfsatype);
1296 PyDict_SetItemString(d, "AliasType", (PyObject *)&Mfsatype);
1297 Mfsstype.ob_type = &PyType_Type;
1298 Py_INCREF(&Mfsstype);
1299 PyDict_SetItemString(d, "FSSpecType", (PyObject *)&Mfsstype);
1300 Mfsitype.ob_type = &PyType_Type;
1301 Py_INCREF(&Mfsitype);
1302 PyDict_SetItemString(d, "FInfoType", (PyObject *)&Mfsitype);
1304 PyMac_InstallNavServicesForSF();