Changeset 7142


Ignore:
Timestamp:
Sep 5, 2007, 4:40:18 AM (12 years ago)
Author:
gb
Message:

New! Improved!

The code which arranges for editing changes to be processed in the
main thread now does so via an NSInvocation (ObjC's notion of a
closure, sort of); the methods which run in the main thread handle
the job of synchronizing the underlying the Hemlock string and the
"real" NSMutableAttributedString as well as informing the text system
of pending editing changes via #/edited:range:changeInLength:. The
code which processes deletions does the change processing before
modifying the string (other methods do it after the change); this seems
to be necessary to avoid some things that could cause ticket:50. (I'm
not sure if this fixes ticket:50, but it does seem to fix a reproducible
case.)

The #/replaceCharactersInRange:withString: method on hemlock-text-storage
(which handles buffer changes originating from non-Hemlock sources) is
careful to use a :right-inserting temporary mark when modifying the buffer,
to help ensure that insertions/deletions take place at the correct absolute
position. (This may at least partially address bugs related to things
getting confused/out-of-bounds errors when doing lots of cutting and pasting,
though it's hard to know without reproducible cases.)

The macros NSSTRING-ENCODING-TO-NSINTEGER and NSINTEGER-TO-NSSTRING-ENCODING
are defined before they're used (at least one of them wasn't.)

The handling of text encoding for editor documents has changed in a few ways.
If "automatic" encoding is used in an "Open ..." dialog and is successfully
able to infer a text file's encoding, the encoding that was inferred becomes
the document's encoding (used in subsequent "save" operations.) On some
OSX versions, the automatic detection mechanism can only recognize UTF-16
files that contain a leading BOM (and the editor's code for dealing with
the automatic mechanism didn't expect this to ever work.) On other systems,
the automatic mechanism can return something correct (I've seen UTF-8) but
possibly suboptimal.

The Open... dialog now defaults to something derived from the user's setting
of CCL:*DEFAULT-FILE-CHARACTER-ENCODING*; because "automatic" is a little
unpredictable, the new default is probably better.

The NSDocument mechanism for creating backup files (with names of the
form "name~.ext") is not used; when backup files are created, we try to
copy the original to a file whose name conforms to the (simple, non-versioned)
Emacs scheme ("name.ext~"). More things seem to work better when the
Emacs scheme is used (though I suppose some people might prefer the NSDocument
scheme and we could make this a preference.)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/ccl/cocoa-ide/cocoa-editor.lisp

    r7116 r7142  
    99
    1010(eval-when (:compile-toplevel :execute)
    11   ;; :ALL-IN-COCOA-THREAD selects code that does all rendering
    12   ;; in the Cocoa event thread.
    13   ;; Something else that could be conditionalized (and might
    14   ;; be similarly named) would force all Hemlock commands -
    15   ;; as well as rendering and event handling - to happen in
    16   ;; the Cocoa thread.
    17   (pushnew :all-in-cocoa-thread *features*)
    1811  (use-interface-dir :cocoa))
    1912
     
    3023(def-cocoa-default *editor-background-color* :color '(1.0 1.0 1.0 1.0) "Editor background color")
    3124
     25(defmacro nsstring-encoding-to-nsinteger (n)
     26  (target-word-size-case
     27   (32 `(u32->s32 ,n))
     28   (64 n)))
     29
     30(defmacro nsinteger-to-nsstring-encoding (n)
     31  (target-word-size-case
     32   (32 `(s32->u32 ,n))
     33   (64 n)))
    3234
    3335(defun make-editor-style-map ()
     
    4244                      (unless (eql f font) f)))
    4345         (color-class (find-class 'ns:ns-color))
    44          (colors (vector (#/blackColor color-class)
    45                          (#/whiteColor  color-class)
    46                          (#/darkGrayColor color-class)
    47                          (#/lightGrayColor color-class)
    48                          (#/redColor color-class)
    49                          (#/blueColor color-class)
    50                          (#/greenColor color-class)
    51                          (#/yellowColor color-class)))
     46         (colors (vector (#/blackColor color-class)))
    5247         (styles (make-instance 'ns:ns-mutable-array
    5348                                :with-capacity (the fixnum (* 4 (length colors)))))
     
    309304                       (char-code #\Newline)
    310305                       line (hi::line-next line)
    311                        len (if line (hi::line-length line))
     306                       len (if line (hi::line-length line) 0)
    312307                       idx 0))))))))
    313308
     
    398393    (#/edited:range:changeInLength: self #$NSTextStorageEditedCharacters r 0)))
    399394
    400 (objc:defmethod (#/noteInsertion: :void) ((self hemlock-text-storage) params)
    401   (let* ((pos (#/longValue (#/objectAtIndex: params 0)))
    402          (n (#/longValue (#/objectAtIndex: params 1))))
    403     (textstorage-note-insertion-at-position self pos n)))
    404 
    405 (objc:defmethod (#/noteDeletion: :void) ((self hemlock-text-storage) params)
    406   (let* ((pos (#/longValue (#/objectAtIndex: params 0)))
    407          (n (#/longValue (#/objectAtIndex: params 1))))
    408     (#/edited:range:changeInLength: self #$NSTextStorageEditedCharacters (ns:make-ns-range pos n) (- n))
    409     (let* ((display (hemlock-buffer-string-cache (#/hemlockString self))))
    410       (reset-buffer-cache display)
    411       (update-line-cache-for-index display pos))))
    412 
    413 (objc:defmethod (#/noteModification: :void) ((self hemlock-text-storage) params)
    414   (let* ((pos (#/longValue (#/objectAtIndex: params 0)))
    415          (n (#/longValue (#/objectAtIndex: params 1))))
    416     #+debug
    417     (#_NSLog #@"Note modification: pos = %d, n = %d" :int pos :int n)
     395
     396;;; This runs on the main thread; it synchronizes the "real" NSMutableAttributedString
     397;;; with the hemlock string and informs the textstorage of the insertion.
     398(objc:defmethod (#/noteHemlockInsertionAtPosition:length: :void) ((self hemlock-text-storage)
     399                                                                  (pos :<NSI>nteger)
     400                                                                  (n :<NSI>nteger)
     401                                                                  (extra :<NSI>nteger))
     402  (declare (ignorable extra))
     403  (let* ((cache (#/cache self))
     404         (hemlock-string (#/hemlockString self))
     405         (display (hemlock-buffer-string-cache hemlock-string))
     406         (buffer (buffer-cache-buffer display))
     407         (hi::*buffer-gap-context* (hi::buffer-gap-context buffer))
     408         (font (buffer-active-font buffer))
     409         (document (#/document self)))
     410    #+debug
     411    (#_NSLog #@"insert: pos = %ld, n = %ld" :long pos :long n)
     412    ;; We need to update the hemlock string cache here so that #/substringWithRange:
     413    ;; will work on the hemlock buffer string.
     414    (adjust-buffer-cache-for-insertion display pos n)
     415    (update-line-cache-for-index display pos)
     416    (let* ((replacestring (#/substringWithRange: hemlock-string (ns:make-ns-range pos n))))
     417      (ns:with-ns-range (replacerange pos 0)
     418        (#/replaceCharactersInRange:withString:
     419         cache replacerange replacestring)))
     420    (#/setAttributes:range: cache font (ns:make-ns-range pos n))   
     421    (textstorage-note-insertion-at-position self pos n)
     422    ;; Arguably, changecount stuff should happen via the document's NSUndoManager.
     423    ;; At some point in time, we'll know whether or not we have and are using
     424    ;; an NSUndoManager; while we're in limbo about that, do it here.
     425    (#/updateChangeCount: document #$NSChangeDone)))
     426
     427
     428(objc:defmethod (#/noteHemlockDeletionAtPosition:length: :void) ((self hemlock-text-storage)
     429                                                                 (pos :<NSI>nteger)
     430                                                                 (n :<NSI>nteger)
     431                                                                 (extra :<NSI>nteger))
     432  (declare (ignorable extra))
     433  (ns:with-ns-range (range pos n)
     434    ;; It seems to be necessary to call #/edited:range:changeInLength: before
     435    ;; deleting from the cached attributed string.  It's not clear whether this
     436    ;; is also true of insertions and modifications.
    418437    (#/edited:range:changeInLength: self (logior #$NSTextStorageEditedCharacters
    419                                                  #$NSTextStorageEditedAttributes) (ns:make-ns-range pos n) 0)))
    420 
    421 (objc:defmethod (#/noteAttrChange: :void) ((self hemlock-text-storage) params)
    422   (let* ((pos (#/longValue (#/objectAtIndex: params 0)))
    423          (n (#/longValue (#/objectAtIndex: params 1))))
    424     #+debug (#_NSLog #@"attribute-change at %d/%d" :int pos :int n)
    425     (#/edited:range:changeInLength: self #$NSTextStorageEditedAttributes (ns:make-ns-range pos n) 0)))
    426 
     438                                                 #$NSTextStorageEditedAttributes)
     439                                    range (- n))
     440    (#/deleteCharactersInRange: (#/cache self) range))
     441  (let* ((display (hemlock-buffer-string-cache (#/hemlockString self))))
     442    (reset-buffer-cache display)
     443    (update-line-cache-for-index display pos))
     444  ;; Arguably, changecount stuff should happen via the document's NSUndoManager.
     445  ;; At some point in time, we'll know whether or not we have and are using
     446  ;; an NSUndoManager; while we're in limbo about that, do it here.
     447  (#/updateChangeCount: (#/document self) #$NSChangeDone))
     448 
     449
     450(objc:defmethod (#/noteHemlockModificationAtPosition:length: :void) ((self hemlock-text-storage)
     451                                                                     (pos :<NSI>nteger)
     452                                                                     (n :<NSI>nteger)
     453                                                                     (extra :<NSI>nteger))
     454  (declare (ignorable extra))
     455  (let* ((hemlock-string (#/hemlockString self))
     456         (cache (#/cache self)))
     457    (ns:with-ns-range (range pos n)
     458      (#/replaceCharactersInRange:withString:
     459       cache range (#/substringWithRange: hemlock-string range))
     460      (#/edited:range:changeInLength: self (logior #$NSTextStorageEditedCharacters
     461                                                   #$NSTextStorageEditedAttributes) range 0)))
     462  ;; Arguably, changecount stuff should happen via the document's NSUndoManager.
     463  ;; At some point in time, we'll know whether or not we have and are using
     464  ;; an NSUndoManager; while we're in limbo about that, do it here.
     465  (#/updateChangeCount: (#/document self) #$NSChangeDone))
     466
     467
     468(objc:defmethod (#/noteHemlockAttrChangeAtPosition:length: :void) ((self hemlock-text-storage)
     469                                                                   (pos :<NSI>nteger)
     470                                                                   (n :<NSI>nteger)
     471                                                                   (fontnum :<NSI>nteger))
     472  (ns:with-ns-range (range pos n)
     473    (#/setAttributes:range: (#/cache self) (#/objectAtIndex: (#/styles self) fontnum) range)
     474    (#/edited:range:changeInLength: self #$NSTextStorageEditedAttributes range 0)))
     475
     476(defloadvar *buffer-change-invocation*
     477    (with-autorelease-pool
     478        (#/retain
     479                   (#/invocationWithMethodSignature: ns:ns-invocation
     480                                                     (#/instanceMethodSignatureForSelector:
     481                                                      hemlock-text-storage
     482                                            (@selector #/noteHemlockInsertionAtPosition:length:))))))
     483
     484(defstatic *buffer-change-invocation-lock* (make-lock))
     485
     486         
     487         
    427488(objc:defmethod (#/beginEditing :void) ((self hemlock-text-storage))
    428489  (with-slots (edit-count) self
     
    463524(objc:defmethod #/styles ((self hemlock-text-storage))
    464525  (slot-value self 'styles))
     526
     527(objc:defmethod #/document ((self hemlock-text-storage))
     528  (or
     529   (let* ((string (#/hemlockString self)))
     530     (unless (%null-ptr-p string)
     531       (let* ((cache (hemlock-buffer-string-cache string)))
     532         (when cache
     533           (let* ((buffer (buffer-cache-buffer cache)))
     534             (when buffer
     535               (hi::buffer-document buffer)))))))
     536   +null-ptr+))
    465537
    466538(objc:defmethod #/initWithString: ((self hemlock-text-storage) s)
     
    520592      attrs)))
    521593
     594000
    522595(objc:defmethod (#/replaceCharactersInRange:withString: :void)
    523596    ((self hemlock-text-storage) (r :<NSR>ange) string)
    524   #+debug (#_NSLog #@"Replace in range %ld/%ld with %@"
     597  #+debug 0 (#_NSLog #@"Replace in range %ld/%ld with %@"
    525598                    :<NSI>nteger (pref r :<NSR>ange.location)
    526599                    :<NSI>nteger (pref r :<NSR>ange.length)
     
    532605         (length (pref r :<NSR>ange.length))
    533606         (point (hi::buffer-point buffer)))
    534     (let* ((lisp-string (lisp-string-from-nsstring string))
     607    (let* ((lisp-string (if (> (#/length string) 0) (lisp-string-from-nsstring string)))
    535608           (document (if buffer (hi::buffer-document buffer)))
    536609           (textstorage (if document (slot-value document 'textstorage))))
    537610      (when textstorage (#/beginEditing textstorage))
    538611      (setf (hi::buffer-region-active buffer) nil)
    539       (unless (zerop length)
    540         (hi::with-mark ((start point)
    541                         (end point))
    542           (move-hemlock-mark-to-absolute-position start cache location)
    543           (move-hemlock-mark-to-absolute-position end cache (+ location length))
    544           (hi::delete-region (hi::region start end))))
    545       (hi::insert-string point lisp-string)
     612      (hi::with-mark ((start point :right-inserting))
     613        (move-hemlock-mark-to-absolute-position start cache location)
     614        (unless (zerop length)
     615          (hi::delete-characters start length))
     616        (when lisp-string
     617          (hi::insert-string start lisp-string)))
    546618      (when textstorage
    547619        (#/endEditing textstorage)
     
    14171489     (change :<NSD>ocument<C>hange<T>ype))
    14181490  (declare (ignore change)))
     1491
     1492(objc:defmethod (#/documentChangeCleared :void) ((self echo-area-document)))
    14191493
    14201494(objc:defmethod (#/keyDown: :void) ((self echo-area-view) event)
     
    17501824 
    17511825(defun hi::document-begin-editing (document)
    1752   #-all-in-cocoa-thread
    1753   (#/beginEditing (slot-value document 'textstorage))
    1754   #+all-in-cocoa-thread
    17551826  (#/performSelectorOnMainThread:withObject:waitUntilDone:
    17561827   (slot-value document 'textstorage)
     
    17631834
    17641835(defun hi::document-end-editing (document)
    1765   #-all-in-cocoa-thread
    1766   (#/endEditing (slot-value document 'textstorage))
    1767   #+all-in-cocoa-thread
    17681836  (#/performSelectorOnMainThread:withObject:waitUntilDone:
    17691837   (slot-value document 'textstorage)
     
    17821850
    17831851
    1784 (defun perform-edit-change-notification (textstorage selector pos n)
    1785   (let* ((number-for-pos
    1786           (#/initWithLong: (#/alloc ns:ns-number) pos))
    1787          (number-for-n
    1788           (#/initWithLong: (#/alloc ns:ns-number) n)))
    1789     (rlet ((paramptrs (:array :id 2)))
    1790       (setf (paref paramptrs (:* :id) 0) number-for-pos
    1791             (paref paramptrs (:* :id) 1) number-for-n)
    1792       (let* ((params (#/initWithObjects:count: (#/alloc ns:ns-array) paramptrs 2)))
    1793         (#/performSelectorOnMainThread:withObject:waitUntilDone:
    1794          textstorage selector params  t)
    1795         (#/release params)
    1796         (#/release number-for-n)
    1797         (#/release number-for-pos)))))
     1852(defun perform-edit-change-notification (textstorage selector pos n &optional (extra 0))
     1853  (with-lock-grabbed (*buffer-change-invocation-lock*)
     1854    (let* ((invocation *buffer-change-invocation*))
     1855      (rlet ((ppos :<NSI>nteger pos)
     1856             (pn :<NSI>nteger n)
     1857             (pextra :<NSI>nteger extra))
     1858        (#/setTarget: invocation textstorage)
     1859        (#/setSelector: invocation selector)
     1860        (#/setArgument:atIndex: invocation ppos 2)
     1861        (#/setArgument:atIndex: invocation pn 3)
     1862        (#/setArgument:atIndex: invocation pextra 4))
     1863      (#/performSelectorOnMainThread:withObject:waitUntilDone:
     1864       invocation
     1865       (@selector #/invoke)
     1866       +null-ptr+
     1867       t))))
    17981868
    17991869(defun textstorage-note-insertion-at-position (textstorage pos n)
     
    18101880    (let* ((document (hi::buffer-document buffer))
    18111881           (textstorage (if document (slot-value document 'textstorage)))
    1812            (styles (#/styles textstorage))
    1813            (cache (#/cache textstorage))
    18141882           (pos (mark-absolute-position (hi::region-start region)))
    18151883           (n (- (mark-absolute-position (hi::region-end region)) pos)))
    1816       #+debug
    1817       (#_NSLog #@"Setting font attributes for %d/%d to %@" :int pos :int n :id (#/objectAtIndex: styles font))
    1818       (#/setAttributes:range: cache (#/objectAtIndex: styles font) (ns:make-ns-range pos n))
    18191884      (perform-edit-change-notification textstorage
    1820                                         (@selector #/noteAttrChange:)
     1885                                        (@selector #/noteHemlockAttrChangeAtPosition:length:)
    18211886                                        pos
    1822                                         n))))
     1887                                        n
     1888                                        font))))
    18231889
    18241890(defun buffer-active-font (buffer)
     
    18371903           (textstorage (if document (slot-value document 'textstorage))))
    18381904      (when textstorage
    1839         (let* ((pos (mark-absolute-position mark))
    1840                (cache (#/cache textstorage))
    1841                (hemlock-string (#/hemlockString textstorage))
    1842                (display (hemlock-buffer-string-cache hemlock-string))
    1843                (buffer (buffer-cache-buffer display))
    1844                (font (buffer-active-font buffer)))
     1905        (let* ((pos (mark-absolute-position mark)))
    18451906          (unless (eq (hi::mark-%kind mark) :right-inserting)
    18461907            (decf pos n))
    1847           #+debug
    1848           (#_NSLog #@"insert: pos = %d, n = %d" :int pos :int n)
    1849           ;;(reset-buffer-cache display)
    1850           (adjust-buffer-cache-for-insertion display pos n)
    1851           (update-line-cache-for-index display pos)
    1852           (let* ((replacestring (#/substringWithRange: hemlock-string (ns:make-ns-range pos n))))
    1853             (ns:with-ns-range (replacerange pos 0)
    1854               (#/replaceCharactersInRange:withString:
    1855                cache replacerange replacestring)))
    1856           (#/setAttributes:range: cache font (ns:make-ns-range pos n))
    1857           #+debug (#_NSLog #@"cache = %@" :id cache)
    1858           #-all-in-cocoa-thread
    1859           (textstorage-note-insertion-at-position textstorage pos n)
    1860           #+all-in-cocoa-thread
    18611908          (perform-edit-change-notification textstorage
    1862                                             (@selector "noteInsertion:")
     1909                                            (@selector #/noteHemlockInsertionAtPosition:length:)
    18631910                                            pos
    18641911                                            n))))))
     
    18691916           (textstorage (if document (slot-value document 'textstorage))))
    18701917      (when textstorage
    1871         (let* ((hemlock-string (#/hemlockString textstorage))
    1872                (cache (#/cache textstorage))
    1873                (pos (mark-absolute-position mark)))
    1874           (ns:with-ns-range (range pos n)
    1875             (#/replaceCharactersInRange:withString:
    1876              cache range (#/substringWithRange: hemlock-string range))
    1877             #+debug
    1878             (#_NSLog #@"enqueue modify: pos = %d, n = %d"
    1879                      :int pos
    1880                      :int n)
    1881             #-all-in-cocoa-thread
    1882             (#/edited:range:changeInLength:
    1883              textstorage
    1884              (logior #$NSTextStorageEditedCharacters
    1885                      #$NSTextStorageEditedAttributes)
    1886              range
    1887              0)
    1888             #+all-in-cocoa-thread
    18891918            (perform-edit-change-notification textstorage
    1890                                               (@selector #/noteModification:)
     1919                                              (@selector #/noteHemlockModificationAtPosition:length:)
    18911920                                              (mark-absolute-position mark)
    1892                                               n)))))))
     1921                                              n)))))
    18931922 
    18941923
     
    18981927           (textstorage (if document (slot-value document 'textstorage))))
    18991928      (when textstorage
    1900         (let* ((pos (mark-absolute-position mark))
    1901                (cache (#/cache textstorage)))
    1902           #-all-in-cocoa-thread
    1903           (progn
    1904             (#/edited:range:changeInLength:
    1905              textstorage #$NSTextStorageEditedCharacters (ns:make-ns-range pos n) (- n))
    1906             (let* ((display (hemlock-buffer-string-cache (#/hemlockString textstorage))))
    1907               (reset-buffer-cache display)
    1908               (update-line-cache-for-index display pos)))
    1909           (#/deleteCharactersInRange: cache (ns:make-ns-range pos (abs n)))
    1910           #+all-in-cocoa-thread
     1929        (let* ((pos (mark-absolute-position mark)))
    19111930          (perform-edit-change-notification textstorage
    1912                                             (@selector #/noteDeletion:)
     1931                                            (@selector #/noteHemlockDeletionAtPosition:length:)
    19131932                                            pos
    19141933                                            (abs n)))))))
    19151934
     1935
     1936
    19161937(defun hi::set-document-modified (document flag)
    1917   (#/updateChangeCount: document (if flag #$NSChangeDone #$NSChangeCleared)))
     1938  (unless flag
     1939    (#/performSelectorOnMainThread:withObject:waitUntilDone:
     1940     document
     1941     (@selector #/documentChangeCleared)
     1942     +null-ptr+
     1943     t)))
    19181944
    19191945
     
    19932019(defclass hemlock-editor-document (ns:ns-document)
    19942020    ((textstorage :foreign-type :id)
    1995      (encoding :foreign-type :<NSS>tring<E>ncoding))
     2021     (encoding :foreign-type :<NSS>tring<E>ncoding :initform (get-default-encoding)))
    19962022  (:metaclass ns:+ns-object))
     2023
     2024(objc:defmethod (#/documentChangeCleared :void) ((self hemlock-editor-document))
     2025  (#/updateChangeCount: self #$NSChangeCleared))
     2026
    19972027
    19982028(defmethod update-buffer-package ((doc hemlock-editor-document) buffer)
     
    21332163               perror)
    21342164              +null-ptr+)))
    2135       (when (%null-ptr-p string)
    2136         (if (zerop selected-encoding)
    2137           (setq selected-encoding (get-default-encoding)))
    2138         (setq string (#/stringWithContentsOfURL:encoding:error:
    2139                       ns:ns-string
    2140                       url
    2141                       selected-encoding
    2142                       perror)))
     2165      (if (%null-ptr-p string)
     2166        (progn
     2167          (if (zerop selected-encoding)
     2168            (setq selected-encoding (get-default-encoding)))
     2169          (setq string (#/stringWithContentsOfURL:encoding:error:
     2170                        ns:ns-string
     2171                        url
     2172                        selected-encoding
     2173                        perror)))
     2174        (setq selected-encoding (pref pused-encoding :<NSS>tring<E>ncoding)))
    21432175      (unless (%null-ptr-p string)
    21442176        (with-slots (encoding) self (setq encoding selected-encoding))
     
    21602192        t))))
    21612193
    2162 #+experimental
    2163 (objc:defmethod (#/writeWithBackupToFile:ofType:saveOperation: :<BOOL>)
    2164     ((self hemlock-editor-document) path type (save-operation :<NSS>ave<O>peration<T>ype))
    2165   #+debug
    2166   (#_NSLog #@"saving file to %@" :id path)
    2167   (call-next-method path type save-operation))
     2194
    21682195
    21692196
     
    21722199
    21732200(objc:defmethod (#/keepBackupFile :<BOOL>) ((self hemlock-editor-document))
    2174   *editor-keep-backup-files*)
    2175 
     2201  ;;; Don't use the NSDocument backup file scheme.
     2202  nil)
     2203
     2204(objc:defmethod (#/writeSafelyToURL:ofType:forSaveOperation:error: :<BOOL>)
     2205    ((self hemlock-editor-document)
     2206     absolute-url
     2207     type
     2208     (save-operation :<NSS>ave<O>peration<T>ype)
     2209     (error (:* :id)))
     2210  (when (and *editor-keep-backup-files*
     2211             (eql save-operation #$NSSaveOperation))
     2212    (write-hemlock-backup-file (#/fileURL self)))
     2213  (call-next-method absolute-url type save-operation error))
     2214
     2215(defun write-hemlock-backup-file (url)
     2216  (unless (%null-ptr-p url)
     2217    (when (#/isFileURL url)
     2218      (let* ((path (#/path url)))
     2219        (unless (%null-ptr-p path)
     2220          (let* ((newpath (#/stringByAppendingString: path #@"~"))
     2221                 (fm (#/defaultManager ns:ns-file-manager)))
     2222            ;; There are all kinds of ways for this to lose.
     2223            ;; In order for the copy to succeed, the destination can't exist.
     2224            ;; (It might exist, but be a directory, or there could be
     2225            ;; permission problems ...)
     2226            (#/removeFileAtPath:handler: fm newpath +null-ptr+)
     2227            (#/copyPath:toPath:handler: fm path newpath +null-ptr+)))))))
     2228
     2229             
    21762230
    21772231(defmethod hemlock-document-buffer (document)
     
    22402294
    22412295
    2242 ;;; Shadow the setFileName: method, so that we can keep the buffer
     2296;;; Shadow the setFileURL: method, so that we can keep the buffer
    22432297;;; name and pathname in synch with the document.
    22442298(objc:defmethod (#/setFileURL: :void) ((self hemlock-editor-document)
     
    24462500
    24472501
    2448 (defmacro nsstring-encoding-to-nsinteger (n)
    2449   (target-word-size-case
    2450    (32 `(u32->s32 ,n))
    2451    (64 n)))
    2452 
    2453 (defmacro nsinteger-to-nsstring-encoding (n)
    2454   (target-word-size-case
    2455    (32 `(s32->u32 ,n))
    2456    (64 n)))
     2502
    24572503
    24582504
     
    24612507;;; user isn't interested in.)
    24622508(defmethod build-encodings-popup ((self hemlock-document-controller)
    2463                                   &optional (preferred-encoding 0))
     2509                                  &optional (preferred-encoding (get-default-encoding)))
    24642510  (let* ((id-list (supported-nsstring-encodings))
    24652511         (popup (make-instance 'ns:ns-pop-up-button)))
Note: See TracChangeset for help on using the changeset viewer.