liutanyu / mcl

Automatically exported from code.google.com/p/mcl
Other
0 stars 0 forks source link

choose-file-dialog #10

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
RMCL doesn't allow opening of vanilla text files (such as CLZ (Clozure)
sources) under MacOS 10.5.* and 10.6.*.  

(ccl::choose-file-dialog) works fine, but command-O and other API file
openers do not.

Playing with the definition and varying mac-file-type and mac-file-creator
args has not helped.

mac-file-creator is bound to (application-file-creator *application*) which
is :CCL2.  (ccl::CHOOSE-FILE-DIALOG :mac-file-creator "????") does allow
CLZ source files to be chosen.

But I assume file type and creator codes are obsolete now.

Callers found are:
pop-up-path-menu calls (choose-file-dialog :directory item-dir
:mac-file-type "TEXT")
edit-select-file calls (choose-file-dialog :mac-file-type "TEXT")
get-doc-string-file  calls (choose-file-dialog :directory (or
(ignore-errors (probe-file "ccl:")) (startup-directory)) :mac-file-type :HELP)
load calls (choose-file-dialog :button-string "Load")
require calls (choose-file-dialog :button-string "Load" :mac-file-type
'(#-ppc-target :fasl #+ppc-target :pfsl :text))
ed-yank-file calls (choose-file-dialog :mac-file-type :text)

I would far rather err on the side of being allowed to open more file types
rather than less (even if erroneously).  MCL can be a very useful tool for
work in all sorts of situations beyond editing MCL source code.

Original issue reported on code.google.com by p2.edoc@gmail.com on 6 Oct 2009 at 9:07

GoogleCodeExporter commented 8 years ago
Command-O calls #'EDIT-SELECT-FILE which calls (CHOOSE-FILE-DIALOG 
:MAC-FILE-TYPE "TEXT"). Unlike 
what's reported for OSX 10.5 and 10.6, the resulting dialog lists non-RMCL text 
files such as Clozure sources 
in OSX 10.4.11. 

Using NIL for mac-file-type (the default) makes #'choose-file-dialog call 
#_navcreategetfiledialog with a 
null-ptr for the inTypeList, which makes *all* files selectable in the dialog. 

With *see-untyped-osx-files* set to T (the default) #'choose-file-dialog will 
extend a :mac-file-type 
argument with types supposed to match untyped osx files, specifically these 
three ostypes:

   #.(ff-long-to-ostype 0) "????" :|utxt|

The :mac-file-creator should be #$kNavGenericSignature to match any 
application. #'choose-file-dialog uses 
(application-file-creator *application*) to get the default mac-file-creator, 
which for the lisp development 
system results in :CCL2 - the value of *ccl-file-creator*. The call to 
application-file-creator should be 
substituted with #$kNavGenericSignature to avoid limiting the listed files to 
only those created by the 
application (although this doesn't seem to fix the reported issue). For further 
testing I suggest using using 
:mac-file-creator #$kNavGenericSignature as argument to #'choose-file-dialog 
and test with various values 
for :mac-file-type to see whether any makes a difference.

Original comment by terje.norderhaug on 8 Oct 2009 at 5:43

GoogleCodeExporter commented 8 years ago
OSX maps the ostype :TEXT to the UTI "com.apple.traditional-mac-plain-text", 
which is too specialized to match .lisp files. I suspect that 
#_navcreategetfiledialog in recent versions of OSX uses the same mapping 
internally to convert the ostype to UTI, thus failing to list 
some files even if they are text.

A potential work-around is top set the filter of the choose file dialog to the 
more general URI "public.text", matching all files the system 
understands to be text:

(in-package :ccl)

(deftrap-inline "_NavDialogSetFilterTypeIdentifiers"  ; not defined in (R)MCL 
5.2
    ((inGetFileDialog :NavDialogRef)
     (inTypeIdentifiers :CFArrayRef)) ;AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER
    :OSStatus
    () )

In #'choose-file-dialog, find the line that says:

(when (neq result #$noerr) (throw-cancel :cancel))

; Add the following below the line:

 (when (or (eq mac-file-type :text)
           (and (listp mac-file-type)
                (member :text mac-file-type)))
    ; compensate for ostype :text improperly considered equivalent to the UTI "com.apple.traditional-mac-plain-text"
     (#_NavDialogSetFilterTypeIdentifiers
        (%get-ptr the-dialog)
        (create-cfarray '("public.text"))))

With this in place (CHOOSE-FILE-DIALOG :mac-file-creator #$kNavGenericSignature 
:mac-file-type :TEXT) should list text files even if 
they don't have a :TEXt ostype.

Original comment by terje.norderhaug on 10 Oct 2009 at 4:59

GoogleCodeExporter commented 8 years ago
Use #'string= to test whether mac-file-type is the TEXT ostype as it can be 
either a string or a keyword.

Original comment by terje.norderhaug on 10 Oct 2009 at 7:10

GoogleCodeExporter commented 8 years ago
(typecase mac-file-type
     ((eql :text) T) 
     (string (string= mac-file-type :text))
     (cons (member :text mac-file-type :test #'string=)))

Original comment by terje.norderhaug on 11 Oct 2009 at 1:56

GoogleCodeExporter commented 8 years ago
As (string= "text" :text) fails, doesn't this introduce case sensitivity to the 
arg?

Original comment by p2.edoc@gmail.com on 11 Oct 2009 at 6:46

GoogleCodeExporter commented 8 years ago
Yes - ostypes like |TEXT| are case-sensitive.

Original comment by terje.norderhaug on 11 Oct 2009 at 3:18

GoogleCodeExporter commented 8 years ago
I have added choose-file-dialog-patch.lisp to the Patches.

Original comment by terje.norderhaug on 30 Nov 2009 at 6:52

GoogleCodeExporter commented 8 years ago
The patch above is limited to a single :TEXT mac-file-type argument. In 
addition, as MacOSX no longer relies on OSTypes to determine the type of a 
file, many "untyped" text files will still not be selectable in 
choose-file-dialog: those with no suffix or with a suffix not associated with 
text by the 
UTI system.

As remedy, I suggest that when *see-untyped-osx-files* is true, the 
choose-file-dialog provides a pop-up menu to optionally select all files.

First, in the call to set-default-dialog-creation-options, add this to the 
argument list:

     :NavNoTypePopup (not *see-untyped-osx-files*)

After the call to set-default-dialog-creation-options, insert:

  (when *see-untyped-osx-files*
                  (rset options :navDialogCreationOptions.OptionFlags
                        (logior (rref options :navDialogCreationOptions.OptionFlags)
                                #$kNavAllFilesInPopup)))

To get a list of readable filetypes in the pop-up menu, substitute this for the 
earlier 'typecase mac-file-type' patch:  

(let (utis)
  (with-cfstrs ((kUTTagClassOSType "com.apple.ostype"))
    (dolist (type (if (listp mac-file-type) mac-file-type (list mac-file-type)))
      (case type
        (:text ; compensate for ostype :text improperly considered equivalent to the UTI "com.apple.traditional-mac-plain-text"
         (push "public.plain-text" utis))
        (:lisp
         (push "org.lisp.lisp-source" utis))
        (otherwise
         (let* ((cf-ostype (#_UTCreateStringForOSType type))
                (cf-uti (#_UTTypeCreatePreferredIdentifierForTag kUTTagClassOSType cf-ostype (%null-ptr))))
           (push (%get-cfstring cf-uti) utis) ; does cfrelease!
           (#_cfrelease cf-ostype)))))
    (#_NavDialogSetFilterTypeIdentifiers
     (%get-ptr the-dialog)
     (create-cfarray (nreverse utis)))))

With this in place, the current code "to allow looking at OSX .h and .make 
files" can be eliminated. Also, the initialization and use of 'tphandle' is 
redundant and can be eliminated, as it is no longer necessary to provide a list 
of OSTypes to #_navcreategetfiledialog.

For the record, this is a more efficient but less maintainable implementation:

(rlet ((cfutis (:array :CFStringRef (1+ ntypes))))
  (with-cfstrs ((kUTTagClassOSType "com.apple.ostype"))
    (let ((index 0))
      (dolist (type (if (listp mac-file-type) mac-file-type (list mac-file-type)))
        (case type
          (:text ; avoids using uti "com.apple.traditional-mac-plain-text"
           (%put-ptr cfutis (create-cfstring-simple "public.text") (* index 4)))
          (:lisp
           (%put-ptr cfutis (create-cfstring-simple "org.lisp.lisp-source") (* index 4)))
          (otherwise
           (let* ((cf-ostype (#_UTCreateStringForOSType type))
                  (cf-uti (#_UTTypeCreatePreferredIdentifierForTag kUTTagClassOSType cf-ostype (%null-ptr))))
             (%put-ptr cfutis cf-uti (* index 4)))))
        (incf index))
      (%put-ptr cfutis (%null-ptr) (* index 4)))
    (let ((uti-array (#_cfarraycreate (%null-ptr) cfutis ntypes (%null-ptr))))
      (#_NavDialogSetFilterTypeIdentifiers (%get-ptr the-dialog) uti-array)
      #+ignore
      (#_cfrelease uti-array))))

Original comment by terje.norderhaug on 15 Dec 2009 at 4:03

GoogleCodeExporter commented 8 years ago
Changes added to patch as Revision 87d9f2d4b0

Original comment by terje.norderhaug on 15 Dec 2009 at 4:40

GoogleCodeExporter commented 8 years ago
Patch available at:

http://code.google.com/p/mcl/source/browse/Patches/choose-file-dialog-patch.lisp

Original comment by terje.norderhaug on 17 Dec 2009 at 6:34