home *** CD-ROM | disk | FTP | other *** search
- (in-package :oou)
- (oou-provide :Resources-u)
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Resources-u.Lisp
- ;;
- ;; Copyright ⌐ 1992 Northwestern University Institute for the Learning Sciences
- ;; All Rights Reserved
- ;;
- ;; author: Michael S. Engber
- ;;
- ;; Utilities for working with resources
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- (oou-dependencies :traps-u)
-
- (export '(with-res-file with-purgeable-resource without-res-load
- get-resource get-resource-id get-resource-name
- release-resource resource-handlep resource-purgeablep
- open-res-file close-res-file opened-res-file-p
- ))
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;; defrecords & macros
-
- (eval-when (:compile-toplevel :load-toplevel :execute)
-
- (defrecord (ResourceHeader :handle)
- (dataOffset longint)
- (mapOffset longint)
- (dataLength longint)
- (mapLength longint))
-
- (defrecord (ResourceMap :handle)
- (header ResourceHeader)
- (nextMapH handle)
- (refnum integer)
- (fileAttributes integer)
- (typeListOffset integer)
- (nameListOffset integer))
-
-
- (defmacro with-res-file-refNum ((refNum
- &key
- (close-when-done-p nil)
- (write-changes-p nil))
- &body body)
- (let ((new-refNum (gensym))
- (old-refNum (gensym)))
- `(let ((,new-refNum)
- (,old-refNum (require-trap #_CurResFile)))
- (declare (dynamic-extent ,old-refNum ,new-refNum)
- (fixnum ,old-refNum ,new-refNum))
- (unwind-protect
- (progn
- ;must protect evaluation of refNum in case it alters
- ;the current res file (like a call to open-res-file)
- (setf ,new-refNum ,refNum)
- (require-trap #_UseResFile ,new-refNum)
- ,@body)
- (when ,new-refNum
- (when ,write-changes-p (require-trap #_UpdateResFile ,new-refNum))
- (when ,close-when-done-p (require-trap #_CloseResFile ,new-refNum)))
- (require-trap #_UseResFile ,old-refNum)))))
-
- (defmacro with-res-file ((pathname
- &key
- (if-does-not-exist :error)
- (if-no-rsrc-fork :error)
- (if-not-open :close-when-done)
- (if-open :leave-open)
- (write-changes-p nil))
- &body body)
- (let ((close-flag (gensym)))
- `(let ((,close-flag (ecase (if (opened-res-file-p ,pathname) ,if-open ,if-not-open)
- (:close-when-done t)
- (:leave-open nil))))
- (declare (dynamic-extent ,close-flag))
- (with-res-file-refNum ((open-res-file ,pathname
- :if-does-not-exist ,if-does-not-exist
- :if-no-rsrc-fork ,if-no-rsrc-fork)
- :close-when-done-p ,close-flag
- :write-changes-p ,write-changes-p)
- ,@body))))
-
- (defmacro without-res-load (&body body)
- `(unwind-protect
- (progn
- (require-trap #_SetResLoad nil)
- ,@body)
- (require-trap #_SetResLoad t)))
-
- (defmacro with-purgeable-resource ((rsrc-handle &key (changed-p nil)) &body body)
- (let ((hState (gensym))
- (rsrc_h (gensym)))
- `(let ((,rsrc_h ,rsrc-handle)
- (,hState nil))
- (declare (dynamic-extent ,hState ,rsrc_h)
- (fixnum ,hState))
- (unwind-protect
- (progn
- (without-interrupts
- (require-trap #_LoadResource ,rsrc_h)
- (require-trap #_HNoPurge ,rsrc_h)
- (setf ,hState (require-trap #_HGetState ,rsrc_h)))
- ,@body)
- (when ,changed-p (require-trap #_ChangedResource ,rsrc_h))
- (require-trap #_HSetState ,rsrc_h ,hState)))))
-
- )
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;; individual resources
-
- (defun get-resource (rsrc-type rsrc-id-or-name &key (errorp t))
- (without-interrupts
- (let ((rsrc_h (etypecase rsrc-id-or-name
- (fixnum (#_GetResource rsrc-type rsrc-id-or-name))
- (string (with-pstrs ((name_p rsrc-id-or-name))
- (#_GetNamedResource rsrc-type name_p))))))
- (when (and errorp (%null-ptr-p rsrc_h))
- (error "Failed to load resource ~s of type ~s (ResError = ~a)."
- rsrc-id-or-name rsrc-type (#_ResError)))
- rsrc_h)))
-
- (defun release-resource (rsrc-handle)
- (if (resource-handlep rsrc-handle)
- (#_ReleaseResource rsrc-handle)
- (error "~s is not a resource handle" rsrc-handle)))
-
- (defun get-resource-id (rsrc-type rsrc-name &key (errorp t))
- (with-returned-pstrs ((name_p rsrc-name))
- (rlet ((id_p :integer)
- (type_p :OSType))
- (with-macptrs ((rsrc_h (without-res-load (#_GetNamedResource rsrc-type name_p))))
- (without-interrupts
- (#_GetResInfo rsrc_h id_p type_p name_p)
- (when (and errorp (not (zerop (#_ResError))))
- (error "resource ~s of type ~s not found." rsrc-name rsrc-type))))
- (%get-signed-word id_p))))
-
- (defun get-resource-name (rsrc-type rsrc-id &key (errorp t))
- (with-returned-pstrs ((name_p ""))
- (rlet ((id_p :integer)
- (type_p :OSType))
- (with-macptrs ((rsrc_h (without-res-load (#_GetResource rsrc-type rsrc-id))))
- (without-interrupts
- (#_GetResInfo rsrc_h id_p type_p name_p)
- (when (and errorp (not (zerop (#_ResError))))
- (error "resource ~s of type ~s not found." rsrc-id rsrc-type))))
- (%get-string name_p))))
-
- (defun resource-handlep (handle)
- (logbitp 5 (#_HGetState handle)))
-
- (defun resource-purgeablep (rsrc-handle)
- (logtest #$resPurgeable (#_GetResAttrs rsrc-handle)))
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;; resource files
-
- (defun opened-res-file-p (pathname)
- ;;Determines if the resource fork of the specified resource file is open
- (with-pstrs ((fileName (mac-namestring pathname)))
- (rlet ((pb :HParamBlockRec
- :ioNamePtr fileName
- :ioVRefNum 0
- :ioFDirIndex 0
- :ioDirID 0))
- (trap-nz-echeck (#_PBHGetFInfo pb))
- (logbitp 2 (pref pb :HParamBlockRec.ioFlAttrib)))))
-
- (defun open-res-file (pathname &key (if-does-not-exist :error) (if-no-rsrc-fork :error))
- ;;Opens the resource fork of the the specified file and returns the refNum
- (with-pstrs ((fn (mac-namestring pathname)))
- (unless (probe-file pathname)
- (when if-does-not-exist
- (ecase if-does-not-exist
- (:create (#_CreateResFile fn) (open-res-file pathname))
- (:error (error "~s does not exist" pathname)))))
- (let ((refNum (#_OpenResFile fn)))
- (if (plusp refNum)
- refNum
- (when if-no-rsrc-fork
- (ecase if-no-rsrc-fork
- (:create (#_CreateResFile fn) (open-res-file pathname))
- (:error (error "~s has no resource fork" pathname))))))))
-
- (defun close-res-file (refNum-or-pathname)
- (let ((refNum (etypecase refNum-or-pathname
- (string (when (opened-res-file-p refNum-or-pathname)
- (open-res-file refNum-or-pathname)))
- (pathname (when (opened-res-file-p refNum-or-pathname)
- (open-res-file refNum-or-pathname)))
- (fixnum refNum-or-pathname))))
- (when refnum
- (without-interrupts
- (#_CloseResFile refNum)
- (zerop (#_ResError))))))
-
-
-
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;; resource maps (linked list of resource files)
-
-
- (defun opened-rsrc-file-refNums (&key (start-mapH (%get-ptr (%int-to-ptr #.#$TopMapHndl)))
- (end-mapH (%get-ptr (%int-to-ptr #.#$SysMapHndl))))
- ;;Returns the refNums of the open resource files.
- ;;end-mapH specifies the endpoint (non-inclusive) for the search of the
- ;;resource map linked list. Typically, you want to search till the system
- ;;resource file (the default). Use (%null-ptr) for the complete list
- (unless (eql start-mapH end-mapH)
- (cons (href start-mapH :ResourceMap.refnum)
- (opened-rsrc-file-refnums :start-mapH (href start-mapH :ResourceMap.nextMapH)
- :end-mapH end-mapH))))
-
- (defun opened-MCL-rsrc-file-refNums (&optional include-MCL-p)
- ;;Returns the refNums of open resource files that were opened since MCL
- ;;booted. include-MCL-p determines if MCL's refNum is on the list
- (let ((refNums (opened-rsrc-file-refNums)))
- (if include-MCL-p refNums (rest refNums))))
-
- (defun opened-MCL-rsrc-file-names (&optional include-MCL-p)
- ;;Returns the names of open resource files that were opened since MCL
- ;;booted. include-MCL-p determines if MCL's name is on the list."
- (with-returned-pstrs ((fn ""))
- (rlet ((pb :FCBPBRec
- :ioNamePtr fn
- :ioVRefNum 0
- :ioFCBIndx 0))
- (flet ((fRefNum-to-fn (fRefNum)
- (pset pb :FCBPBRec.ioRefNum fRefNum)
- (trap-nz-echeck (#_PBGetFCBInfo pb))
- (%get-string fn)))
- (declare (dynamic-extent #'fRefNum-to-fn))
- (mapcar #'fRefNum-to-fn (opened-MCL-rsrc-file-refNums include-MCL-p))))))
-