home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / GNU / emacs.inst / emacs19.idb / usr / gnu / lib / emacs / site-lisp / jka-compr.el.z / jka-compr.el
Encoding:
Text File  |  1994-08-02  |  40.0 KB  |  1,265 lines

  1. ;;; jka-compr19.el - low level support for reading/writing/loading compressed
  2. ;;;                  files in GNU Emacs Version 19.
  3. ;;; bugs/comments to jka@ece.cmu.edu
  4. ;;; Version: 0.7
  5. ;;; Last modified: 12/21/93
  6.  
  7.  
  8. ;;; Copyright (C) 1993  Jay K. Adams
  9. ;;;
  10. ;;; This program is free software; you can redistribute it and/or modify
  11. ;;; it under the terms of the GNU General Public License as published by
  12. ;;; the Free Software Foundation; either version 2 of the License, or
  13. ;;; (at your option) any later version.
  14. ;;;
  15. ;;; This program is distributed in the hope that it will be useful,
  16. ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18. ;;; GNU General Public License for more details.
  19. ;;;
  20. ;;; You should have received a copy of the GNU General Public License
  21. ;;; along with this program; if not, write to the Free Software
  22. ;;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  23.  
  24.  
  25. ;;; LCD Archive Entry:
  26. ;;; jka-compr19|Jay Adams|jka@ece.cmu.edu|
  27. ;;; Low level support for reading/writing/loading compressed files in GNU Emacs V19|
  28. ;;; 21-Dec-1993|0.7|~/misc/jka-compr19.el.Z|
  29.  
  30.  
  31. ;;; This package implements low-level support for reading, writing,
  32. ;;; and loading compressed files.  It hooks into the low-level file I/O
  33. ;;; functions (including write-region and insert-file-contents) so
  34. ;;; that they automatically compress or uncompress a file if the file
  35. ;;; appears to need it (based on the extension of the file name).
  36. ;;; Although its a little presumptious of a low-level function to make
  37. ;;; a decision about whether a file should be compressed or
  38. ;;; uncompressed, doing so offers the benefit of allowing packages
  39. ;;; like Rmail, Vm, Gnus, and Info to work with compressed files
  40. ;;; without modification.
  41.  
  42.  
  43. ;;; INSTRUCTIONS:
  44. ;;;
  45. ;;; To use jka-compr, simply load this package, and edit as usual.
  46. ;;; Its operation should be transparent to the user (except for
  47. ;;; messages appearing when a file is being compressed or
  48. ;;; uncompressed).
  49. ;;;
  50. ;;; The variable, jka-compr-compression-info-list can be used to
  51. ;;; customize jka-compr to work with other compression programs.  The
  52. ;;; default value of this variable allows jka-compr to work with Unix
  53. ;;; compress and gzip.
  54. ;;; 
  55. ;;; If you are concerned about the stderr output of gzip and other
  56. ;;; compression/decompression programs showing up in your buffers you
  57. ;;; should set the discard-error flag in the compression-info-list.
  58. ;;; This will cause the stderr of all programs to be discarded.
  59. ;;; However, it also causes emacs to call compression/uncompression
  60. ;;; programs through a shell (which is specified by jka-compr-shell).
  61. ;;; This may be a drag if, on your system, starting up a shell is
  62. ;;; slow.
  63. ;;;
  64. ;;; If you don't want messages about compressing and decompressing
  65. ;;; to show up in the echo area, you can set the compress-name and
  66. ;;; decompress-name fields of the jka-compr-compression-info-list to
  67. ;;; nil.
  68.  
  69.  
  70. ;;; APPLICATION NOTES:
  71. ;;; 
  72. ;;; dired (note: I don't know if thie still applies in Version 19 of Emacs)
  73. ;;;   Normally jka-compr works fine with dired.  However, one case
  74. ;;;   where it doesn't work so well is when you use the dired 'B'
  75. ;;;   command (byte compile file).  The .z on the file name makes
  76. ;;;   dired think the file is not compilable.  Changing the
  77. ;;;   dired-byte-recompile function to the one shown below will get
  78. ;;;   around this problem.  It makes dired recognize a file as being
  79. ;;;   an emacs lisp file even if it has a .z or .Z extension after the
  80. ;;;   .el. 
  81. ;;;
  82. ;;;   (defun dired-byte-recompile ()
  83. ;;;     "Byte recompile this file."
  84. ;;;     (interactive)
  85. ;;;     (let* ((buffer-read-only nil)
  86. ;;;            (from-file (dired-get-filename))
  87. ;;;            (to-file (substring from-file 0 -3)))
  88. ;;;       (if (string-match "\\.el\\(\\.[zZ]\\)?$" from-file) nil
  89. ;;;           (error "%s is uncompilable!" from-file))
  90. ;;;       (byte-compile-file from-file)))
  91. ;;;
  92. ;;;   The dired supplied with Lucid Emacs 19.6 is a little different
  93. ;;;   and requires the following version of dired-byte-compile (from
  94. ;;;   David Hughes, Apr 20, 1993).
  95. ;;;       
  96. ;;;   (defun dired-byte-compile ()
  97. ;;;     ;; Return nil for success, offending file name else.
  98. ;;;     (let* ((filename (dired-get-filename))
  99. ;;;            (elc-file
  100. ;;;             (if (eq system-type 'vax-vms)
  101. ;;;                 (concat (substring filename 0
  102. ;;;                                    (string-match ";" filename)) "c")
  103. ;;;               (if (string-match "\\.el\\(\\.[zZ]\\)?$" filename)
  104. ;;;                   (concat (substring filename 0
  105. ;;;                                      (match-beginning 0)) ".elc")
  106. ;;;                 (error "%s is uncompilable!" filename))))
  107. ;;;            buffer-read-only failure)
  108. ;;;       (condition-case err
  109. ;;;           (save-excursion (byte-compile-file filename))
  110. ;;;         (error
  111. ;;;          (setq failure err)))
  112. ;;;       (if failure
  113. ;;;           (progn
  114. ;;;             (dired-log "Byte compile error for %s:\n%s\n"
  115. ;;;                        filename failure)
  116. ;;;             (dired-make-relative filename))
  117. ;;;         (dired-remove-file elc-file)
  118. ;;;         (forward-line)                    ; insert .elc after its .el file
  119. ;;;         (dired-add-file elc-file)
  120. ;;;         nil)))
  121. ;;;
  122. ;;;
  123. ;;; rmail, vm, gnus, etc.
  124. ;;;   To use compressed mail folders, .newsrc files, etc., you need
  125. ;;;   only compress the file.  Since jka-compr searches for .z
  126. ;;;   versions of the files it's finding, you need not change
  127. ;;;   variables within rmail, gnus, etc.  
  128. ;;;
  129. ;;; crypt++
  130. ;;;   jka-compr can coexist with crpyt++ if you take all the decryption
  131. ;;;   entries out of the crypt-encoding-list.  Clearly problems will
  132. ;;;   arise if you have two programs trying to compress/decompress
  133. ;;;   files.  jka-compr will not "work with" crypt++: you won't be
  134. ;;;   able to decode encrypted compressed files--that is, files that
  135. ;;;   have been compressed then encrypted (in that order).
  136. ;;;   Theoretically, crypt++ and jka-compr could properly handle a
  137. ;;;   file that has been encrypted then compressed, but there is little
  138. ;;;   point in trying to compress an encrypted file.
  139.  
  140.  
  141.  
  142. ;;; TO DO
  143. ;;;
  144. ;;; Note:  as far as I'm concerned, the whole idea of dealing with
  145. ;;; compressed files in this way is still experimental.  Still, I and
  146. ;;; others have been using this code for some time and have found it
  147. ;;; useful.
  148. ;;;
  149. ;;; Also, I consider this code to be in beta-test.  The bug rate has
  150. ;;; been pretty low, however, so after the few remaining issues
  151. ;;; (listed below) are addressed, I'll release Version 1.0 (maybe
  152. ;;; sometime this summer).
  153. ;;;
  154. ;;; To do list:
  155. ;;;
  156. ;;; 1. Fix it so that the compression extension (.Z or .z) does not
  157. ;;;    appear in the buffer name.
  158. ;;;
  159. ;;; 2. Add the ability to configure translations on the file name to
  160. ;;;    be applied before mode-specification.  For instance, .taz files
  161. ;;;    should be recognized as being compressed but should be treated
  162. ;;;    as .tar files for mode-specification.
  163. ;;;
  164. ;;; 3. Figure out a good way to handle the beg and end args to
  165. ;;;    insert-file-contents.
  166. ;;;
  167.  
  168.  
  169. ;;; History:
  170. ;;;
  171. ;;;   Apr 20, 1993    Started keeping a history of changes.
  172. ;;;
  173. ;;;   Apr 20, 1993    Fixed problems caused by expand-file-name
  174. ;;;                   mysteriously returning nil.
  175. ;;;
  176. ;;;                   0.1 released
  177. ;;;
  178. ;;;   Apr 30, 1993    Added error handler to jka-compr-insert-file-contents
  179. ;;;                   to catch and properly handle errors caused by the 
  180. ;;;                   file not being readable.
  181. ;;;
  182. ;;;   May 25, 1993    Fixed jka-compr-file-name-sans-versions to comply
  183. ;;;                   with Version 19.
  184. ;;;
  185. ;;;                   0.2 released
  186. ;;;
  187. ;;;   June 6, 1993    jka-compr for Version 19 created.  
  188. ;;;                   New file name: jka-compr19.el
  189. ;;;
  190. ;;;                   Added support for the visit argument of
  191. ;;;                   write-region being a string.
  192. ;;;
  193. ;;;                   Changed dummy writes in insert-file-contents and
  194. ;;;                   write-region to calls to set-visited-file-name
  195. ;;;                   and set-visited-file-modtime.
  196. ;;;
  197. ;;;                   Modified the compression-info-list to recognize
  198. ;;;                   the .gz extension for gzip.
  199. ;;;
  200. ;;;                   Added checks for the exit status of calls to
  201. ;;;                   compression and uncompression programs.
  202. ;;;
  203. ;;;                   Changed the way the package hooks into file I/O
  204. ;;;                   functions (using the file-name-handler-alist
  205. ;;;                   instead of overwriting function definitions).
  206. ;;;
  207. ;;;                   Added a rewrite of ange-ftp-file-name-directory
  208. ;;;                   to work around a bug in set-visited-file-modtime.
  209. ;;;
  210. ;;;    June 7, 1993   Created jka-compr-call-process to cut down on
  211. ;;;                   the complexity of jka-compr-write-region and
  212. ;;;                   jka-compr-insert-file-contents.
  213. ;;;
  214. ;;;                   0.3 of jka-compr19 released.
  215. ;;;
  216. ;;;                   Added a workaround for a bug in rename-file (in 19.12).
  217. ;;;
  218. ;;;                   0.3a released.
  219. ;;;
  220. ;;;    June 8, 1993   Added jka-compr-file-local-copy.
  221. ;;;
  222. ;;;                   Added support for loading compressed files (folded
  223. ;;;                   in code from jka-load.el).
  224. ;;;
  225. ;;;                   Change default directory for
  226. ;;;                   jka-compr-temp-name-template to /tmp (was /usr/tmp).
  227. ;;;
  228. ;;;                   0.4 released.
  229. ;;;
  230. ;;;    June 9, 1993   Made jka-compr-write-region understand the meaning
  231. ;;;                   of a string for the visit argument.
  232. ;;;
  233. ;;;                   Added a workaround for a bug in copy-file (in 19.13).
  234. ;;;
  235. ;;;    June 14, 1993  Added support for file-name-completion.
  236. ;;;
  237. ;;;    June 17, 1993  Changed default values of jka-compr-verify- variables.
  238. ;;;
  239. ;;;    June 18, 1993  Implement new args BEG and END for
  240. ;;;                   jka-compr-insert-file-contents.
  241. ;;;
  242. ;;;                   Removed bug workarounds for rename-file and
  243. ;;;                   copy-file.  This version no longer works for
  244. ;;;                   versions of emacs earlier than 19.14.
  245. ;;;
  246. ;;;    June 21, 1993  Removed the bug workaround for set-vistited-file-modtime.
  247. ;;;                   This will no longer work for versions of emacs earlier
  248. ;;;                   than 19.15.
  249. ;;;
  250. ;;;                   Version 0.6
  251. ;;;    
  252. ;;;    Sept. 17, 1993 Disabled file-name-completion (until the problem
  253. ;;;                   with basic-save-buffer can be fixed).
  254. ;;;
  255. ;;;                   Version 0.6a
  256. ;;;
  257. ;;;    Oct. 25, 1993  Modified jka-compr-file-name-sans-versions so
  258. ;;;                   that compression extension would not be removed.
  259. ;;;
  260. ;;;                   Added (set-buffer-modified-p nil) to write
  261. ;;;                   region so that modified flag will be cleared
  262. ;;;                   when a file is saved.
  263. ;;;                   
  264. ;;;                   Added permanent-local variables,
  265. ;;;                   jka-compr-buffer-file-name and
  266. ;;;                   jka-compr-original-file-name, to help
  267. ;;;                   write-region detect when it compress the file
  268. ;;;                   (and where it should write it).
  269. ;;;
  270. ;;;                   Added a workaround for a bug in write-region.
  271. ;;;
  272. ;;;                   Version 0.6b
  273. ;;;
  274. ;;;    Oct. 27, 1993  Added a workaround for a bug in
  275. ;;;                   insert-file-contents (similar to the one in
  276. ;;;                   write-region).
  277. ;;;
  278. ;;;    Nov. 10, 1993  Fixed a bug in write-region (filename should have
  279. ;;;                   been file).
  280. ;;;
  281. ;;;                   Version 0.6d
  282. ;;;
  283. ;;;    Nov. 29, 1993  Fixed the insert-file-contents bug workaround so
  284. ;;;                   that buffer-file-name would be correctly expanded.
  285. ;;;
  286. ;;;                   Version 0.6e
  287. ;;;
  288. ;;;    Dec. 8, 1993   Changed messages in load so that entire pathname
  289. ;;;                   of file is not printed.
  290. ;;;
  291. ;;;                   Version 0.6f
  292. ;;;
  293. ;;;    Dec. 16, 1993  Added a workaround to the auto-save bug
  294. ;;;                   (diagnosed by Chris Ross, cross@eng.umd.edu).
  295. ;;;
  296. ;;;                   Added "-q" flag (supress warning messages) to the
  297. ;;;                   gzip entries in jka-compr-comprssion-info-list.
  298. ;;;
  299. ;;;    Dec. 21, 1993  Reenabled file-name-completion.
  300. ;;;                   
  301. ;;;                   Version 0.7
  302.  
  303.  
  304. (defvar jka-compr-enabled t
  305.   "*Non-nil means that the jka-compr package is enabled.")
  306.  
  307.  
  308. (defvar jka-compr-verify-append-file-change nil
  309.   "Non-nil means ask the user before changing the name of an append file.")
  310.  
  311.  
  312. (defvar jka-compr-verify-overwrite-file-change nil
  313.   "Non-nil means ask the user before changing the name of a file being written.")
  314.  
  315.  
  316. (defvar jka-compr-verify-visited-file-change nil
  317.   "Non-nil means ask the user before changing the visited file name of a buffer.")
  318.  
  319.  
  320. (defvar jka-compr-verify-delete-file-change nil
  321.   "Non-nil means ask the user before changing the name of a file being deleted.")
  322.  
  323.  
  324. (defvar jka-compr-shell "sh"
  325.   "*Shell to be used for calling compression programs.
  326. The value of this variable only matters if you want to discard the
  327. stderr of a compression/decompression program (see the documentation
  328. for jka-compr-compression-info-list).")
  329.  
  330.  
  331. ;;; I have this defined so that .Z files are assumed to be in unix
  332. ;;; compress format; and .z files, in gzip format.
  333. (defvar jka-compr-compression-info-list
  334.   ;;[regexp  magic 
  335.   ;; compr-name  compr-prog  compr-discard  compr-args
  336.   ;; uncomp-name uncomp-prog uncomp-discard uncomp-args
  337.   ;; can-append extension]
  338.   '(["\\.Z~?$"     "\037\235"
  339.      "compress"    "compress"     nil  nil
  340.      "uncompress"  "uncompress"   nil  nil
  341.      nil           ".Z"]
  342.     ["\\.z~?$"     "\037\213"
  343.      "zip"         "gzip"         nil  ("-q")
  344.      "unzip"       "gzip"         nil  ("-q" "-d")
  345.      t             ".z"]
  346.     ["\\.gz~?$"     "\037\213"
  347.      "zip"         "gzip"         nil  ("-q")
  348.      "unzip"       "gzip"         nil  ("-q" "-d")
  349.      t             ".gz"])
  350.  
  351.   "List of vectors that describe available compression techniques.
  352. Each element, which describes a compression technique, is a vector of
  353. the form [regexp magic compress-name compress-program compress-discard-err
  354. compress-args uncompress-name uncompress-program uncompress-discard-err
  355. uncompress-args append-flag extension] where:
  356.  
  357.    regexp                is a regexp that matches filenames that are
  358.                          compressed with this format
  359.  
  360.    magic                 is a two-byte magic number that identifies
  361.                          files that are compressed with this format
  362.  
  363.    compress-name         is an English name of the compression (nil
  364.                          means don't show message when compressing)
  365.  
  366.    compress-program      is a program that performs this compression
  367.  
  368.    compress-discard-err  is non-nil if the stderr output of the compress
  369.                          program should be discarded.  Setting this flag to 
  370.                          non-nil also causes jka-compr to call compression
  371.                          programs using a shell rather than directly.
  372.  
  373.    compress-args         is a list of args to pass to the compress program
  374.  
  375.    uncompress-name       is an English name of the uncompression (nil
  376.                          means don't show message when decompressing)
  377.  
  378.    uncompress-program    is a program that performs this compression
  379.  
  380.    uncompress-discard-err  is non-nil if the stderr output of the uncompress
  381.                          program should be discarded.  Setting this flag to 
  382.                          non-nil also causes jka-compr to call decompression
  383.                          programs using a shell rather than directly.
  384.  
  385.    uncompress-args       is a list of args to pass to the uncompress program
  386.  
  387.    append-flag           is non-nil if this compression technique can be
  388.                          appended
  389.  
  390.    extension             string to add to end of filename when looking for
  391.                          files compressed with this technique.
  392.  
  393. Because of the way call-process is defined, discarding the stderr output of
  394. a program adds the overhead of starting a shell each time the program is
  395. invoked.")
  396.  
  397.  
  398. ;;; Functions for accessing the return value of jka-get-compression-info
  399. (defun jka-compr-info-fname-match-beg      (info)  (car (car info)))
  400. (defun jka-compr-info-fname-match-end      (info)  (cdr (car info)))
  401. (defun jka-compr-info-fname-regexp         (info)  (aref (cdr info) 0))
  402. (defun jka-compr-info-magic                (info)  (aref (cdr info) 1))
  403. (defun jka-compr-info-compress-message     (info)  (aref (cdr info) 2))
  404. (defun jka-compr-info-compress-program     (info)  (aref (cdr info) 3))
  405. (defun jka-compr-info-compress-discard-err (info)  (aref (cdr info) 4))
  406. (defun jka-compr-info-compress-args        (info)  (aref (cdr info) 5))
  407. (defun jka-compr-info-uncompress-message   (info)  (aref (cdr info) 6))
  408. (defun jka-compr-info-uncompress-program   (info)  (aref (cdr info) 7))
  409. (defun jka-compr-info-uncompress-discard-err (info)  (aref (cdr info) 8))
  410. (defun jka-compr-info-uncompress-args      (info)  (aref (cdr info) 9))
  411. (defun jka-compr-info-can-append           (info)  (aref (cdr info) 10))
  412. (defun jka-compr-info-extension            (info)  (aref (cdr info) 11))
  413.  
  414.  
  415. (defun jka-compr-get-compression-info-mapper (x)
  416.   "Function used by jka-compr-get-compression-info
  417. to map across the jka-compr-compression-info-list."
  418.   (let ((case-fold-search nil))
  419.     (if (string-match (aref x 0) filename)
  420.     (throw 'compression-info
  421.            (cons (cons (match-beginning 0) (match-end 0))
  422.              x)))))
  423.  
  424.  
  425. (defvar jka-compr-mktemp-regexp 
  426.   "[A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9]"
  427.   "A regexp that matches the return value of mktemp(3).")
  428.  
  429.  
  430. (defun jka-compr-get-compression-info (filename)
  431.   "Return information about the compression scheme of FILENAME.
  432. The determination as to which compression scheme, if any, to use is
  433. based on the filename itself and jka-compr-compression-info-list."
  434.   (catch 'compression-info
  435.     (mapcar 'jka-compr-get-compression-info-mapper
  436.         jka-compr-compression-info-list)
  437.     nil))
  438.  
  439.  
  440. (defun jka-compr-call-process (prog infile output temp discard-err args)
  441.   (if discard-err
  442.  
  443.       (or (zerop
  444.        (call-process jka-compr-shell infile
  445.              (if (stringp output) nil output)
  446.              nil
  447.              "-c"
  448.              (format "%s -c %s 2> /dev/null %s"
  449.                  prog
  450.                  (mapconcat (function (lambda (x) x))
  451.                         args
  452.                         " ")
  453.                  (if (stringp output)
  454.                      (concat "> " output)
  455.                    ""))))
  456.  
  457.       (error "Non-zero exit status for %s." prog))
  458.  
  459.     (or (zerop
  460.      (apply 'call-process
  461.         prog
  462.         infile
  463.         (if (stringp output) temp output)
  464.         nil
  465.         args))
  466.     (error "Non-zero exit status for %s." prog))
  467.  
  468.     (and (stringp output)
  469.      (let ((cbuf (current-buffer)))
  470.        (set-buffer temp)
  471.        (jka-compr-real-write-region (point-min) (point-max) output)
  472.        (erase-buffer)
  473.        (set-buffer cbuf)))))
  474.  
  475.  
  476. (defvar jka-compr-temp-name-template
  477.   "/tmp/jka-compr")
  478.  
  479.  
  480. (defun jka-compr-write-region (start end file &optional append visit)
  481.   "Documented as original."
  482.   (interactive "r\nFWrite region to file: ")
  483.   (unwind-protect
  484.       (progn
  485.     (setq file-name-handler-alist
  486.           (delq jka-compr-file-name-handler-entry
  487.             file-name-handler-alist))
  488.   (cond
  489.    (jka-compr-enabled
  490.     (let ((filename (expand-file-name file))
  491.       (visited  (and (stringp visit) (expand-file-name visit)))
  492.       zfile)
  493.       
  494.       (if visited
  495.       (progn
  496.         (setq zfile (or (jka-compr-find-compressed-version visited)
  497.                 visited))
  498.         (or
  499.          (string= zfile visited)
  500.          (and
  501.           (or (not jka-compr-verify-visited-file-change)
  502.           (yes-or-no-p (format "Change visited file to %s? " zfile)))
  503.           (setq visit zfile))))
  504.  
  505.     (setq zfile (or (jka-compr-find-compressed-version filename)
  506.             filename))
  507.     (or
  508.      (string= zfile filename)
  509.      (if visit
  510.  
  511.          (and (or (not jka-compr-verify-visited-file-change)
  512.               (yes-or-no-p (format "Change visited file to %s? " zfile)))
  513.           (setq filename zfile))
  514.  
  515.        (if append
  516.  
  517.            (and (or (not jka-compr-verify-append-file-change)
  518.             (yes-or-no-p (format "Append to file %s? " zfile)))
  519.             (setq filename zfile))
  520.  
  521.          (and (or (not jka-compr-verify-overwrite-file-change)
  522.               (yes-or-no-p (format "Overwrite file %s? " zfile)))
  523.           (setq filename zfile))))))
  524.  
  525.       (let ((info (jka-compr-get-compression-info zfile)))
  526.  
  527.     (if info
  528.  
  529.         (let ((can-append (jka-compr-info-can-append info))
  530.           (compress-program (jka-compr-info-compress-program info))
  531.           (compress-message (jka-compr-info-compress-message info))
  532.           (uncompress-program (jka-compr-info-uncompress-program info))
  533.           (uncompress-message (jka-compr-info-uncompress-message info))
  534.           (compress-args (jka-compr-info-compress-args info))
  535.           (uncompress-args (jka-compr-info-uncompress-args info))
  536.           (must-discard-stderr (jka-compr-info-compress-discard-err info))
  537.           (temp-file (make-temp-name jka-compr-temp-name-template))
  538.           (visit-file (if (stringp visit) visit filename))
  539.           cbuf temp-buffer)
  540.  
  541.           (setq cbuf (current-buffer)
  542.             temp-buffer (get-buffer-create " *jka-compr-temp*"))
  543.           (set-buffer temp-buffer)
  544.           (widen) (erase-buffer)
  545.           (set-buffer cbuf)
  546.  
  547.           (and append
  548.            (not can-append)
  549.            (file-exists-p filename)
  550.            (let* ((local-copy (file-local-copy filename))
  551.               (local-file (or local-copy filename)))
  552.  
  553.              (unwind-protect
  554.  
  555.              (progn
  556.               
  557.                (and
  558.                 uncompress-message
  559.                 (message "%sing %s..." uncompress-message
  560.                      (file-name-nondirectory visit-file)))
  561.  
  562.                (jka-compr-call-process uncompress-program
  563.                            local-file
  564.                            temp-file
  565.                            temp-buffer
  566.                            must-discard-stderr
  567.                            uncompress-args)
  568.                (and
  569.                 uncompress-message
  570.                 (message "%sing %s...done" uncompress-message
  571.                      (file-name-nondirectory visit-file))))
  572.              
  573.                (and
  574.             local-copy
  575.             (file-exists-p local-copy)
  576.             (delete-file local-copy)))))
  577.  
  578.           (and 
  579.            compress-message
  580.            (message "%sing %s..." compress-message
  581.             (file-name-nondirectory visit-file)))
  582.  
  583.           (jka-compr-real-write-region start end temp-file t 'dont)
  584.  
  585.           (jka-compr-call-process compress-program
  586.                       temp-file
  587.                       temp-buffer
  588.                       nil
  589.                       must-discard-stderr
  590.                       compress-args)
  591.  
  592.           (set-buffer temp-buffer)
  593.           (jka-compr-real-write-region (point-min) (point-max)
  594.                        filename (and append can-append))
  595.           (erase-buffer)
  596.           (set-buffer cbuf)
  597.  
  598.           (delete-file temp-file)
  599.  
  600.           (and
  601.            compress-message
  602.            (message "%sing %s...done" compress-message
  603.             (file-name-nondirectory visit-file)))
  604.  
  605.           (cond
  606.            ((eq visit t)
  607.         (setq buffer-file-name zfile)
  608.         (set-buffer-modified-p nil)
  609.         (set-buffer-auto-saved)
  610.         (set-visited-file-modtime))
  611.            ((stringp visit)
  612.         (set-visited-file-name visit)
  613.         (set-buffer-modified-p nil)
  614.         (set-buffer-auto-saved)
  615.         (set-visited-file-modtime)))
  616.  
  617.           (and (or (eq visit t)
  618.                (eq visit nil)
  619.                (stringp visit))
  620.            (message "Wrote %s" visit-file))
  621.  
  622.           nil)
  623.           
  624.       (jka-compr-real-write-region start end filename append visit)))))
  625.    (t
  626.     (jka-compr-real-write-region start end file append visit))))
  627.  
  628.     (setq file-name-handler-alist
  629.       (cons jka-compr-file-name-handler-entry
  630.         file-name-handler-alist))))
  631.  
  632.  
  633. (defun jka-compr-insert-file-contents (filename &optional visit beg end)
  634.   "Documented as original."
  635.  
  636.   (unwind-protect
  637.       (progn
  638.     (setq file-name-handler-alist
  639.           (delq jka-compr-file-name-handler-entry
  640.             file-name-handler-alist))
  641.   (cond
  642.    (jka-compr-enabled
  643.  
  644.     (barf-if-buffer-read-only)
  645.  
  646.     (and (or beg end)
  647.      visit
  648.      (error "Attempt to visit less than an entire file"))
  649.  
  650.     (let* ((zfile (expand-file-name
  651.            (or (jka-compr-find-compressed-version filename)
  652.                filename)))
  653.        (info (jka-compr-get-compression-info zfile)))
  654.  
  655.       (if info
  656.  
  657.       (let ((magic (jka-compr-info-magic info))
  658.         (uncompress-message (jka-compr-info-uncompress-message info))
  659.         (uncompress-program (jka-compr-info-uncompress-program info))
  660.         (must-discard-stderr (jka-compr-info-uncompress-discard-err info))
  661.         (uncompress-args (jka-compr-info-uncompress-args info))
  662.         (temp-file (make-temp-name jka-compr-temp-name-template))
  663.         (notfound nil)
  664.         (local-copy (file-local-copy zfile))
  665.         local-file
  666.         size start)
  667.  
  668.         (setq local-file (or local-copy zfile))
  669.  
  670.         (unwind-protect        ; to make sure local-copy gets deleted
  671.  
  672.         (progn
  673.           
  674.           (and
  675.            uncompress-message
  676.            (message "%sing %s..." uncompress-message
  677.                 (file-name-nondirectory zfile)))
  678.  
  679.           (condition-case error-code
  680.  
  681.               (progn
  682.             (setq start (point))
  683.             (jka-compr-call-process uncompress-program
  684.                         local-file
  685.                         t
  686.                         nil
  687.                         must-discard-stderr
  688.                         uncompress-args)
  689.             (if end
  690.                 (delete-region (+ start end) (point)))
  691.             (if beg
  692.                 (delete-region start (+ start beg)))
  693.             (setq size (- (point) start))
  694.             (goto-char start))
  695.             
  696.             (error
  697.              (if (and (eq (car error-code) 'file-error)
  698.                   (eq (nth 3 error-code) local-file))
  699.              (if visit
  700.                  (setq notfound error-code)
  701.                (signal 'file-error 
  702.                    (cons "Openning input file"
  703.                      (nthcdr 2 error-code))))
  704.                (signal (car error-code) (cdr error-code))))))
  705.  
  706.           (and
  707.            local-copy
  708.            (file-exists-p local-copy)
  709.            (delete-file local-copy))
  710.  
  711.           (and
  712.            (file-exists-p temp-file)
  713.            (delete-file temp-file)))
  714.  
  715.                   
  716.         (and
  717.          visit
  718.          (progn
  719.            (setq buffer-file-name zfile)
  720.            ;;
  721.            (make-local-variable 'jka-compr-buffer-file-name)
  722.            (put 'jka-compr-buffer-file-name 'permanent-local t)
  723.            (setq jka-compr-buffer-file-name zfile)
  724.            ;;
  725.            (make-local-variable 'jka-compr-original-file-name)
  726.            (put 'jka-compr-original-file-name 'permanent-local t)
  727.            (setq jka-compr-original-fie-name (expand-file-name filename))
  728.            ;;
  729.            ;; this sets the save_modified field of the buffer
  730.            (set-buffer-modified-p nil)
  731.            ;; this sets the auto_save_modified and save_length of the buffer
  732.            (set-buffer-auto-saved)
  733.            ;; set the modtime of the buffer
  734.            (set-visited-file-modtime)))
  735.         
  736.         (and
  737.          uncompress-message
  738.          (message "%sing %s...done" uncompress-message
  739.               (file-name-nondirectory zfile)))
  740.  
  741.         (and
  742.          visit
  743.          notfound
  744.          (signal 'file-error
  745.              (cons "Openning input file" (nth 2 notfound))))
  746.  
  747.         (list zfile size))
  748.  
  749.     (jka-compr-real-insert-file-contents filename visit beg end))))
  750.    (t
  751.     (jka-compr-real-insert-file-contents filename visit beg end))))
  752.  
  753.     (setq file-name-handler-alist
  754.       (cons jka-compr-file-name-handler-entry
  755.         file-name-handler-alist))))
  756.     
  757.     
  758.  
  759.  
  760. ;;; This originally came from uncompress.el
  761. (defun jka-compr-find-compressed-version (filename)
  762.   "If FILENAME does not exist, try to find a compressed version.
  763. Return the version (extended filename) that is found.  If the file
  764. does not exist and no compressed versions are found, return nil."
  765.   (if (file-exists-p filename)
  766.       filename
  767.     (catch 'found-compressed-version
  768.       (mapcar
  769.        (function (lambda (cinfo)
  770.            (let ((extended-fname (concat filename (aref cinfo 11))))
  771.              (if (file-exists-p extended-fname)
  772.              (throw 'found-compressed-version extended-fname)))))
  773.        jka-compr-compression-info-list)
  774.       nil)))
  775.  
  776.  
  777.  
  778. ;;; There are probably many little functions like this that need to
  779. ;;; be defined.  These seem to to the job for info and rmail.
  780.  
  781. (defun jka-compr-file-readable-p (file)
  782.   "Documented as original."
  783.   (if jka-compr-enabled
  784.       (and 
  785.        (setq file (expand-file-name file))
  786.        (setq file (jka-compr-find-compressed-version file))
  787.        (file-readable-p file))
  788.     (file-readable-p file)))
  789.  
  790.  
  791. (defun jka-compr-file-writable-p (file)
  792.   "Documented as original."
  793.   (if jka-compr-enabled 
  794.       (let* ((efile (expand-file-name file))
  795.          (zfile (and efile (jka-compr-find-compressed-version efile))))
  796.     (if zfile
  797.         (file-writable-p zfile)
  798.       (file-directory-p (file-name-directory file))))
  799.     (file-writable-p file)))
  800.  
  801.  
  802. (defun jka-compr-verify-visited-file-modtime (buf)
  803.   "Documented as original."
  804.   (and
  805.    jka-compr-enabled
  806.    (not (file-exists-p (buffer-file-name buf)))
  807.    (let* ((bfile (buffer-file-name buf))
  808.       (efile (expand-file-name bfile))
  809.       (file  (and efile (jka-compr-find-compressed-version efile)))
  810.       (cbuf (current-buffer)))
  811.      
  812.      (and
  813.       (stringp file)
  814.       (not (string= file bfile))
  815.       (or (not jka-compr-verify-visited-file-change)
  816.       (yes-or-no-p
  817.        (format "Change visited file of buffer %s to %s? "
  818.            (buffer-name buf) file)))
  819.       (set-buffer buf)
  820.       (setq buffer-file-name file)
  821.       (set-buffer cbuf))))
  822.   (verify-visited-file-modtime buf))
  823.  
  824.  
  825. (defun jka-compr-file-symlink-p (file)
  826.   "Documented as original."
  827.   (if jka-compr-enabled
  828.       (and
  829.        (setq file (expand-file-name file))
  830.        (setq file (jka-compr-find-compressed-version file))
  831.        (file-symlink-p file))
  832.     (file-symlink-p file)))
  833.  
  834.  
  835. (defun jka-compr-file-attributes (file)
  836.   "Documented as original."
  837.   (if jka-compr-enabled
  838.       (and
  839.        (setq file (expand-file-name file))
  840.        (setq file (jka-compr-find-compressed-version file))
  841.        (file-attributes file))
  842.     (file-attributes file)))
  843.  
  844.  
  845. (defun jka-compr-file-exists-p (file)
  846.   "Documented as original."
  847.   (and jka-compr-enabled
  848.        (let ((efile (expand-file-name file)))
  849.      (or (and efile (jka-compr-find-compressed-version efile))
  850.          (file-exists-p file)))))
  851.  
  852.  
  853. (defun jka-compr-delete-file (file)
  854.   "Documented as original."
  855.   (if jka-compr-enabled
  856.       (let (zfile)
  857.     (setq file  (expand-file-name file)
  858.           zfile (or (and file (jka-compr-find-compressed-version file))
  859.             file))
  860.     (and
  861.      (or (string= zfile file)
  862.          (not jka-compr-verify-delete-file-change)
  863.          (yes-or-no-p (format "Delete file %s? "zfile)))
  864.      (delete-file zfile)))
  865.  
  866.     (delete-file file)))
  867.  
  868.  
  869. (defun jka-compr-get-file-buffer (file)
  870.   "Documented as original."
  871.   (if jka-compr-enabled
  872.       (or
  873.        (jka-compr-real-get-file-buffer file)
  874.        (and
  875.     (setq file (expand-file-name file))
  876.     (setq file (jka-compr-find-compressed-version file))
  877.     (jka-compr-real-get-file-buffer file)))
  878.     (jka-compr-real-get-file-buffer file)))
  879.  
  880.  
  881. (defun jka-compr-file-name-sans-versions (name &optional keep-backup-version)
  882.   "Documented as original."
  883.   ;; this function assumes that the regexps in jka-compr-compression-info-list
  884.   ;; will find .z extensions even if there are backup flags or version numbers
  885.   ;; attached.
  886.   (if jka-compr-enabled
  887.       (file-name-sans-versions name keep-backup-version)
  888.     (file-name-sans-versions name keep-backup-version)))
  889.  
  890.  
  891. (defun jka-compr-remove-compression-extension (name)
  892.   (catch 'name-sans-compress-extension
  893.     (mapcar
  894.      (function (lambda (x)
  895.          (if (string-match (aref x 0) name)
  896.              (throw 'name-sans-compress-extension 
  897.                 (substring name 0 (match-beginning 0))))))
  898.      jka-compr-compression-info-list)
  899.     name))
  900.  
  901.  
  902. (defun jka-compr-file-name-completion (file dir)
  903.   (let ((completions (file-name-all-completions file dir)))
  904.     (or
  905.      (try-completion
  906.       file
  907.       (mapcar
  908.        (function (lambda (x)
  909.            (list (jka-compr-remove-compression-extension x))))
  910.        completions))
  911.      (file-name-completion file dir))))
  912.  
  913.  
  914. (defun jka-compr-rename-file (file newname &optional noerror)
  915.   (let* ((efile (expand-file-name file))
  916.      (zfile (or (jka-compr-find-compressed-version efile)
  917.             efile))
  918.      info ext new)
  919.     (cond
  920.      ((string= efile zfile)
  921.       (rename-file zfile newname noerror))
  922.      (t
  923.       (setq info (jka-compr-get-compression-info zfile))
  924.       (setq ext (jka-compr-info-extension info))
  925.       (setq new (jka-compr-remove-compression-extension newname))
  926.       (rename-file zfile (concat new ext) noerror)))))
  927.  
  928.  
  929. (defun jka-compr-file-local-copy (filename)
  930.   "Documented as original."
  931.  
  932.   (cond
  933.    (jka-compr-enabled
  934.  
  935.     (setq filename (or (jka-compr-find-compressed-version filename)
  936.                filename))
  937.  
  938.     (let ((info (jka-compr-get-compression-info filename)))
  939.  
  940.       (if info
  941.  
  942.       (let ((magic (jka-compr-info-magic info))
  943.         (uncompress-message (jka-compr-info-uncompress-message info))
  944.         (uncompress-program (jka-compr-info-uncompress-program info))
  945.         (must-discard-stderr (jka-compr-info-uncompress-discard-err info))
  946.         (uncompress-args (jka-compr-info-uncompress-args info))
  947.         (local-copy (file-local-copy filename))
  948.         (temp-file (make-temp-name jka-compr-temp-name-template))
  949.         (temp-buffer (get-buffer-create " *jka-compr-temp*"))
  950.         (notfound nil)
  951.         (cbuf (current-buffer))
  952.         local-file)
  953.  
  954.         (setq local-file (or local-copy filename))
  955.  
  956.         (unwind-protect
  957.  
  958.         (progn
  959.           
  960.           (and
  961.            uncompress-message
  962.            (message "%sing %s..." uncompress-message
  963.                 (file-name-nondirectory filename)))
  964.  
  965.           (set-buffer temp-buffer)
  966.           
  967.           (jka-compr-call-process uncompress-program
  968.                       local-file
  969.                       t
  970.                       nil
  971.                       must-discard-stderr
  972.                       uncompress-args)
  973.  
  974.           (and
  975.            uncompress-message
  976.            (message "%sing %s...done" uncompress-message
  977.                 (file-name-nondirectory filename)))
  978.  
  979.           (jka-compr-real-write-region
  980.            (point-min) (point-max) temp-file nil 'dont))
  981.  
  982.           (and
  983.            local-copy
  984.            (file-exists-p local-copy)
  985.            (delete-file local-copy))
  986.  
  987.           (set-buffer cbuf)
  988.           (kill-buffer temp-buffer))
  989.  
  990.         temp-file)
  991.         
  992.     (file-local-copy filename))))
  993.  
  994.    (t
  995.     (file-local-copy filename))))
  996.  
  997.  
  998.  
  999. ;;; Support for loading compressed files.  This was originally part of
  1000. ;;; jka-compr.el.
  1001.  
  1002. (defvar jka-compr-lisp-file-extensions '(".elc" ".el" "")
  1003.   "List of extensions to try adding to emacs lisp load files.")
  1004.  
  1005.  
  1006. ;;; This is sort of like the openp routine in lread.c except there is
  1007. ;;; no exec_only arg and the suffix arg is a list instead of a string.
  1008. ;;; In fact, if the lisp code looks a little strange here its because
  1009. ;;; I pretty much transliterated the C version.
  1010. (defun jka-compr-openp (path str suffix)
  1011.   "Duplicate the function of the openp routing in lread.c."
  1012.   (catch 'result
  1013.     (let ((absolute (file-name-absolute-p str))
  1014.       filename suf try)
  1015.       (while path
  1016.     (catch 'continue
  1017.       (setq filename (expand-file-name str (car path)))
  1018.       (if (not (file-name-absolute-p filename))
  1019.           (progn
  1020.         (setq filename (expand-file-name str default-directory))
  1021.         (if (not (file-name-absolute-p filename))
  1022.             (throw 'continue nil))))
  1023.  
  1024.       (setq suf suffix)
  1025.       (while suf
  1026.         (setq try (concat filename (car suf)))
  1027.         (and (file-readable-p try)
  1028.          (not (file-directory-p try))
  1029.          (throw 'result try))
  1030.         (setq suf (cdr suf))))
  1031.  
  1032.     (if absolute
  1033.         (throw 'result nil)
  1034.       (setq path (cdr path)))))
  1035.  
  1036.     nil))
  1037.       
  1038.    
  1039. (defun jka-compr-load (file &optional noerror nomessage nosuffix)
  1040.   "Documented as original."
  1041.   (unwind-protect
  1042.       (progn
  1043.  
  1044.     (setq file-name-handler-alist
  1045.           (cons jka-compr-file-name-handler-entry
  1046.             file-name-handler-alist))
  1047.  
  1048.     (let ((filename
  1049.            (jka-compr-openp load-path file 
  1050.                 (if nosuffix
  1051.                     (cons "" nil)
  1052.                   jka-compr-lisp-file-extensions))))
  1053.       (if (not filename)
  1054.  
  1055.           (if noerror
  1056.           nil
  1057.         (error "Cannot open load file %s" file))
  1058.  
  1059.         (let ((cbuf (current-buffer))
  1060.           (lbufname (concat " *jka-load-temp:" filename))
  1061.           lbuf)
  1062.  
  1063.           (or nomessage
  1064.           (message "Loading %s..." file))
  1065.  
  1066.           (unwind-protect
  1067.           (progn
  1068.             (setq lbuf (get-buffer lbufname))
  1069.             (if lbuf
  1070.             (set-buffer lbuf)
  1071.               (setq lbuf (get-buffer-create lbufname))
  1072.               (set-buffer lbuf)
  1073.               (insert-file-contents filename))
  1074.             (set-buffer cbuf)
  1075.             (eval-buffer lbuf)
  1076.             (let ((after (assoc file after-load-alist)))
  1077.               (and
  1078.                after
  1079.                (apply 'progn (cdr after)))))
  1080.         (and
  1081.          lbuf
  1082.          (kill-buffer lbuf)))
  1083.  
  1084.           (or nomessage
  1085.           (message "Loading %s...done." file))))))
  1086.  
  1087.     (setq file-name-handler-alist
  1088.       (delq jka-compr-file-name-handler-entry
  1089.         file-name-handler-alist))))
  1090.  
  1091.  
  1092. (defun jka-compr-file-truename (filename)
  1093.   (let ((zfile (or (jka-compr-find-compressed-version filename)
  1094.            filename)))
  1095.     (file-truename zfile)))
  1096.  
  1097.  
  1098. (defvar jka-compr-file-name-handler-entry
  1099.   (cons "[^#]\\'" 'jka-compr-handler)
  1100.   "The entry in file-name-handler-alist used by the jka-compr I/O functions.")
  1101.  
  1102.  
  1103. (defun jka-compr-handler (operation &rest args)
  1104.  
  1105.   (let ((jka-op (intern-soft (symbol-name operation) jka-compr-op-table)))
  1106.  
  1107.     (unwind-protect
  1108.     (progn
  1109.       (setq file-name-handler-alist
  1110.         (delq jka-compr-file-name-handler-entry
  1111.               file-name-handler-alist))
  1112.       (if jka-op
  1113.           (apply jka-op args)
  1114.         (apply operation args)))
  1115.  
  1116.       (setq file-name-handler-alist
  1117.         (cons jka-compr-file-name-handler-entry
  1118.           file-name-handler-alist)))))
  1119.  
  1120.   
  1121. (defvar jka-compr-op-table
  1122.   (make-vector 127 0))
  1123.  
  1124.  
  1125. (defun jka-compr-intern-operation (op)
  1126.   (let ((opsym (intern (symbol-name op) jka-compr-op-table))
  1127.     (jka-fn (intern (concat "jka-compr-" (symbol-name op)))))
  1128.     (fset opsym jka-fn)))
  1129.  
  1130.  
  1131. (defvar jka-compr-operation-list
  1132.   '(
  1133. ;;; write-region
  1134. ;;; insert-file-contents
  1135.     file-readable-p
  1136.     file-writable-p
  1137.     file-symlink-p
  1138.     file-attributes
  1139.     file-exists-p
  1140.     delete-file
  1141.     get-file-buffer
  1142.     file-name-sans-versions
  1143.     file-name-completion
  1144.     verify-visited-file-modtime
  1145.     file-local-copy
  1146.     rename-file
  1147.     file-truename
  1148.     load
  1149.     )
  1150.   "List of file operations implemented by jka-compr.")
  1151.  
  1152.  
  1153. (mapcar
  1154.  (function
  1155.   (lambda (fn)
  1156.     (jka-compr-intern-operation fn)))
  1157.  jka-compr-operation-list)
  1158.  
  1159.  
  1160. (defun jka-compr-handler-installed ()
  1161.   (let ((fnha file-name-handler-alist))
  1162.     (catch 'installed
  1163.       (while fnha
  1164.     (and (eq (cdr (car fnha)) 'jka-compr-handler)
  1165.          (throw 'installed (car fnha)))
  1166.     (setq fnha (cdr fnha)))
  1167.       nil)))
  1168.  
  1169.       
  1170. ;;; Add the file I/O hook if it does not already exist.
  1171. ;;; Make sure that jka-compr-file-name-handler-entry is eq to the
  1172. ;;; entry for jka-compr in file-name-handler-alist.
  1173. (let ((alist-entry (jka-compr-handler-installed)))
  1174.   (if alist-entry
  1175.       (setq jka-compr-file-name-handler-entry alist-entry)
  1176.     (setq file-name-handler-alist
  1177.       (cons jka-compr-file-name-handler-entry
  1178.         file-name-handler-alist))))
  1179.  
  1180.  
  1181. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1182. ;;;
  1183. ;;; Emacs bug workarounds.
  1184. ;;;
  1185.  
  1186. ;;; This function was lifted from ange-ftp.  I added some args to make
  1187. ;;; it a little more general. - jka
  1188. (defun jka-compr-overwrite-fn (fun saved-prefix new-prefix overwrite-msg)
  1189.   "Replace FUN's function definition with NEW-PREFIX-FUN's, saving the
  1190. original definition as SAVED-PREFIX-FUN.  The original documentation is
  1191. placed on the new definition suitably augmented.  Third arg, OVERWRITE-MSG,
  1192. is tacked on to the doc string of the new fun."
  1193.  
  1194.   (let* ((name (symbol-name fun))
  1195.      (saved (intern (concat saved-prefix name)))
  1196.      (new (intern (concat new-prefix name)))
  1197.      (nfun (symbol-function new))
  1198.      (exec-directory (if (or (equal (nth 3 command-line-args) "dump")
  1199.                  (equal (nth 4 command-line-args) "dump"))
  1200.                  "../etc/"
  1201.                exec-directory)))             
  1202.     
  1203.     (while (symbolp nfun)
  1204.       (setq nfun (symbol-function nfun)))
  1205.     
  1206.     (or (fboundp saved)
  1207.     (progn
  1208.       (fset saved (symbol-function fun))
  1209.       (fset fun new)))
  1210.     
  1211.     (let* ((doc-str (jka-compr-safe-documentation saved))
  1212.        (ndoc-str (concat doc-str (and doc-str "\n")
  1213.                  overwrite-msg)))
  1214.       
  1215.       (cond ((listp nfun)
  1216.          ;; Probe to test whether function is in preloaded read-only
  1217.          ;; memory, and if so make writable copy:
  1218.          (condition-case nil
  1219.          (setcar nfun (car nfun))
  1220.            (error
  1221.         (setq nfun (copy-sequence nfun)) ; shallow copy only
  1222.         (fset new nfun)))
  1223.          (let ((ndoc-cdr (nthcdr 2 nfun)))
  1224.            (if (stringp (car ndoc-cdr))
  1225.            ;; Replace the existing docstring.
  1226.            (setcar ndoc-cdr ndoc-str)
  1227.          ;; There is no docstring.  Insert the overwrite msg.
  1228.          (setcdr ndoc-cdr (cons (car ndoc-cdr) (cdr ndoc-cdr)))
  1229.          (setcar ndoc-cdr overwrite-msg))))
  1230.         (t
  1231.          ;; it's an emacs19 compiled-code object
  1232.          (let ((new-code (append nfun nil))) ; turn it into a list
  1233.            (if (nthcdr 4 new-code)
  1234.            (setcar (nthcdr 4 new-code) ndoc-str)
  1235.          (setcdr (nthcdr 3 new-code) (cons ndoc-str nil)))
  1236.            (fset new (apply 'make-byte-code new-code))))))))
  1237.  
  1238.  
  1239. (defun jka-compr-safe-documentation (fun)
  1240.   "A documentation function that isn't quite as fragile."
  1241.   (condition-case ()
  1242.       (documentation fun)
  1243.     (error nil)))
  1244.  
  1245.  
  1246. ;;; Still have to do get-file-buffer the old way...
  1247. (jka-compr-overwrite-fn
  1248.  'get-file-buffer
  1249.  "jka-compr-real-" "jka-compr-"
  1250.  "Note: This function has been modified to work with jka-compr.")
  1251.  
  1252. (jka-compr-overwrite-fn
  1253.  'write-region
  1254.  "jka-compr-real-" "jka-compr-"
  1255.  "Note: This function has been modified by jka-compr to work around an emacs bug.")
  1256.  
  1257. (jka-compr-overwrite-fn
  1258.  'insert-file-contents
  1259.  "jka-compr-real-" "jka-compr-"
  1260.  "Note: This function has been modified by jka-compr to work around an emacsb ug.")
  1261.  
  1262.  
  1263. (provide 'jka-compr)
  1264.  
  1265.