]> code.delx.au - gnu-emacs/blobdiff - lisp/international/mule.el
(buffer-file-coding-system-explicit):
[gnu-emacs] / lisp / international / mule.el
index 9136a257ee19df78137a46ff6a5604044f2ba4f2..fe16d07fe17411e45961d0e245fd116127c608ff 100644 (file)
@@ -1135,7 +1135,7 @@ FROM is a form to evaluate to define the coding-system."
   (setq coding-system-alist (cons (list (symbol-name symbol))
                                  coding-system-alist)))
 
-(defun set-buffer-file-coding-system (coding-system &optional force)
+(defun set-buffer-file-coding-system (coding-system &optional force nomodify)
   "Set the file coding-system of the current buffer to CODING-SYSTEM.
 This means that when you save the buffer, it will be converted
 according to CODING-SYSTEM.  For a list of possible values of CODING-SYSTEM,
@@ -1149,8 +1149,9 @@ specified there).  Otherwise, leave it unspecified.
 
 This marks the buffer modified so that the succeeding \\[save-buffer]
 surely saves the buffer with CODING-SYSTEM.  From a program, if you
-don't want to mark the buffer modified, just set the variable
-`buffer-file-coding-system' directly."
+don't want to mark the buffer modified, specify t for NOMODIFY.
+If you know exactly what coding system you want to use,
+just set the variable `buffer-file-coding-system' directly."
   (interactive "zCoding system for saving file (default, nil): \nP")
   (check-coding-system coding-system)
   (if (and coding-system buffer-file-coding-system (null force))
@@ -1161,7 +1162,8 @@ don't want to mark the buffer modified, just set the variable
   ;; `set-buffer-major-mode-hook' take care of setting the table.
   (if (fboundp 'ucs-set-table-for-input) ; don't lose when building
       (ucs-set-table-for-input))
-  (set-buffer-modified-p t)
+  (unless nomodify
+    (set-buffer-modified-p t))
   (force-mode-line-update))
 
 (defun revert-buffer-with-coding-system (coding-system &optional force)
@@ -1725,18 +1727,41 @@ function by default."
 
 (setq set-auto-coding-function 'set-auto-coding)
 
-(defun after-insert-file-set-coding (inserted)
+;; This variable is set in these two cases:
+;;   (1) A file is read by a coding system specified explicitly.
+;;       after-insert-file-set-coding sets this value to
+;;       coding-system-for-read.
+;;   (2) A buffer is saved.
+;;       After writing, basic-save-buffer-1 sets this value to
+;;       last-coding-system-used.
+;; This variable is used for decoding in revert-buffer.
+(defvar buffer-file-coding-system-explicit nil
+  "The file coding system explicitly specified for the current buffer.
+Internal use only.")
+(make-variable-buffer-local 'buffer-file-coding-system-explicit)
+(put 'buffer-file-coding-system-explicit 'permanent-local t)
+
+(defun after-insert-file-set-coding (inserted &optional visit)
   "Set `buffer-file-coding-system' of current buffer after text is inserted.
 INSERTED is the number of characters that were inserted, as figured
 in the situation before this function.  Return the number of characters
 inserted, as figured in the situation after.  The two numbers can be
-different if the buffer has become unibyte."
+different if the buffer has become unibyte.
+The optional second arg VISIT non-nil means that we are visiting a file."
+  (if (and visit
+          coding-system-for-read
+          (not (eq coding-system-for-read 'auto-save-coding)))
+      (setq buffer-file-coding-system-explicit coding-system-for-read))
   (if last-coding-system-used
       (let ((coding-system
             (find-new-buffer-file-coding-system last-coding-system-used))
            (modified-p (buffer-modified-p)))
        (when coding-system
-         (set-buffer-file-coding-system coding-system t)
+         ;; Tell set-buffer-file-coding-system not to mark the file
+         ;; as modified; we just read it, and it's supposed to be unmodified.
+         ;; Marking it modified would try to lock it, which would
+         ;; check the modtime, and we don't want to do that again now.
+         (set-buffer-file-coding-system coding-system t t)
          (if (and enable-multibyte-characters
                   (or (eq coding-system 'no-conversion)
                       (eq (coding-system-type coding-system) 5))
@@ -1746,7 +1771,9 @@ different if the buffer has become unibyte."
                   (= (buffer-size) inserted))
              ;; For coding systems no-conversion and raw-text...,
              ;; edit the buffer as unibyte.
-             (let ((pos-marker (copy-marker (+ (point) inserted))))
+             (let ((pos-marker (copy-marker (+ (point) inserted)))
+                   ;; Prevent locking.
+                   (buffer-file-name nil))
                (set-buffer-multibyte nil)
                (setq inserted (- pos-marker (point)))))
          (set-buffer-modified-p modified-p))))
@@ -1870,13 +1897,27 @@ or a function symbol which, when called, returns such a cons cell."
 (defun decode-coding-inserted-region (from to filename
                                           &optional visit beg end replace)
   "Decode the region between FROM and TO as if it is read from file FILENAME.
+The idea is that the text between FROM and TO was just inserted somehow.
 Optional arguments VISIT, BEG, END, and REPLACE are the same as those
-of the function `insert-file-contents'."
+of the function `insert-file-contents'.
+Part of the job of this function is setting `buffer-undo-list' appropriately."
   (save-excursion
     (save-restriction
-      (narrow-to-region from to)
-      (goto-char (point-min))
-      (let ((coding coding-system-for-read))
+      (let ((coding coding-system-for-read)
+           undo-list-saved)
+       (if visit
+           ;; Temporarily turn off undo recording, if we're decoding the
+           ;; text of a visited file.
+           (setq buffer-undo-list t)
+         ;; Otherwise, if we can recognize the undo elt for the insertion,
+         ;; remove it and get ready to replace it later.
+         ;; In the mean time, turn off undo recording.
+         (let ((last (car-safe buffer-undo-list))) 
+           (if (and (consp last) (eql (car last) from) (eql (cdr last) to))
+               (setq undo-list-saved (cdr buffer-undo-list)
+                     buffer-undo-list t))))
+       (narrow-to-region from to)
+       (goto-char (point-min))
        (or coding
            (setq coding (funcall set-auto-coding-function
                                  filename (- (point-max) (point-min)))))
@@ -1891,7 +1932,35 @@ of the function `insert-file-contents'."
          (setq coding nil))
        (if coding
            (decode-coding-region (point-min) (point-max) coding)
-         (setq last-coding-system-used coding))))))
+         (setq last-coding-system-used coding))
+       ;; If we're decoding the text of a visited file,
+       ;; the undo list should start out empty.
+       (if visit
+           (setq buffer-undo-list nil)
+         ;; If we decided to replace the undo entry for the insertion,
+         ;; do so now.
+         (if undo-list-saved
+             (setq buffer-undo-list
+                   (cons (cons from (point-max)) undo-list-saved))))))))
+
+(defun recode-region (start end new-coding coding)
+  "Re-decode the region (previously decoded by CODING) by NEW-CODING."
+  (interactive
+   (list (region-beginning) (region-end)
+        (read-coding-system "Text was really in: ")
+        (let ((coding (or buffer-file-coding-system last-coding-system-used)))
+          (read-coding-system
+           (concat "But was interpreted as"
+                   (if coding (format " (default %S): " coding) ": "))
+           coding))))
+  (or (and new-coding coding)
+      (error "Coding system not specified"))
+  ;; Check it before we encode the region.
+  (check-coding-system new-coding)
+  (save-restriction
+    (narrow-to-region start end)
+    (encode-coding-region (point-min) (point-max) coding)
+    (decode-coding-region (point-min) (point-max) new-coding)))
 
 (defun make-translation-table (&rest args)
   "Make a translation table from arguments.