home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1993 #1 / NN_1993_1.iso / spool / comp / emacs / 3955 < prev    next >
Encoding:
Text File  |  1993-01-12  |  20.8 KB  |  981 lines

  1. Path: sparky!uunet!zaphod.mps.ohio-state.edu!cs.utexas.edu!torn!nott!cunews!revcan!software.mitel.com!sharman!sharman
  2. From: sharman@Software.Mitel.COM (Richard Sharman)
  3. Newsgroups: comp.emacs
  4. Subject: Re: find-file-maybe-uncompress? (for Gnu under unix)
  5. Message-ID: <SHARMAN.93Jan12104154@sharman.Software.Mitel.COM>
  6. Date: 12 Jan 93 15:41:54 GMT
  7. References: <lkolp9INNhg1@bathtub.cs.utexas.edu>
  8. Sender: sharman@Software.Mitel.COM
  9. Organization: Mitel. Kanata (Ontario). Canada.
  10. Lines: 968
  11. In-reply-to: schrag@cs.utexas.edu's message of 7 Jan 93 16:15:37 GMT
  12.  
  13.  
  14.    Does anybody have a version of find-file (or find-file-noselect) that
  15.    will automatically uncompress the file, if it has the .Z suffix?
  16.  
  17. We have this behaviour at our site by the use of Kyle Jones's "crypt"
  18. package. By simply having this file in a directory on the emacs load
  19. path and putting (require 'crypt) in your ~/.emacs file will do what
  20. you requested.    (Thanks Kyle, it's *very* handy.)
  21.  
  22. ;From ark1!nems!mimsy!tank!ux1.cso.uiuc.edu!brutus.cs.uiuc.edu!uakari.primate.wisc.edu!uwm.edu!bionet!rutgers!mcnc!rti!talos!kjones Thu Jan 11 09:53:07 1990
  23. ;Article 1163 of comp.emacs:
  24. ;Xref: ark1 comp.emacs:1163 gnu.emacs:948
  25. ;Path: ark1!nems!mimsy!tank!ux1.cso.uiuc.edu!brutus.cs.uiuc.edu!uakari.primate.wisc.edu!uwm.edu!bionet!rutgers!mcnc!rti!talos!kjones
  26. ;>From kjones@talos.uu.net (Kyle Jones)
  27. ;Newsgroups: comp.emacs,gnu.emacs,alt.sources
  28. ;Subject: crypt.el for GNU Emacs
  29. ;Message-ID: <1990Jan9.175837.25058@talos.uu.net>
  30. ;Date: 9 Jan 90 17:58:37 GMT
  31. ;Lines: 476
  32.  
  33. ;;; Compaction, compression and encryption for GNU Emacs
  34. ;;; Copyright (C) 1988, 1989, 1990 Kyle E. Jones
  35. ;;;
  36. ;;; This program is free software; you can redistribute it and/or modify
  37. ;;; it under the terms of the GNU General Public License as published by
  38. ;;; the Free Software Foundation; either version 1, or (at your option)
  39. ;;; any later version.
  40. ;;;
  41. ;;; This program is distributed in the hope that it will be useful,
  42. ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  43. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  44. ;;; GNU General Public License for more details.
  45. ;;;
  46. ;;; A copy of the GNU General Public License can be obtained from this
  47. ;;; program's author (send electronic mail to kyle@cs.odu.edu) or from
  48. ;;; the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
  49. ;;; 02139, USA.
  50. ;;;
  51. ;;; Send bug reports to kyle@cs.odu.edu.
  52.  
  53. ;; To use this package, put it in a file called "crypt.el" in a Lisp
  54. ;; directory that Emacs knows about, byte-compile it, and put the line:
  55. ;;    (require 'crypt)
  56. ;; in your .emacs file or in the file default.el in the "lisp" directory
  57. ;; of the Emacs distribution.  Don't bother trying to autoload this file;
  58. ;; this package uses a find-file hook and thus should be loaded the
  59. ;; first time you visit any sort of file.
  60. ;;
  61. ;; The basic purpose of this package of Lisp functions is to automatically
  62. ;; recognize encrypted, compacted or compressed files when they are first
  63. ;; visited and decode the file's BUFFER before it is presented to the user.
  64. ;; The file itself is unchanged.  When the buffer is subsequently saved to
  65. ;; disk, a hook function re-encodes the buffer before the actual disk write
  66. ;; takes place.
  67. ;;
  68. ;; This package recognizes compacted and compressed files by a magic number at
  69. ;; the beginning of these files, but a heuristic is used to detect encrypted
  70. ;; files.  If you are asked for an encryption key for a file that is in fact
  71. ;; not encrypted, just hit RET and the file will be accepted as is, and the
  72. ;; crypt minor mode will not be entered.
  73.  
  74. (provide 'crypt)
  75.  
  76. (defvar auto-decode-buffer t
  77.   "*Non-nil value means that the buffers associated with encoded files will
  78. be decoded automatically, without requesting confirmation from the user.
  79. Nil means to ask before doing the decoding.")
  80.  
  81. (defvar buffer-save-encrypted nil
  82.   "*Non-nil means that when this buffer is saved it will be written out
  83. encrypted, as with the UNIX crypt(1) command.  Automatically local to all
  84. buffers.")
  85. (make-variable-buffer-local 'buffer-save-encrypted)
  86.  
  87. (defvar buffer-save-compacted nil
  88.   "*Non-nil means that when this buffer is saved it will be written out
  89. compacted, as with the UNIX compact(1) command.  Automatically local to all
  90. buffers.")
  91. (make-variable-buffer-local 'buffer-save-compacted)
  92.  
  93. (defvar buffer-save-compressed nil
  94.   "*Non-nil means that when this buffer is saved it will be written out
  95. compressed, as with the UNIX compress(1) command.  Automatically local to all
  96. buffers.")
  97. (make-variable-buffer-local 'buffer-save-compressed)
  98.  
  99. (defvar buffer-encryption-key nil
  100.   "*Key to use when encrypting the current buffer, prior to saving it.
  101. Automatically local to all buffers.")
  102. (make-variable-buffer-local 'buffer-encryption-key)
  103.  
  104. (defconst compact-magic-regexp "\377\037"
  105.   "Regexp that matches the magic number at the beginning of files created
  106. by the compact(1) command.")
  107.  
  108. (defconst compress-magic-regexp "\037\235\220"
  109.   "Regexp that matches the magic number at the beginning of files created
  110. by the compress(1) command.")
  111.  
  112. ;; Encrypted files have no magic number, so we have to hack a way of
  113. ;; determining which new buffers start in crypt mode.  The current setup is
  114. ;; that we use only buffers that have a non-ASCII character very close to
  115. ;; beginning of buffer and that do NOT match crypt-magic-regexp-inverse.
  116. ;; Currently crypt-magic-regexp-inverse will match Sun OS, 4.x BSD, and
  117. ;; Ultrix executable magic numbers, so binaries can still be edited (heh)
  118. ;; without headaches.
  119.  
  120. (defconst crypt-magic-regexp-inverse
  121.   "\\(..\\)?\\([\007\010\013]\001\\|\001[\007\010\013]\\)"
  122.   "Regexp that must NOT match the beginning of an encrypted buffer.")
  123.  
  124.  
  125.  
  126.  
  127.  
  128.  
  129.  
  130.  
  131.  
  132.  
  133.  
  134.  
  135.  
  136.  
  137.  
  138.  
  139.  
  140.  
  141.  
  142.  
  143.  
  144.  
  145.  
  146.  
  147.  
  148.  
  149.  
  150.  
  151.  
  152.  
  153.  
  154.  
  155.  
  156.  
  157.  
  158.  
  159.  
  160.  
  161.  
  162.  
  163.  
  164.  
  165.  
  166.  
  167.  
  168.  
  169.  
  170.  
  171.  
  172.  
  173.  
  174.  
  175.  
  176.  
  177.  
  178.  
  179.  
  180.  
  181.  
  182.  
  183. (defmacro save-point (&rest body)
  184.   "Save value of point, evalutes FORMS and restore value of point.
  185. If the saved value of point is no longer valid go to (point-max).
  186. This macro exists because, save-excursion loses track of point during
  187. some types of deletions."
  188.   (let ((var (make-symbol "saved-point")))
  189.     (list 'let (list (list var '(point)))
  190.       (list 'unwind-protect
  191.         (cons 'progn body)
  192.         (list 'goto-char var)))))
  193.  
  194.  
  195.  
  196.  
  197.  
  198.  
  199.  
  200.  
  201.  
  202.  
  203.  
  204.  
  205.  
  206.  
  207.  
  208.  
  209.  
  210.  
  211.  
  212.  
  213.  
  214.  
  215.  
  216.  
  217.  
  218.  
  219.  
  220.  
  221.  
  222.  
  223.  
  224.  
  225.  
  226.  
  227.  
  228.  
  229.  
  230.  
  231.  
  232.  
  233.  
  234.  
  235.  
  236.  
  237.  
  238.  
  239.  
  240.  
  241.  
  242.  
  243.  
  244.  
  245.  
  246.  
  247.  
  248.  
  249.  
  250.  
  251.  
  252.  
  253. (defun find-crypt-file-hook ()
  254.   (save-point
  255.     (save-restriction
  256.       (widen)
  257.       (goto-char (point-min))
  258.       (let ((buffer-file-name buffer-file-name)
  259.         (old-buffer-file-name buffer-file-name)
  260.         (old-buffer-modified-p (buffer-modified-p))
  261.         encrypted compressed compacted case-fold-search buffer-read-only)
  262.     ;; We can reasonably assume that either compaction or compression will
  263.     ;; be used, or neither, but not both.
  264.     (cond ((and (looking-at compact-magic-regexp)
  265.             (or auto-decode-buffer
  266.             (y-or-n-p (format "Uncompact buffer %s? "
  267.                       (buffer-name)))))
  268.            (message "Uncompacting %s..." (buffer-name))
  269.            (compact-buffer (current-buffer) t)
  270.            ;; We can't actually go into compact mode yet because the major
  271.            ;; mode may change later on and blow away all local variables
  272.            ;; (and thus the minor modes).  So we make a note to go into
  273.            ;; compact mode later.
  274.            (setq compacted t)
  275.            ;; here we strip the compacted file's .C extension so that later
  276.            ;; we can set the buffer's major mode based on this modified
  277.            ;; name instead of the name with the .C extension.
  278.            (if (string-match "\\(\\.C\\)$" buffer-file-name)
  279.            (setq buffer-file-name
  280.              (substring buffer-file-name 0 (match-beginning 1))))
  281.            (if (not (input-pending-p))
  282.            (message "Uncompacting %s... done" (buffer-name))))
  283.           ((and (looking-at compress-magic-regexp)
  284.             (or auto-decode-buffer
  285.             (y-or-n-p (format "Uncompress buffer %s? "
  286.                       (buffer-name)))))
  287.            (message "Uncompressing %s..." (buffer-name))
  288.            (compress-buffer (current-buffer) t)
  289.            (setq compressed t)
  290.            (if (string-match "\\(\\.Z\\)$" buffer-file-name)
  291.            (setq buffer-file-name
  292.              (substring buffer-file-name 0 (match-beginning 1))))
  293.            (if (not (input-pending-p))
  294.            (message "Uncompressing %s... done" (buffer-name)))))
  295.     ;; Now peek at the file and see if it still looks like a binary file.
  296.     ;; If so, try the crypt-magic-regexp-inverse against it and if it FAILS
  297.     ;; we assume that this is an encrypted buffer.
  298.     (cond ((and (not (eobp))
  299.             (re-search-forward "[\200-\377]" (min (point-max) 15) t)
  300.             (goto-char (point-min))
  301.             (not (looking-at crypt-magic-regexp-inverse)))
  302.            (if (not buffer-encryption-key)
  303.            (call-interactively 'set-encryption-key))
  304.            ;; if user did not enter a key, turn off crypt mode.
  305.            ;; good for binaries that crypt-magic-regexp-inverse
  306.            ;; doesn't recognize.
  307.            ;; -- thanx to Paul Dworkin (paul@media-lab.media.mit.edu)
  308.            (if (equal buffer-encryption-key "")
  309.            (message "No key given, buffer %s assumed normal."
  310.                 (buffer-name))
  311.          (message "Decrypting %s..." (buffer-name))
  312.          (crypt-buffer buffer-encryption-key)
  313.          ;; Tuck the key away for safe keeping since setting the major
  314.          ;; mode may well blow it away.
  315.          (setq encrypted buffer-encryption-key)
  316.          (if (not (input-pending-p))
  317.              (message "Decrypting %s... done" (buffer-name))))))
  318.     ;; OK, if any changes have been made to the buffer we need to rerun the
  319.     ;; code the does automatic selection of major mode.
  320.     (cond ((or compressed compacted encrypted)
  321.            (set-auto-mode)
  322.            (hack-local-variables)
  323.            ;; Now set our minor modes.
  324.            (if compressed (compress-mode 1))
  325.            (if compacted (compact-mode 1))
  326.            (if encrypted
  327.            (progn (crypt-mode 1)
  328.               (setq buffer-encryption-key encrypted)))
  329.            ;; Restore buffer file name now, so that lock file entry is
  330.            ;; removed properly.
  331.            (setq buffer-file-name old-buffer-file-name)
  332.            ;; Restore buffer modified flag to its previous value.
  333.            ;; This will also remove the lock file entry for the buffer
  334.            ;; if the previous value was nil; this is why buffer-file-name
  335.            ;; had to be manually restored above.
  336.            (set-buffer-modified-p old-buffer-modified-p)))))))
  337.  
  338. ;; This function should be called ONLY as a write-file hook.
  339. ;; Odd things will happen if it is called elsewhere.
  340. (defun write-crypt-file-hook ()
  341.   (cond
  342.    ((or buffer-save-encrypted buffer-save-compacted buffer-save-compressed)
  343.     (save-excursion
  344.       (save-restriction
  345.     (let ((copy-buffer (get-buffer-create " *crypt copy buffer*"))
  346.           (selective-display selective-display)
  347.           (buffer-read-only))
  348.       (copy-to-buffer copy-buffer 1 (1+ (buffer-size)))
  349.       (narrow-to-region (point) (point))
  350.       (unwind-protect
  351.           (progn
  352.         (insert-buffer-substring copy-buffer)
  353.         (kill-buffer copy-buffer)
  354.         ;; selective-display non-nil means we must convert carriage
  355.         ;; returns to newlines now, and set selective-display
  356.         ;; temporarily to nil.
  357.         (cond (selective-display
  358.                (goto-char (point-min))
  359.                (subst-char-in-region (point-min) (point-max) ?\r ?\n)
  360.                (setq selective-display nil)))
  361.         (cond
  362.          (buffer-save-encrypted
  363.           (if (null buffer-encryption-key)
  364.               (error "No encryption key set for buffer %s"
  365.                  (buffer-name)))
  366.           (if (not (stringp buffer-encryption-key))
  367.               (error "Encryption key is not a string"))
  368.           (message "Encrypting %s..." (buffer-name))
  369.           (crypt-buffer buffer-encryption-key)))
  370.         (cond
  371.          ((and buffer-save-compacted buffer-save-compressed)
  372.           (error "Cannot compact and compress buffer %s"
  373.              (buffer-name)))
  374.          (buffer-save-compacted
  375.           (message "Compacting %s..." (buffer-name))
  376.           (compact-buffer))
  377.          (buffer-save-compressed
  378.           (message "Compressing %s..." (buffer-name))
  379.           (compress-buffer)))
  380.         (write-region (point-min) (point-max) buffer-file-name nil t)
  381.         (delete-region (point-min) (point-max))
  382.         (set-buffer-modified-p nil)
  383.         ;; return t so that basic-save-buffer will
  384.         ;; know that the save has already been done.
  385.         t )
  386.         ;; unwind...
  387.         ;; If the crypted stuff has already been removed
  388.         ;; then this is a no-op.
  389.         (delete-region (point-min) (point-max)))))))))
  390.  
  391.  
  392.  
  393.  
  394.  
  395.  
  396.  
  397.  
  398.  
  399.  
  400.  
  401.  
  402.  
  403.  
  404.  
  405.  
  406.  
  407.  
  408.  
  409.  
  410.  
  411.  
  412.  
  413.  
  414.  
  415.  
  416.  
  417.  
  418.  
  419.  
  420.  
  421.  
  422.  
  423.  
  424.  
  425.  
  426.  
  427.  
  428.  
  429.  
  430.  
  431.  
  432.  
  433.  
  434.  
  435.  
  436.  
  437.  
  438.  
  439.  
  440.  
  441.  
  442.  
  443.  
  444.  
  445.  
  446.  
  447.  
  448.  
  449.  
  450. (defun crypt-region (start end key)
  451.   "Encrypt/decrypt the text in the region.
  452. From a program, this function takes three args: START, END and KEY.
  453. When called interactively START and END default to point and mark
  454. \(START being the lesser of the two), KEY is prompted for."
  455.   (interactive
  456.    (progn
  457.      (barf-if-buffer-read-only)
  458.      (list
  459.       (region-beginning)
  460.       (region-end)
  461.       (read-string-no-echo "Crypt region using key: "))))
  462.   (save-point
  463.    (let ((opoint-max (point-max)))
  464.      (call-process-region start end shell-file-name t t nil "-c"
  465.               (concat "crypt \"" key "\""))
  466.      (if (not (= opoint-max (point-max)))
  467.      (error "crypt command failed!")))))
  468.  
  469. (defun crypt-buffer (key &optional buffer)
  470.   "Using KEY, encrypt/decrypt BUFFER.
  471. BUFFER defaults to the current buffer."
  472.   (interactive
  473.    (progn
  474.      (barf-if-buffer-read-only)
  475.      (list (read-string-no-echo "Crypt buffer using key: "))))
  476.   (or buffer (setq buffer (current-buffer)))
  477.   (save-excursion
  478.     (set-buffer buffer)
  479.     (crypt-region (point-min) (point-max) key)))
  480.  
  481.  
  482.  
  483.  
  484.  
  485.  
  486.  
  487.  
  488.  
  489.  
  490.  
  491.  
  492.  
  493.  
  494.  
  495.  
  496.  
  497.  
  498.  
  499.  
  500.  
  501.  
  502.  
  503.  
  504.  
  505.  
  506.  
  507.  
  508.  
  509.  
  510.  
  511.  
  512.  
  513.  
  514.  
  515.  
  516.  
  517.  
  518.  
  519.  
  520.  
  521.  
  522.  
  523.  
  524.  
  525.  
  526.  
  527.  
  528.  
  529.  
  530.  
  531.  
  532.  
  533.  
  534.  
  535.  
  536.  
  537.  
  538.  
  539.  
  540. (defun compact-region (start end &optional undo)
  541.   "Compact the text in the region.
  542. From a program, this function takes three args: START, END and UNDO.
  543. When called interactively START and END default to point and mark
  544. \(START being the lesser of the two).
  545. Prefix arg (or optional second arg non-nil) UNDO means uncompact."
  546.   (interactive "*r\nP")
  547.   (save-point
  548.    (call-process-region start end shell-file-name t t nil "-c"
  549.             (if undo "uncompact" "compact"))
  550.    (cond ((not undo)
  551.       (goto-char start)
  552.       (let (case-fold-search)
  553.         (if (not (looking-at compact-magic-regexp))
  554.         (error "%s failed!" (if undo
  555.                     "Uncompaction"
  556.                       "Compaction"))))))))
  557.  
  558. (defun compact-buffer (&optional buffer undo)
  559.   "Compact BUFFER.
  560. BUFFER defaults to the current buffer.
  561. Prefix arg (or second arg non-nil from a program) UNDO means uncompact."
  562.   (interactive (list (current-buffer) current-prefix-arg))
  563.   (or buffer (setq buffer (current-buffer)))
  564.   (save-excursion
  565.     (set-buffer buffer)
  566.     (compact-region (point-min) (point-max) undo)))
  567.  
  568.  
  569.  
  570.  
  571.  
  572.  
  573.  
  574.  
  575.  
  576.  
  577.  
  578.  
  579.  
  580.  
  581.  
  582.  
  583.  
  584.  
  585.  
  586.  
  587.  
  588.  
  589.  
  590.  
  591.  
  592.  
  593.  
  594.  
  595.  
  596.  
  597.  
  598.  
  599.  
  600.  
  601.  
  602.  
  603.  
  604.  
  605.  
  606.  
  607.  
  608.  
  609.  
  610.  
  611.  
  612.  
  613.  
  614.  
  615.  
  616.  
  617.  
  618.  
  619.  
  620.  
  621.  
  622.  
  623.  
  624.  
  625.  
  626.  
  627. (defun compress-region (start end &optional undo)
  628.   "Compress the text in the region.
  629. From a program, this function takes three args: START, END and UNDO.
  630. When called interactively START and END default to point and mark
  631. \(START being the lesser of the two).
  632. Prefix arg (or optional second arg non-nil) UNDO means uncompress."
  633.   (interactive "*r\nP")
  634.   (save-point
  635.    (call-process-region start end shell-file-name t t nil "-c"
  636.             (if undo "compress -d" "compress"))
  637.    (cond ((not undo)
  638.       (goto-char start)
  639.       (let (case-fold-search)
  640.         (if (not (looking-at compress-magic-regexp))
  641.         (error "%s failed!" (if undo
  642.                     "Uncompression"
  643.                       "Compression"))))))))
  644.  
  645. (defun compress-buffer (&optional buffer undo)
  646.   "Compress BUFFER.
  647. BUFFER defaults to the current buffer.
  648. Prefix arg (or second arg non-nil from a program) UNDO means uncompress."
  649.   (interactive (list (current-buffer) current-prefix-arg))
  650.   (or buffer (setq buffer (current-buffer)))
  651.   (save-excursion
  652.     (set-buffer buffer)
  653.     (compress-region (point-min) (point-max) undo)))
  654.  
  655.  
  656.  
  657.  
  658.  
  659.  
  660.  
  661.  
  662.  
  663.  
  664.  
  665.  
  666.  
  667.  
  668.  
  669.  
  670.  
  671.  
  672.  
  673.  
  674.  
  675.  
  676.  
  677.  
  678.  
  679.  
  680.  
  681.  
  682.  
  683.  
  684.  
  685.  
  686.  
  687.  
  688.  
  689.  
  690.  
  691.  
  692.  
  693.  
  694.  
  695.  
  696.  
  697.  
  698.  
  699.  
  700.  
  701.  
  702.  
  703.  
  704.  
  705.  
  706.  
  707.  
  708.  
  709.  
  710.  
  711.  
  712.  
  713.  
  714. (defun set-encryption-key (key &optional buffer)
  715.   "Set the encryption KEY for BUFFER.
  716. KEY should be a string.
  717. BUFFER should be a buffer or the name of one;
  718. it defaults to the current buffer.  If BUFFER is in crypt mode, then it is
  719. also marked as modified, since it needs to be saved with the new key."
  720.   (interactive
  721.    (progn
  722.      (barf-if-buffer-read-only)
  723.      (list
  724.       (read-string-no-echo
  725.        (format "Set encryption key for buffer %s: " (buffer-name))))))
  726.   (or buffer (setq buffer (current-buffer)))
  727.   (save-excursion
  728.     (set-buffer buffer)
  729.     (if (equal key buffer-encryption-key)
  730.     (message "Key is identical to original, no change.")
  731.       (setq buffer-encryption-key key)
  732.       ;; don't touch the modify flag unless we're in crypt-mode.
  733.       (if buffer-save-encrypted
  734.       (set-buffer-modified-p t)))))
  735.  
  736. (defun crypt-mode (&optional arg)
  737.   "Toggle crypt mode.
  738. With arg, turn crypt mode on iff arg is positive, otherwise turn it off.
  739. In crypt mode, buffers are automatically encrypted before being written.
  740. If crypt mode is toggled and a key has been set for the current buffer, then
  741. the current buffer is marked modified, since it needs to be rewritten
  742. with (or without) encryption.
  743.  
  744. Use \\[set-encryption-key] to set the encryption key for the current buffer.
  745.  
  746. Entering crypt mode causes auto-saving to be turned off in the current buffer,
  747. as there is no way (in Emacs Lisp) to force auto save files to be encrypted."
  748.   (interactive "P")
  749.   (let ((oldval buffer-save-encrypted))
  750.     (setq buffer-save-encrypted
  751.       (if arg (> arg 0) (not buffer-save-encrypted)))
  752.     (if buffer-save-encrypted
  753.     (auto-save-mode 0)
  754.       (auto-save-mode (if (and auto-save-default buffer-file-name) 1 0)))
  755.     (if buffer-encryption-key
  756.     (set-buffer-modified-p
  757.      (not (eq oldval buffer-save-encrypted))))))
  758.  
  759. (defun compact-mode (&optional arg)
  760.   "Toggle compact mode.
  761. With arg, turn compact mode on iff arg is positive, otherwise turn it off.
  762. In compact mode, buffers are automatically compacted before being written.
  763. If compact mode is toggled, the current buffer is marked modified, since
  764. it needs to be written with (or without) compaction.
  765.  
  766. Entering compact mode causes auto-saving to be turned off in the current
  767. buffer, as there is no way (in Emacs Lisp) to force auto save files to be
  768. compacted."
  769.   (interactive "P")
  770.   (let ((oldval buffer-save-compacted))
  771.     (setq buffer-save-compacted
  772.       (if arg (> arg 0) (not buffer-save-compacted)))
  773.     (if buffer-save-compacted
  774.     (auto-save-mode 0)
  775.       (auto-save-mode (if (and auto-save-default buffer-file-name) 1 0)))
  776.     (set-buffer-modified-p (not (eq oldval buffer-save-compacted)))))
  777.  
  778. (defun compress-mode (&optional arg)
  779.   "Toggle compress mode.
  780. With arg, turn compress mode on iff arg is positive, otherwise turn it off.
  781. In compress mode, buffers are automatically compressed before being written.
  782. If compress mode is toggled, the current buffer is marked modified, since
  783. it needs to be written with (or without) compression.
  784.  
  785. Entering compress mode causes auto-saving to be turned off in the current
  786. buffer, as there is no way (in Emacs Lisp) to force auto save files to be
  787. compressed."
  788.   (interactive "P")
  789.   (let ((oldval buffer-save-compressed))
  790.     (setq buffer-save-compressed
  791.       (if arg (> arg 0) (not buffer-save-compressed)))
  792.     (if buffer-save-compressed
  793.     (auto-save-mode 0)
  794.       (auto-save-mode (if (and auto-save-default buffer-file-name) 1 0)))
  795.     (set-buffer-modified-p (not (eq oldval buffer-save-compressed)))))
  796.  
  797.  
  798.  
  799.  
  800.  
  801.  
  802.  
  803.  
  804.  
  805.  
  806.  
  807.  
  808.  
  809.  
  810.  
  811.  
  812.  
  813.  
  814.  
  815.  
  816.  
  817.  
  818.  
  819.  
  820.  
  821.  
  822.  
  823.  
  824.  
  825.  
  826.  
  827.  
  828.  
  829.  
  830.  
  831.  
  832.  
  833.  
  834.  
  835.  
  836.  
  837.  
  838.  
  839.  
  840.  
  841.  
  842.  
  843.  
  844.  
  845.  
  846.  
  847.  
  848.  
  849.  
  850.  
  851.  
  852.  
  853.  
  854.  
  855.  
  856. (defun read-string-no-echo (prompt &optional confirm)
  857.   "Read a string from the minibuffer, prompting with PROMPT.
  858. Optional second argument CONFIRM non-nil means that the user will be asked
  859.   to type the string a second time for confirmation and if there is a
  860.   mismatch, the process is repeated.
  861.  
  862. Line editing keys are:
  863.   C-h, DEL    rubout
  864.   C-u, C-x      line kill
  865.   C-q, C-v      literal next"
  866.   (catch 'return-value
  867.     (save-excursion
  868.       (let ((input-buffer (get-buffer-create " *password*"))
  869.         (cursor-in-echo-area t)
  870.         (echo-keystrokes 0)
  871.         char string help-form done kill-ring)
  872.     (set-buffer input-buffer)
  873.     (unwind-protect
  874.         (while t
  875.           (erase-buffer)
  876.           (message prompt)
  877.           (while (not (memq (setq char (read-char)) '(?\C-m ?\C-j)))
  878.         (if (setq form
  879.              (cdr
  880.               (assq char
  881.                 '((?\C-h . (delete-char -1))
  882.                   (?\C-? . (delete-char -1))
  883.                   (?\C-u . (delete-region 1 (point)))
  884.                   (?\C-x . (delete-region 1 (point)))
  885.                   (?\C-q . (quoted-insert 1))
  886.                   (?\C-v . (quoted-insert 1))))))
  887.             (condition-case error-data
  888.             (eval form)
  889.               (error t))
  890.           (insert char))
  891.         (message prompt))
  892.           (cond ((and confirm string)
  893.              (cond ((not (string= string (buffer-string)))
  894.                 (message
  895.                  (concat prompt "[Mismatch... try again.]"))
  896.                 (ding)
  897.                 (sit-for 2)
  898.                 (setq string nil))
  899.                (t (throw 'return-value string))))
  900.             (confirm
  901.              (setq string (buffer-string))
  902.              (message (concat prompt "[Retype to confirm...]"))
  903.              (sit-for 2))
  904.             (t (throw 'return-value (buffer-string)))))
  905.       (set-buffer-modified-p nil)
  906.       (kill-buffer input-buffer))))))
  907.  
  908.  
  909.  
  910.  
  911.  
  912.  
  913.  
  914.  
  915.  
  916.  
  917.  
  918.  
  919.  
  920.  
  921.  
  922.  
  923.  
  924.  
  925.  
  926.  
  927.  
  928.  
  929.  
  930.  
  931.  
  932.  
  933.  
  934.  
  935.  
  936.  
  937.  
  938.  
  939.  
  940.  
  941.  
  942.  
  943.  
  944.  
  945.  
  946.  
  947.  
  948.  
  949.  
  950.  
  951.  
  952.  
  953.  
  954.  
  955.  
  956.  
  957.  
  958.  
  959.  
  960.  
  961.  
  962.  
  963.  
  964.  
  965.  
  966.  
  967. ;; Install the hooks, then add the mode indicators to
  968. ;; the minor mode alist.
  969. (cond
  970.  ((not (memq 'write-crypt-file-hook write-file-hooks))
  971.   ;; make this hook last on purpose
  972.   (setq write-file-hooks (append write-file-hooks
  973.                  (list 'write-crypt-file-hook))
  974.     find-file-hooks (cons 'find-crypt-file-hook find-file-hooks)
  975.     find-file-not-found-hooks (cons 'find-crypt-file-hook
  976.                     find-file-not-found-hooks)
  977.     minor-mode-alist (nconc (list '(buffer-save-encrypted " Crypt")
  978.                       '(buffer-save-compacted " Compact")
  979.                       '(buffer-save-compressed " Compress"))
  980.                 minor-mode-alist))))
  981.