home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / editors / emacs / xemacs / xemacs-1.006 / xemacs-1 / lib / xemacs-19.13 / lisp / prim / simple.el < prev    next >
Encoding:
Text File  |  1995-08-30  |  108.6 KB  |  2,946 lines

  1. ;;; simple.el --- basic editing commands for XEmacs
  2.  
  3. ;; Copyright (C) 1985, 1986, 1987, 1993, 1994 Free Software Foundation, Inc.
  4. ;; Copyright (C) 1995 Tinker Systems and INS Engineering Corp.
  5.  
  6. ;; This file is part of XEmacs.
  7.  
  8. ;; XEmacs is free software; you can redistribute it and/or modify it
  9. ;; under the terms of the GNU General Public License as published by
  10. ;; the Free Software Foundation; either version 2, or (at your option)
  11. ;; any later version.
  12.  
  13. ;; XEmacs is distributed in the hope that it will be useful, but
  14. ;; WITHOUT ANY WARRANTY; without even the implied warranty of
  15. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16. ;; General Public License for more details.
  17.  
  18. ;; You should have received a copy of the GNU General Public License
  19. ;; along with XEmacs; see the file COPYING.  If not, write to the Free
  20. ;; Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  
  22. ;;; Synched up with: FSF 19.28.
  23.  
  24. ;;; Commentary:
  25.  
  26. ;; A grab-bag of basic XEmacs commands not specifically related to some
  27. ;; major mode or to file-handling.
  28.  
  29. ;;; Changes for zmacs-style active-regions:
  30. ;;;
  31. ;;; beginning-of-buffer, end-of-buffer, count-lines-region, 
  32. ;;; count-lines-buffer, what-line, what-cursor-position, set-goal-column,
  33. ;;; set-fill-column, prefix-arg-internal, and line-move (which is used by
  34. ;;; next-line and previous-line) set zmacs-region-stays to t, so that they
  35. ;;; don't affect the current region-hilighting state.
  36. ;;;
  37. ;;; mark-whole-buffer, mark-word, exchange-point-and-mark, and
  38. ;;; set-mark-command (without an argument) call zmacs-activate-region.
  39. ;;;
  40. ;;; mark takes an optional arg like the new Fmark_marker() does.  When 
  41. ;;; the region is not active, mark returns nil unless the optional arg is true.
  42. ;;;
  43. ;;; push-mark, pop-mark, exchange-point-and-mark, and set-marker, and
  44. ;;; set-mark-command use (mark t) so that they can access the mark whether
  45. ;;; the region is active or not.  
  46. ;;;
  47. ;;; shell-command, shell-command-on-region, yank, and yank-pop (which all
  48. ;;; push a mark) have been altered to call exchange-point-and-mark with an
  49. ;;; argument, meaning "don't activate the region".  These commands  only use
  50. ;;; exchange-point-and-mark to position the newly-pushed mark correctly, so
  51. ;;; this isn't a user-visible change.  These functions have also been altered
  52. ;;; to use (mark t) for the same reason.
  53.  
  54. ;;; Code:
  55.  
  56. (defun open-line (arg)
  57.   "Insert a newline and leave point before it.
  58. With arg N, insert N newlines."
  59. ;;   "Insert a newline and leave point before it.
  60. ;; If there is a fill prefix, insert the fill prefix on the new line
  61. ;; if the line would have been empty.
  62. ;; With arg N, insert N newlines."
  63.   (interactive "*p")
  64.   (let* (;;(do-fill-prefix (and fill-prefix (bolp)))
  65.      (do-fill-prefix nil)  ;; screw this -- says JWZ
  66.      (flag (and (null do-fill-prefix) (bolp) (not (bobp)))))
  67.     ;; If this is a simple case, and we are at the beginning of a line,
  68.     ;; actually insert the newline *before* the preceding newline
  69.     ;; instead of after.  That makes better display behavior.
  70.     (if flag
  71.     (progn
  72.       ;; If undo is enabled, don't let this hack be visible:
  73.       ;; record the real value of point as the place to move back to
  74.       ;; if we undo this insert.
  75.       (if (not (eq buffer-undo-list t))
  76.           (setq buffer-undo-list (cons (point) buffer-undo-list)))
  77.       (forward-char -1)))
  78.     (save-excursion
  79.       (while (> arg 0)
  80.     (if do-fill-prefix (insert fill-prefix))
  81.     (insert ?\n)
  82.     (setq arg (1- arg))))
  83.     (end-of-line)
  84.     (if flag (forward-char 1))))
  85.  
  86. (defun split-line ()
  87.   "Split current line, moving portion beyond point vertically down."
  88.   (interactive "*")
  89.   (skip-chars-forward " \t")
  90.   (let ((col (current-column))
  91.     (pos (point)))
  92.     (insert ?\n)
  93.     (indent-to col 0)
  94.     (goto-char pos)))
  95.  
  96. (defun quoted-insert (arg)
  97.   "Read next input character and insert it.
  98. This is useful for inserting control characters.
  99. You may also type up to 3 octal digits, to insert a character with that code.
  100.  
  101. In overwrite mode, this function inserts the character anyway, and
  102. does not handle octal digits specially.  This means that if you use
  103. overwrite as your normal editing mode, you can use this function to
  104. insert characters when necessary.
  105.  
  106. In binary overwrite mode, this function does overwrite, and octal
  107. digits are interpreted as a character code.  This is supposed to make
  108. this function useful in editing binary files."
  109.   (interactive "*p")
  110.   (let ((char (if (or (not overwrite-mode)
  111.               (eq overwrite-mode 'overwrite-mode-binary))
  112.           (read-quoted-char)
  113.         (read-char))))
  114.     (if (eq overwrite-mode 'overwrite-mode-binary)
  115.     (delete-char arg))
  116.     (insert-char char arg)))
  117.  
  118. (defun delete-indentation (&optional arg)
  119.   "Join this line to previous and fix up whitespace at join.
  120. If there is a fill prefix, delete it from the beginning of this line.
  121. With argument, join this line to following line."
  122.   (interactive "*P")
  123.   (beginning-of-line)
  124.   (if arg (forward-line 1))
  125.   (if (eq (preceding-char) ?\n)
  126.       (progn
  127.     (delete-region (point) (1- (point)))
  128.     ;; If the second line started with the fill prefix,
  129.     ;; delete the prefix.
  130.     (if (and fill-prefix
  131.          (<= (+ (point) (length fill-prefix)) (point-max))
  132.          (string= fill-prefix
  133.               (buffer-substring (point)
  134.                         (+ (point) (length fill-prefix)))))
  135.         (delete-region (point) (+ (point) (length fill-prefix))))
  136.     (fixup-whitespace))))
  137.  
  138. (defun fixup-whitespace ()
  139.   "Fixup white space between objects around point.
  140. Leave one space or none, according to the context."
  141.   (interactive "*")
  142.   (save-excursion
  143.     (delete-horizontal-space)
  144.     (if (or (looking-at "^\\|\\s)")
  145.         (save-excursion (forward-char -1)
  146.                 (looking-at "$\\|\\s(\\|\\s'")))
  147.     nil
  148.       (insert ?\ ))))
  149.  
  150. (defun delete-horizontal-space ()
  151.   "Delete all spaces and tabs around point."
  152.   (interactive "*")
  153.   (skip-chars-backward " \t")
  154.   (delete-region (point) (progn (skip-chars-forward " \t") (point))))
  155.  
  156. (defun just-one-space ()
  157.   "Delete all spaces and tabs around point, leaving one space."
  158.   (interactive "*")
  159.   (expand-abbrev)
  160.   (skip-chars-backward " \t")
  161.   (if (= (following-char) ? )
  162.       (forward-char 1)
  163.     (insert ? ))
  164.   (delete-region (point) (progn (skip-chars-forward " \t") (point))))
  165.  
  166. (defun delete-blank-lines ()
  167.   "On blank line, delete all surrounding blank lines, leaving just one.
  168. On isolated blank line, delete that one.
  169. On nonblank line, delete any immediately following blank lines."
  170.   (interactive "*")
  171.   (let (thisblank singleblank)
  172.     (save-excursion
  173.       (beginning-of-line)
  174.       (setq thisblank (looking-at "[ \t]*$"))
  175.       ;; Set singleblank if there is just one blank line here.
  176.       (setq singleblank
  177.         (and thisblank
  178.          (not (looking-at "[ \t]*\n[ \t]*$"))
  179.          (or (bobp)
  180.              (progn (forward-line -1)
  181.                 (not (looking-at "[ \t]*$")))))))
  182.     ;; Delete preceding blank lines, and this one too if it's the only one.
  183.     (if thisblank
  184.     (progn
  185.       (beginning-of-line)
  186.       (if singleblank (forward-line 1))
  187.       (delete-region (point)
  188.              (if (re-search-backward "[^ \t\n]" nil t)
  189.                  (progn (forward-line 1) (point))
  190.                (point-min)))))
  191.     ;; Delete following blank lines, unless the current line is blank
  192.     ;; and there are no following blank lines.
  193.     (if (not (and thisblank singleblank))
  194.     (save-excursion
  195.       (end-of-line)
  196.       (forward-line 1)
  197.       (delete-region (point)
  198.              (if (re-search-forward "[^ \t\n]" nil t)
  199.                  (progn (beginning-of-line) (point))
  200.                (point-max)))))
  201.     ;; Handle the special case where point is followed by newline and eob.
  202.     ;; Delete the line, leaving point at eob.
  203.     (if (looking-at "^[ \t]*\n\\'")
  204.     (delete-region (point) (point-max)))))
  205.  
  206. (defun back-to-indentation ()
  207.   "Move point to the first non-whitespace character on this line."
  208.   (interactive "_")
  209.   (beginning-of-line 1)
  210.   (skip-chars-forward " \t"))
  211.  
  212. (defun newline-and-indent ()
  213.   "Insert a newline, then indent according to major mode.
  214. Indentation is done using the value of `indent-line-function'.
  215. In programming language modes, this is the same as TAB.
  216. In some text modes, where TAB inserts a tab, this command indents to the
  217. column specified by the variable `left-margin'."
  218.   (interactive "*")
  219.   (delete-region (point) (progn (skip-chars-backward " \t") (point)))
  220.   (newline)
  221.   (indent-according-to-mode))
  222.  
  223. (defun reindent-then-newline-and-indent ()
  224.   "Reindent current line, insert newline, then indent the new line.
  225. Indentation of both lines is done according to the current major mode,
  226. which means calling the current value of `indent-line-function'.
  227. In programming language modes, this is the same as TAB.
  228. In some text modes, where TAB inserts a tab, this indents to the
  229. column specified by the variable `left-margin'."
  230.   (interactive "*")
  231.   (save-excursion
  232.     (delete-region (point) (progn (skip-chars-backward " \t") (point)))
  233.     (indent-according-to-mode))
  234.   (newline)
  235.   (indent-according-to-mode))
  236.  
  237. ;; Internal subroutine of delete-char
  238. (defun kill-forward-chars (arg)
  239.   (if (listp arg) (setq arg (car arg)))
  240.   (if (eq arg '-) (setq arg -1))
  241.   (kill-region (point) (+ (point) arg)))
  242.  
  243. ;; Internal subroutine of backward-delete-char
  244. (defun kill-backward-chars (arg)
  245.   (if (listp arg) (setq arg (car arg)))
  246.   (if (eq arg '-) (setq arg -1))
  247.   (kill-region (point) (- (point) arg)))
  248.  
  249. (defun backward-delete-char-untabify (arg &optional killp)
  250.   "Delete characters backward, changing tabs into spaces.
  251. Delete ARG chars, and kill (save in kill ring) if KILLP is non-nil.
  252. Interactively, ARG is the prefix arg (default 1)
  253. and KILLP is t if a prefix arg was specified."
  254.   (interactive "*p\nP")
  255.   (let ((count arg))
  256.     (save-excursion
  257.       (while (and (> count 0) (not (bobp)))
  258.     (if (= (preceding-char) ?\t)
  259.         (let ((col (current-column)))
  260.           (forward-char -1)
  261.           (setq col (- col (current-column)))
  262.           (insert-char ?\ col)
  263.           (delete-char 1)))
  264.     (forward-char -1)
  265.     (setq count (1- count)))))
  266.   (delete-backward-char arg killp)
  267.   ;; In overwrite mode, back over columns while clearing them out,
  268.   ;; unless at end of line.
  269.   (and overwrite-mode (not (eolp))
  270.        (save-excursion (insert-char ?\  arg))))
  271.  
  272. (defun zap-to-char (arg char)
  273.   "Kill up to and including ARG'th occurrence of CHAR.
  274. Goes backward if ARG is negative; error if CHAR not found."
  275.   (interactive "*p\ncZap to char: ")
  276.   (kill-region (point) (progn
  277.              (search-forward (char-to-string char) nil nil arg)
  278. ;             (goto-char (if (> arg 0) (1- (point)) (1+ (point))))
  279.              (point))))
  280.  
  281. (defun beginning-of-buffer (&optional arg)
  282.   "Move point to the beginning of the buffer; leave mark at previous position.
  283. With arg N, put point N/10 of the way from the true beginning.
  284.  
  285. Don't use this command in Lisp programs!
  286. \(goto-char (point-min)) is faster and avoids clobbering the mark."
  287.   (interactive "_P")
  288.   (push-mark)
  289.   (goto-char (if arg
  290.          (if (> (buffer-size) 10000)
  291.              ;; Avoid overflow for large buffer sizes!
  292.              (* (prefix-numeric-value arg)
  293.             (/ (buffer-size) 10))
  294.            (/ (+ 10 (* (buffer-size) (prefix-numeric-value arg))) 10))
  295.            (point-min)))
  296.   (if arg (forward-line 1)))
  297.  
  298. (defun end-of-buffer (&optional arg)
  299.   "Move point to the end of the buffer; leave mark at previous position.
  300. With arg N, put point N/10 of the way from the true end.
  301.  
  302. Don't use this command in Lisp programs!
  303. \(goto-char (point-max)) is faster and avoids clobbering the mark."
  304.   (interactive "_P")
  305.   (push-mark)
  306.   (let ((scroll-to-end (not (pos-visible-in-window-p (point-max)))))
  307.     (goto-char (if arg
  308.            (- (1+ (buffer-size))
  309.               (if (> (buffer-size) 10000)
  310.               ;; Avoid overflow for large buffer sizes!
  311.               (* (prefix-numeric-value arg)
  312.                  (/ (buffer-size) 10))
  313.             (/ (* (buffer-size) (prefix-numeric-value arg)) 10)))
  314.          (point-max)))
  315.     (cond (arg
  316.            ;; If we went to a place in the middle of the buffer,
  317.            ;; adjust it to the beginning of a line.
  318.            (forward-line 1))
  319.       (scroll-to-end
  320.            ;; If the end of the buffer is not already on the screen,
  321.            ;; then scroll specially to put it near, but not at, the bottom.
  322.            (recenter -3)))))
  323.  
  324. (defun mark-beginning-of-buffer (&optional arg)
  325.   "Push a mark at the beginning of the buffer; leave point where it is.
  326. With arg N, push mark N/10 of the way from the true beginning."
  327.   (interactive "P")
  328.   (push-mark (if arg
  329.          (if (> (buffer-size) 10000)
  330.              ;; Avoid overflow for large buffer sizes!
  331.              (* (prefix-numeric-value arg)
  332.             (/ (buffer-size) 10))
  333.            (/ (+ 10 (* (buffer-size) (prefix-numeric-value arg))) 10))
  334.            (point-min))
  335.              nil
  336.              t))
  337. (define-function 'mark-bob 'mark-beginning-of-buffer)
  338.  
  339. (defun mark-end-of-buffer (&optional arg)
  340.   "Push a mark at the end of the buffer; leave point where it is.
  341. With arg N, push mark N/10 of the way from the true end."
  342.   (interactive "P")
  343.   (push-mark (if arg
  344.          (- (1+ (buffer-size))
  345.             (if (> (buffer-size) 10000)
  346.             ;; Avoid overflow for large buffer sizes!
  347.             (* (prefix-numeric-value arg)
  348.                (/ (buffer-size) 10))
  349.               (/ (* (buffer-size) (prefix-numeric-value arg)) 10)))
  350.                  (point-max))
  351.              nil
  352.              t))
  353. (define-function 'mark-eob 'mark-end-of-buffer)
  354.  
  355. (defun mark-whole-buffer ()
  356.   "Put point at beginning and mark at end of buffer.
  357. You probably should not use this function in Lisp programs;
  358. it is usually a mistake for a Lisp function to use any subroutine
  359. that uses or sets the mark."
  360.   (interactive)
  361.   (push-mark (point))
  362.   (push-mark (point-max) nil t)
  363.   (goto-char (point-min)))
  364.  
  365. (defun eval-current-buffer (&optional printflag)
  366.   "Evaluate the current buffer as Lisp code.
  367. Programs can pass argument PRINTFLAG which controls printing of output:
  368. nil means discard it; anything else is stream for print."
  369.   (interactive)
  370.   (eval-buffer (current-buffer) printflag))
  371.  
  372. (defun count-words-buffer (b)
  373.   (interactive "b")
  374.   (save-excursion
  375.     (let ((buf (or b (current-buffer))))
  376.       (set-buffer buf)
  377.       (message "Buffer has %d words"
  378.            (count-words-region (point-min) (point-max))))))
  379.  
  380. (defun count-words-region (start end)
  381.   (interactive "r")
  382.   (save-excursion
  383.     (let ((n 0))
  384.       (goto-char start)
  385.       (while (< (point) end)
  386.     (if (forward-word 1)
  387.         (setq n (1+ n))))
  388.       (message "Region has %d words" n)
  389.       n)))
  390.  
  391. (defun count-lines-region (start end)
  392.   "Print number of lines and characters in the region."
  393.   (interactive "_r")
  394.   (let ((n (count-lines start end)))
  395.     (message "Region has %d lines, %d characters"
  396.          n (- end start))
  397.     n))
  398.  
  399. (defun count-lines-buffer (b)
  400.   "Print number of lines and charcters in the specified buffer."
  401.   (interactive "_b")
  402.   (save-excursion
  403.     (let ((buf (or b (current-buffer)))
  404.           cnt)
  405.       (set-buffer buf)
  406.       (setq cnt (count-lines (point-min) (point-max)))
  407.       (message "Region has %d lines, %d characters"
  408.                cnt (- (point-max) (point-min)))
  409.       cnt)))
  410.  
  411. (defun what-line ()
  412.   "Print the current line number (in the buffer) of point."
  413.   (interactive "_")
  414.   (save-restriction
  415.     (widen)
  416.     (save-excursion
  417.       (beginning-of-line)
  418.       (message "Line %d" (1+ (count-lines 1 (point)))))))
  419.  
  420. (defun count-lines (start end)
  421.   "Return number of lines between START and END.
  422. This is usually the number of newlines between them,
  423. but can be one more if START is not equal to END
  424. and the greater of them is not at the start of a line."
  425.   (save-match-data
  426.     (save-excursion
  427.       (save-restriction
  428.     (narrow-to-region start end)
  429.     (goto-char (point-min))
  430.     (if (eq selective-display t)
  431.         (let ((done 0))
  432.           (while (re-search-forward "[\n\C-m]" nil t 40)
  433.         (setq done (+ 40 done)))
  434.           (while (re-search-forward "[\n\C-m]" nil t 1)
  435.         (setq done (+ 1 done)))
  436.           (goto-char (point-max))
  437.           (if (and (/= start end)
  438.                (not (bolp)))
  439.           (1+ done)
  440.         done))
  441.       (- (buffer-size) (forward-line (buffer-size))))))))
  442.  
  443. (defun what-cursor-position ()
  444.   "Print info on cursor position (on screen and within buffer)."
  445.   (interactive "_")
  446.   (let* ((char (following-char))
  447.      (beg (point-min))
  448.      (end (point-max))
  449.          (pos (point))
  450.      (total (buffer-size))
  451.      (percent (if (> total 50000)
  452.               ;; Avoid overflow from multiplying by 100!
  453.               (/ (+ (/ total 200) (1- pos)) (max (/ total 100) 1))
  454.             (/ (+ (/ total 2) (* 100 (1- pos))) (max total 1))))
  455.      (hscroll (if (= (window-hscroll) 0)
  456.               ""
  457.             (format " Hscroll=%d" (window-hscroll))))
  458.      (col (current-column)))
  459.     (if (= pos end)
  460.     (if (or (/= beg 1) (/= end (1+ total)))
  461.         (message "point=%d of %d(%d%%) <%d - %d>  column %d %s"
  462.              pos total percent beg end col hscroll)
  463.       (message "point=%d of %d(%d%%)  column %d %s"
  464.            pos total percent col hscroll))
  465.       (if (or (/= beg 1) (/= end (1+ total)))
  466.       (message "Char: %s (0%o)  point=%d of %d(%d%%) <%d - %d>  column %d %s"
  467.            (text-char-description char) char pos total percent beg
  468.            end col hscroll)
  469.     (message "Char: %s (0%o)  point=%d of %d(%d%%)  column %d %s"
  470.          (text-char-description char) char pos total percent col
  471.          hscroll)))))
  472.  
  473. (defun fundamental-mode ()
  474.   "Major mode not specialized for anything in particular.
  475. Other major modes are defined by comparison with this one."
  476.   (interactive)
  477.   (kill-all-local-variables))
  478.  
  479.  
  480. ;; We define this, rather than making `eval' interactive,
  481. ;; for the sake of completion of names like eval-region, eval-current-buffer.
  482. (defun eval-expression (expression)
  483.   "Evaluate EXPRESSION and print value in minibuffer.
  484. Value is also consed on to front of the variable `values'."
  485.   (interactive "xEval: ")
  486.   (setq values (cons (eval expression) values))
  487.   (prin1 (car values) t))
  488.  
  489. (defun edit-and-eval-command (prompt command &optional history)
  490.   "Prompting with PROMPT, let user edit COMMAND and eval result.
  491. COMMAND is a Lisp expression.  Let user edit that expression in
  492. the minibuffer, then read and evaluate the result."
  493.   (eval (read-expression prompt
  494.              ;; first try to format the thing readably;
  495.              ;; and if that fails, print it normally.
  496.              (condition-case ()
  497.                  (let ((print-readably t))
  498.                    (prin1-to-string command))
  499.                (error (prin1-to-string command)))
  500.              (or history '(command-history . 1)))))
  501.  
  502. (defun repeat-complex-command (arg)
  503.   "Edit and re-evaluate last complex command, or ARGth from last.
  504. A complex command is one which used the minibuffer.
  505. The command is placed in the minibuffer as a Lisp form for editing.
  506. The result is executed, repeating the command as changed.
  507. If the command has been changed or is not the most recent previous command
  508. it is added to the front of the command history.
  509. You can use the minibuffer history commands \\<minibuffer-local-map>\\[next-history-element] and \\[previous-history-element]
  510. to get different commands to edit and resubmit."
  511.   (interactive "p")
  512.   (edit-and-eval-command "Redo: "
  513.              (or (nth (1- arg) command-history)
  514.                  (error ""))
  515.              (cons 'command-history arg)))
  516.  
  517. (defun goto-line (arg)
  518.   "Goto line ARG, counting from line 1 at beginning of buffer."
  519.   (interactive "NGoto line: ")
  520.   (save-restriction
  521.     (widen)
  522.     (goto-char 1)
  523.     (if (eq selective-display t)
  524.     (re-search-forward "[\n\C-m]" nil 'end (1- arg))
  525.       (forward-line (1- arg)))))
  526.  
  527. ;Put this on C-x u, so we can force that rather than C-_ into startup msg
  528. (define-function 'advertised-undo 'undo)
  529.  
  530. (defun undo (&optional arg)
  531.   "Undo some previous changes.
  532. Repeat this command to undo more changes.
  533. A numeric argument serves as a repeat count."
  534.   (interactive "*p")
  535.   ;; If we don't get all the way through, make last-command indicate that
  536.   ;; for the following command.
  537.   (setq this-command t)
  538.   (let ((modified (buffer-modified-p))
  539.     (recent-save (recent-auto-save-p)))
  540.     (or (eq (selected-window) (minibuffer-window))
  541.     (message "Undo!"))
  542.     (or (and (eq last-command 'undo)
  543.          (eq (current-buffer) last-undo-buffer))
  544.     (progn (undo-start)
  545.            (undo-more 1)))
  546.     (undo-more (or arg 1))
  547.     ;; Don't specify a position in the undo record for the undo command.
  548.     ;; Instead, undoing this should move point to where the change is.
  549.     (let ((tail buffer-undo-list)
  550.       done)
  551.       (while (and tail (not done) (not (null (car tail))))
  552.     (if (integerp (car tail))
  553.         (progn
  554.           (setq done t)
  555.           (setq buffer-undo-list (delq (car tail) buffer-undo-list))))
  556.     (setq tail (cdr tail))))
  557.     (and modified (not (buffer-modified-p))
  558.      (delete-auto-save-file-if-necessary recent-save)))
  559.   ;; If we do get all the way through, make this-command indicate that.
  560.   (setq this-command 'undo))
  561.  
  562. (defvar pending-undo-list nil
  563.   "Within a run of consecutive undo commands, list remaining to be undone.")
  564.  
  565. (defvar last-undo-buffer nil)
  566.  
  567. (defun undo-start ()
  568.   "Set `pending-undo-list' to the front of the undo list.
  569. The next call to `undo-more' will undo the most recently made change."
  570.   (if (eq buffer-undo-list t)
  571.       (error "No undo information in this buffer"))
  572.   (setq pending-undo-list buffer-undo-list))
  573.  
  574. (defun undo-more (count)
  575.   "Undo back N undo-boundaries beyond what was already undone recently.
  576. Call `undo-start' to get ready to undo recent changes,
  577. then call `undo-more' one or more times to undo them."
  578.   (or pending-undo-list
  579.       (error "No further undo information"))
  580.   (setq pending-undo-list (primitive-undo count pending-undo-list)
  581.     last-undo-buffer (current-buffer)))
  582.  
  583. (defun call-with-transparent-undo (fn &rest args)
  584.   "Apply FN to ARGS, and then undo all changes made by FN to the current
  585. buffer.  The undo records are processed even if FN returns non-locally.
  586. There is no trace of the changes made by FN in the buffer's undo history.
  587.  
  588. You can use this in a write-file-hooks function with continue-save-buffer
  589. to make the contents of a disk file differ from its in-memory buffer."
  590.   (let ((buffer-undo-list nil)
  591.     ;; Kludge to prevent undo list truncation:
  592.     (undo-high-threshold -1)
  593.     (undo-threshold -1)
  594.     (obuffer (current-buffer)))
  595.     (unwind-protect
  596.     (apply fn args)
  597.       ;; Go to the buffer we will restore and make it writable:
  598.       (set-buffer obuffer)
  599.       (save-excursion
  600.     (let ((buffer-read-only nil))
  601.       (save-restriction
  602.         (widen)
  603.         ;; Perform all undos, with further undo logging disabled:
  604.         (let ((tail buffer-undo-list))
  605.           (setq buffer-undo-list t)
  606.           (while tail
  607.         (setq tail (primitive-undo (length tail) tail))))))))))
  608.  
  609.  
  610. (defun universal-argument ()
  611.   "Begin a numeric argument for the following command.
  612. Digits or minus sign following \\[universal-argument] make up the numeric argument.
  613. \\[universal-argument] following the digits or minus sign ends the argument.
  614. \\[universal-argument] without digits or minus sign provides 4 as argument.
  615. Repeating \\[universal-argument] without digits or minus sign
  616.  multiplies the argument by 4 each time."
  617.   (interactive)
  618.   (let ((factor 4)
  619.      (start-char last-command-event)
  620.         (key nil))
  621. ;;;####> Fix read-key-sequence so we can use that instead
  622. ;   (setq key (read-key-sequence nil t))
  623. ;   (while (equal (key-binding key) 'universal-argument)
  624. ;     (setq factor (* 4 factor))
  625. ;     (setq key (read-key-sequence nil t)))
  626.     (while (progn
  627.          (setq key (next-command-event key))
  628.          (equal key start-char))
  629.       (setq factor (* 4 factor)))
  630.     (prefix-arg-internal key factor nil)))
  631.  
  632. (defun prefix-arg-internal (event factor value)
  633.   (setq zmacs-region-stays t)
  634.   (let ((sign 1)
  635.     char)
  636.     (if (key-press-event-p event) (setq char (event-key event)))
  637.     (if (and (numberp value) (< value 0))
  638.     (setq sign -1 value (- value)))
  639.     (if (eq value '-)
  640.     (setq sign -1 value nil))
  641.     (while (eq ?- char)
  642.       (setq sign (- sign) factor nil)
  643.       ;;####(setq key (read-key-sequence nil t)))
  644.       (next-command-event event)
  645.       (if (key-press-event-p event) (setq char (event-key event))))
  646.     (while (and (numberp char) (>= char ?0) (<= char ?9))
  647.       (setq value (+ (* (if (numberp value) value 0) 10) (- char ?0))
  648.             factor nil)
  649.       (next-command-event event)
  650.       (if (key-press-event-p event) (setq char (event-key event))))
  651.     (setq prefix-arg
  652.       (cond (factor (list factor))
  653.         ((numberp value) (* value sign))
  654.         ((= sign -1) '-)))
  655.     (if (and (key-press-event-p event)
  656.              (eq (key-binding (vector event)) 'universal-argument))
  657.         ;; Calling universal-argument after digits
  658.         ;; terminates the argument but is ignored.
  659.     (describe-prefix-arg value sign)
  660.       (setq unread-command-event event))))
  661.  
  662. (defun describe-prefix-arg (value sign)
  663.   (cond ((numberp value)
  664.      (message "Arg: %d" (* value sign)))
  665.     ((consp value)
  666.      (message "Arg: [%d]" (car value)))
  667.     ((< sign 0)
  668.      (message "Arg: -"))))
  669.  
  670. (defun digit-argument (arg)
  671.   "Part of the numeric argument for the next command.
  672. \\[universal-argument] following digits or minus sign ends the argument."
  673.   (interactive "P")
  674.   (prefix-arg-internal last-command-event nil arg))
  675.  
  676. (defun negative-argument (arg)
  677.   "Begin a negative numeric argument for the next command.
  678. \\[universal-argument] following digits or minus sign ends the argument."
  679.   (interactive "P")
  680.   (prefix-arg-internal (character-to-event ?- (allocate-event)) nil arg))
  681.  
  682. (defun forward-to-indentation (arg)
  683.   "Move forward ARG lines and position at first nonblank character."
  684.   (interactive "p")
  685.   (forward-line arg)
  686.   (skip-chars-forward " \t"))
  687.  
  688. (defun backward-to-indentation (arg)
  689.   "Move backward ARG lines and position at first nonblank character."
  690.   (interactive "p")
  691.   (forward-line (- arg))
  692.   (skip-chars-forward " \t"))
  693.  
  694. (defvar kill-whole-line nil
  695.   "*If non-nil, `kill-line' with no arg at beg of line kills the whole line.")
  696.  
  697. (defun kill-line (&optional arg)
  698.   "Kill the rest of the current line; if no nonblanks there, kill thru newline.
  699. With prefix argument, kill that many lines from point.
  700. Negative arguments kill lines backward.
  701.  
  702. When calling from a program, nil means \"no arg\",
  703. a number counts as a prefix arg.
  704.  
  705. If `kill-whole-line' is non-nil, then kill the whole line
  706. when given no argument at the beginning of a line."
  707.   (interactive "*P")
  708.   (kill-region (point)
  709.            ;; Don't shift point before doing the delete; that way,
  710.            ;; undo will record the right position of point.
  711.            (save-excursion
  712.          (if arg
  713.              (forward-line (prefix-numeric-value arg))
  714.            (if (eobp)
  715.                (signal 'end-of-buffer nil))
  716.            (if (or (looking-at "[ \t]*$") (and kill-whole-line (bolp)))
  717.                (forward-line 1)
  718.              (end-of-line)))
  719.          (point))))
  720.  
  721. (defun backward-kill-line nil
  722.   "Kill back to the beginning of the line."
  723.   (interactive)
  724.   (let ((point (point)))
  725.     (beginning-of-line nil)
  726.     (kill-region (point) point)))
  727.  
  728.  
  729. ;;;; Window system cut and paste hooks.
  730. ;;;
  731. ;;; I think that kill-hooks is a better name and more general mechanism
  732. ;;; than interprogram-cut-function (from FSFmacs).  I don't like the behavior
  733. ;;; of interprogram-paste-function: ^Y should always come from the kill ring,
  734. ;;; not the X selection.  But if that were provided, it should be called (and
  735. ;;; behave as) yank-hooks instead.  -- jwz
  736.  
  737. ;(defvar interprogram-cut-function nil
  738. ;  "Function to call to make a killed region available to other programs.
  739. ;
  740. ;Most window systems provide some sort of facility for cutting and
  741. ;pasting text between the windows of different programs.
  742. ;This variable holds a function that XEmacs calls whenever text
  743. ;is put in the kill ring, to make the new kill available to other
  744. ;programs.
  745. ;
  746. ;The function takes one or two arguments.
  747. ;The first argument, TEXT, is a string containing
  748. ;the text which should be made available.
  749. ;The second, PUSH, if non-nil means this is a \"new\" kill;
  750. ;nil means appending to an \"old\" kill.")
  751. ;
  752. ;(defvar interprogram-paste-function nil
  753. ;  "Function to call to get text cut from other programs.
  754. ;
  755. ;Most window systems provide some sort of facility for cutting and
  756. ;pasting text between the windows of different programs.
  757. ;This variable holds a function that XEmacs calls to obtain
  758. ;text that other programs have provided for pasting.
  759. ;
  760. ;The function should be called with no arguments.  If the function
  761. ;returns nil, then no other program has provided such text, and the top
  762. ;of the XEmacs kill ring should be used.  If the function returns a
  763. ;string, that string should be put in the kill ring as the latest kill.
  764. ;
  765. ;Note that the function should return a string only if a program other
  766. ;than XEmacs has provided a string for pasting; if XEmacs provided the
  767. ;most recent string, the function should return nil.  If it is
  768. ;difficult to tell whether XEmacs or some other program provided the
  769. ;current string, it is probably good enough to return nil if the string
  770. ;is equal (according to `string=') to the last text XEmacs provided.")
  771.  
  772. (defvar kill-hooks nil
  773.   "Functions run when something is added to the XEmacs kill ring.
  774. These functions are called with one argument, the string most recently
  775. cut or copied.  You can use this to, for example, make the most recent 
  776. kill become the X Clipboard selection.")
  777.  
  778.  
  779. ;;;; The kill ring data structure.
  780.  
  781. (defvar kill-ring nil
  782.   "List of killed text sequences.
  783. In order to maintain correct interaction with cut-and-paste facilities 
  784. offered by window systems, the functions `kill-new', `kill-append', and
  785. `current-kill' should be used to access the kill ring, instead of using
  786. this variable directly.")
  787.  
  788. (defvar kill-ring-max 30
  789.   "*Maximum length of kill ring before oldest elements are thrown away.")
  790.  
  791. (defvar kill-ring-yank-pointer nil
  792.   "The tail of the kill ring whose car is the last thing yanked.")
  793.  
  794. (defun kill-new (string)
  795.   "Make STRING the latest kill in the kill ring.
  796. Set the kill-ring-yank pointer to point to it.
  797. Runs `kill-hooks'."
  798.   (setq kill-ring (cons string kill-ring))
  799.   (if (> (length kill-ring) kill-ring-max)
  800.       (setcdr (nthcdr (1- kill-ring-max) kill-ring) nil))
  801.   (setq kill-ring-yank-pointer kill-ring)
  802. ;  (if interprogram-cut-function
  803. ;      (funcall interprogram-cut-function string t))
  804.   (run-hook-with-args 'kill-hooks string))
  805.  
  806. (defun kill-append (string before-p)
  807.   "Append STRING to the end of the latest kill in the kill ring.
  808. If BEFORE-P is non-nil, prepend STRING to the kill.
  809. Runs `kill-hooks'."
  810.   (setcar kill-ring
  811.       (if before-p
  812.           (concat string (car kill-ring))
  813.         (concat (car kill-ring) string)))
  814. ;  (if interprogram-cut-function
  815. ;      (funcall interprogram-cut-function (car kill-ring)))
  816.   (run-hook-with-args 'kill-hooks string))
  817.  
  818. (defun current-kill (n &optional do-not-move)
  819.   "Rotate the yanking point by N places, and then return that kill.
  820. If optional arg DO-NOT-MOVE is non-nil, then don't actually move the 
  821. yanking point\; just return the Nth kill forward."
  822.   (or kill-ring (error "Kill ring is empty"))
  823.   (let* ((tem (nthcdr (mod (- n (length kill-ring-yank-pointer))
  824.                            (length kill-ring))
  825.               kill-ring)))
  826.     (or do-not-move
  827.     (setq kill-ring-yank-pointer tem))
  828.     (car tem)))
  829.  
  830.  
  831.  
  832. ;;;; Commands for manipulating the kill ring.
  833.  
  834. ;;FSFmacs
  835. ;(defvar kill-read-only-ok nil
  836. ;  "*Non-nil means don't signal an error for killing read-only text.")
  837.  
  838. (defun kill-region (beg end &optional verbose) ; verbose is XEmacs addition
  839.   "Kill between point and mark.
  840. The text is deleted but saved in the kill ring.
  841. The command \\[yank] can retrieve it from there.
  842. \(If you want to kill and then yank immediately, use \\[copy-region-as-kill].)
  843.  
  844. This is the primitive for programs to kill text (as opposed to deleting it).
  845. Supply two arguments, character numbers indicating the stretch of text
  846.  to be killed.
  847. Any command that calls this function is a \"kill command\".
  848. If the previous command was also a kill command,
  849. the text killed this time appends to the text killed last time
  850. to make one entry in the kill ring."
  851.   (interactive "*r\np")
  852. ;  (interactive
  853. ;   (let ((region-hack (and zmacs-regions (eq last-command 'yank))))
  854. ;     ;; This lets "^Y^W" work.  I think this is dumb, but zwei did it.
  855. ;     (if region-hack (zmacs-activate-region))
  856. ;     (prog1
  857. ;     (list (point) (mark) current-prefix-arg)
  858. ;       (if region-hack (zmacs-deactivate-region)))))
  859.   ;; beg and end can be markers but the rest of this function is
  860.   ;; written as if they are only integers
  861.   (if (markerp beg) (setq beg (marker-position beg)))
  862.   (if (markerp end) (setq end (marker-position end)))
  863.   (or (and beg end) (if zmacs-regions ;; rewritten for I18N3 snarfing
  864.             (error "The region is not active now")
  865.               (error "The mark is not set now")))
  866.   (if verbose (if buffer-read-only
  867.           (message "Copying %d characters"
  868.                (- (max beg end) (min beg end)))
  869.           (message "Killing %d characters"
  870.                (- (max beg end) (min beg end)))))
  871.   (cond
  872.    ;; I don't like this large change in behavior -- jwz
  873.    ;;((and buffer-read-only (not inhibit-read-only))
  874.    ;; (if verbose (message "Copying %d characters"
  875.    ;;              (- (max beg end) (min beg end))))
  876.    ;; (copy-region-as-kill beg end))
  877.    ;; ;; This should always barf, and give us the correct error.
  878.    ;; (barf-if-buffer-read-only))
  879.  
  880.    ;; In certain cases, we can arrange for the undo list and the kill
  881.    ;; ring to share the same string object.  This code does that.
  882.    ((not (or (eq buffer-undo-list t)
  883.          (eq last-command 'kill-region)
  884.          (equal beg end)))
  885.     ;; Don't let the undo list be truncated before we can even access it.
  886.     (let ((undo-high-threshold (+ (- (max beg end) (min beg end)) 100))
  887.       ;(old-list buffer-undo-list)
  888.       tail)
  889.       (delete-region beg end)
  890.       ;; Search back in buffer-undo-list for this string,
  891.       ;; in case a change hook made property changes.
  892.       (setq tail buffer-undo-list)
  893.       (while (not (stringp (car-safe (car-safe tail))))
  894.     (setq tail (cdr tail)))
  895.       ;; Take the same string recorded for undo
  896.       ;; and put it in the kill-ring.
  897.       (kill-new (car (car tail)))
  898.       (setq this-command 'kill-region)))
  899.  
  900.    (t
  901.     ;; if undo is not kept, grab the string then delete it (which won't
  902.     ;; add another string to the undo list).
  903.     (copy-region-as-kill beg end)
  904.     (delete-region beg end))))
  905.  
  906. (defun copy-region-as-kill (beg end)
  907.   "Save the region as if killed, but don't kill it.
  908. Runs `kill-hooks'."
  909.   (interactive "r")
  910.   (if (eq last-command 'kill-region)
  911.       (kill-append (buffer-substring beg end) (< end beg))
  912.     (kill-new (buffer-substring beg end)))
  913.   (setq this-command 'kill-region)
  914.   nil)
  915.  
  916. (defun kill-ring-save (beg end)
  917.   "Save the region as if killed, but don't kill it.
  918. This command is similar to `copy-region-as-kill', except that it gives
  919. visual feedback indicating the extent of the region being copied."
  920.   (interactive "r")
  921.   (copy-region-as-kill beg end)
  922.   ;; copy before delay, for xclipboard's benefit
  923.   (if (interactive-p)
  924.       (let ((other-end (if (= (point) beg) end beg))
  925.         (opoint (point))
  926.         ;; Inhibit quitting so we can make a quit here
  927.         ;; look like a C-g typed as a command.
  928.         (inhibit-quit t))
  929.     (if (pos-visible-in-window-p other-end (selected-window))
  930.         (progn
  931.           (goto-char other-end)
  932.               (sit-for 1)
  933.               (goto-char opoint)
  934.               ;; If user quit, deactivate the mark
  935.           ;; as C-g would as a command.
  936.           (and quit-flag (mark)
  937.                    (zmacs-deactivate-region)))
  938.       ;; too noisy. -- jwz
  939. ;      (let* ((killed-text (current-kill 0))
  940. ;         (message-len (min (length killed-text) 40)))
  941. ;        (if (= (point) beg)
  942. ;        ;; Don't say "killed"; that is misleading.
  943. ;        (message "Saved text until \"%s\""
  944. ;            (substring killed-text (- message-len)))
  945. ;          (message "Saved text from \"%s\""
  946. ;              (substring killed-text 0 message-len))))
  947.       ))))
  948.  
  949. (defun append-next-kill ()
  950.   "Cause following command, if it kills, to append to previous kill."
  951.   (interactive "_")
  952.   (if (interactive-p)
  953.       (progn
  954.     (setq this-command 'kill-region)
  955.     (message "If the next command is a kill, it will append"))
  956.     (setq last-command 'kill-region)))
  957.  
  958. (defun yank-pop (arg)
  959.   "Replace just-yanked stretch of killed text with a different stretch.
  960. This command is allowed only immediately after a `yank' or a `yank-pop'.
  961. At such a time, the region contains a stretch of reinserted
  962. previously-killed text.  `yank-pop' deletes that text and inserts in its
  963. place a different stretch of killed text.
  964.  
  965. With no argument, the previous kill is inserted.
  966. With argument N, insert the Nth previous kill.
  967. If N is negative, this is a more recent kill.
  968.  
  969. The sequence of kills wraps around, so that after the oldest one
  970. comes the newest one."
  971.   (interactive "*p")
  972.   (if (not (eq last-command 'yank))
  973.       (error "Previous command was not a yank"))
  974.   (setq this-command 'yank)
  975.   (let ((before (< (point) (mark t))))
  976.     (delete-region (point) (mark t))
  977.     (set-mark (point))
  978.     (insert (current-kill arg))
  979.     (if before (exchange-point-and-mark t))))
  980.  
  981. (defun yank (&optional arg)
  982.   "Reinsert the last stretch of killed text.
  983. More precisely, reinsert the stretch of killed text most recently
  984. killed OR yanked.  Put point at end, and set mark at beginning.
  985. With just C-u as argument, same but put point at beginning (and mark at end).
  986. With argument N, reinsert the Nth most recently killed stretch of killed text.
  987. See also the command \\[yank-pop]."
  988.   (interactive "*P")
  989.   ;; If we don't get all the way through, make last-command indicate that
  990.   ;; for the following command.
  991.   (setq this-command t)
  992.   (push-mark (point))
  993.   (insert (current-kill (cond
  994.              ((listp arg) 0)
  995.              ((eq arg '-) -1)
  996.              (t (1- arg)))))
  997.   (if (consp arg)
  998.       (exchange-point-and-mark t))
  999.   ;; If we do get all the way through, make this-command indicate that.
  1000.   (setq this-command 'yank))
  1001.  
  1002. (defun rotate-yank-pointer (arg)
  1003.   "Rotate the yanking point in the kill ring.
  1004. With argument, rotate that many kills forward (or backward, if negative)."
  1005.   (interactive "p")
  1006.   (current-kill arg))
  1007.  
  1008.  
  1009. (defun insert-buffer (buffer)
  1010.   "Insert after point the contents of BUFFER.
  1011. Puts mark after the inserted text.
  1012. BUFFER may be a buffer or a buffer name."
  1013.   (interactive (list (progn (barf-if-buffer-read-only)
  1014.                 (read-buffer "Insert buffer: " (other-buffer) t))))
  1015.   (or (bufferp buffer)
  1016.       (setq buffer (get-buffer buffer)))
  1017.   (let (start end newmark)
  1018.     (save-excursion
  1019.       (save-excursion
  1020.     (set-buffer buffer)
  1021.     (setq start (point-min) end (point-max)))
  1022.       (insert-buffer-substring buffer start end)
  1023.       (setq newmark (point)))
  1024.     (push-mark newmark))
  1025.   nil)
  1026.  
  1027. (defun append-to-buffer (buffer start end)
  1028.   "Append to specified buffer the text of the region.
  1029. It is inserted into that buffer before its point.
  1030.  
  1031. When calling from a program, give three arguments:
  1032. BUFFER (or buffer name), START and END.
  1033. START and END specify the portion of the current buffer to be copied."
  1034.   (interactive
  1035.    (list (read-buffer "Append to buffer: " (other-buffer nil t) t)
  1036.      (region-beginning) (region-end)))
  1037.   (let ((oldbuf (current-buffer)))
  1038.     (save-excursion
  1039.       (set-buffer (get-buffer-create buffer))
  1040.       (insert-buffer-substring oldbuf start end))))
  1041.  
  1042. (defun prepend-to-buffer (buffer start end)
  1043.   "Prepend to specified buffer the text of the region.
  1044. It is inserted into that buffer after its point.
  1045.  
  1046. When calling from a program, give three arguments:
  1047. BUFFER (or buffer name), START and END.
  1048. START and END specify the portion of the current buffer to be copied."
  1049.   (interactive "BPrepend to buffer: \nr")
  1050.   (let ((oldbuf (current-buffer)))
  1051.     (save-excursion
  1052.       (set-buffer (get-buffer-create buffer))
  1053.       (save-excursion
  1054.     (insert-buffer-substring oldbuf start end)))))
  1055.  
  1056. (defun copy-to-buffer (buffer start end)
  1057.   "Copy to specified buffer the text of the region.
  1058. It is inserted into that buffer, replacing existing text there.
  1059.  
  1060. When calling from a program, give three arguments:
  1061. BUFFER (or buffer name), START and END.
  1062. START and END specify the portion of the current buffer to be copied."
  1063.   (interactive "BCopy to buffer: \nr")
  1064.   (let ((oldbuf (current-buffer)))
  1065.     (save-excursion
  1066.       (set-buffer (get-buffer-create buffer))
  1067.       (erase-buffer)
  1068.       (save-excursion
  1069.     (insert-buffer-substring oldbuf start end)))))
  1070.  
  1071. ;;;#### FSFmacs
  1072. ;(defvar mark-even-if-inactive nil
  1073. ;  "*Non-nil means you can use the mark even when inactive.
  1074. ;This option makes a difference in Transient Mark mode.
  1075. ;When the option is non-nil, deactivation of the mark
  1076. ;turns off region highlighting, but commands that use the mark
  1077. ;behave as if the mark were still active.")
  1078. ;
  1079. ;(put 'mark-inactive 'error-conditions '(mark-inactive error))
  1080. ;(put 'mark-inactive 'error-message "The mark is not active now")
  1081.  
  1082. ;;;#### FSFmacs
  1083. ;;; Many places set mark-active directly, and several of them failed to also
  1084. ;;; run deactivate-mark-hook.  This shorthand should simplify.
  1085. ;(defsubst deactivate-mark ()
  1086. ;  "Deactivate the mark by setting `mark-active' to nil.
  1087. ;\(That makes a difference only in Transient Mark mode.)
  1088. ;Also runs the hook `deactivate-mark-hook'."
  1089. ;  (if transient-mark-mode
  1090. ;      (progn
  1091. ;    (setq mark-active nil)
  1092. ;    (run-hooks 'deactivate-mark-hook))))
  1093.  
  1094. (defun mark (&optional force buffer)
  1095.   "Return this buffer's mark value as integer, or nil if no mark.
  1096.  
  1097. If `zmacs-regions' is true, then this returns nil unless the region is
  1098. currently in the active (highlighted) state.  With an argument of t, this
  1099. returns the mark (if there is one) regardless of the active-region state.
  1100. You should *generally* not use the mark unless the region is active, if
  1101. the user has expressed a preference for the active-region model.
  1102.  
  1103. If you are using this in an editing command, you are most likely making
  1104. a mistake\; see the documentation of `set-mark'."
  1105.   (setq buffer (decode-buffer buffer))
  1106.   (let ((m (mark-marker force buffer)))
  1107.     (and m (marker-position m))))
  1108.  
  1109. (defun set-mark (pos &optional buffer)
  1110.   "Set this buffer's mark to POS.  Don't use this function!
  1111. That is to say, don't use this function unless you want
  1112. the user to see that the mark has moved, and you want the previous
  1113. mark position to be lost.
  1114.  
  1115. Normally, when a new mark is set, the old one should go on the stack.
  1116. This is why most applications should use push-mark, not set-mark.
  1117.  
  1118. Novice Emacs Lisp programmers often try to use the mark for the wrong
  1119. purposes.  The mark saves a location for the user's convenience.
  1120. Most editing commands should not alter the mark.
  1121. To remember a location for internal use in the Lisp program,
  1122. store it in a Lisp variable.  Example:
  1123.  
  1124.    (let ((beg (point))) (forward-line 1) (delete-region beg (point)))."
  1125.  
  1126.   (setq buffer (decode-buffer buffer))
  1127.   (set-marker (mark-marker t buffer) pos buffer))
  1128.  
  1129. (defvar mark-ring nil
  1130.   "The list of former marks of the current buffer, most recent first.")
  1131. (make-variable-buffer-local 'mark-ring)
  1132. (put 'mark-ring 'permanent-local t)
  1133.  
  1134. (defvar mark-ring-max 16
  1135.   "*Maximum size of mark ring.  Start discarding off end if gets this big.")
  1136.  
  1137. (defvar global-mark-ring nil
  1138.   "The list of saved global marks, most recent first.")
  1139.  
  1140. (defconst global-mark-ring-max 16
  1141.   "*Maximum size of global mark ring.  \
  1142. Start discarding off end if gets this big.")
  1143.  
  1144. (defun set-mark-command (arg)
  1145.   "Set mark at where point is, or jump to mark.
  1146. With no prefix argument, set mark,  push old mark position on local mark
  1147. ring, and push mark on global mark ring.
  1148. With argument, jump to mark, and pop a new position for mark off the ring
  1149. \(does not affect global mark ring\).
  1150.  
  1151. Novice Emacs Lisp programmers often try to use the mark for the wrong
  1152. purposes.  See the documentation of `set-mark' for more information."
  1153.   (interactive "P")
  1154.   (if (null arg)
  1155.       (push-mark nil nil t)
  1156.     (if (null (mark t))
  1157.     (error "No mark set in this buffer")
  1158.       (goto-char (mark t))
  1159.       (pop-mark))))
  1160.  
  1161. (defun push-mark (&optional location nomsg activate-region buffer)
  1162.   "Set mark at LOCATION (point, by default) and push old mark on mark ring.
  1163. If the last global mark pushed was not in the current buffer,
  1164. also push LOCATION on the global mark ring.
  1165. Display `Mark set' unless the optional second arg NOMSG is non-nil.
  1166. Activate mark if optional third arg ACTIVATE-REGION non-nil.
  1167.  
  1168. Novice Emacs Lisp programmers often try to use the mark for the wrong
  1169. purposes.  See the documentation of `set-mark' for more information."
  1170.   (setq buffer (decode-buffer buffer))
  1171.   (if (null (mark t buffer))
  1172.       nil
  1173.     ;; The save-excursion / set-buffer is necessary because mark-ring
  1174.     ;; is a buffer local variable
  1175.     (save-excursion
  1176.       (set-buffer buffer)
  1177.       (setq mark-ring (cons (copy-marker (mark-marker t buffer)) mark-ring))
  1178.       (if (> (length mark-ring) mark-ring-max)
  1179.       (progn
  1180.         (move-marker (car (nthcdr mark-ring-max mark-ring)) nil buffer)
  1181.         (setcdr (nthcdr (1- mark-ring-max) mark-ring) nil)))))
  1182.   (set-mark (or location (point buffer)) buffer)
  1183.   ;; Now push the mark on the global mark ring.
  1184.   (if (or (null global-mark-ring)
  1185.           (not (eq (marker-buffer (car global-mark-ring)) buffer)))
  1186.       ;; The last global mark pushed wasn't in this same buffer.
  1187.       (progn
  1188.         (setq global-mark-ring (cons (copy-marker (mark-marker t buffer))
  1189.                                      global-mark-ring))
  1190.         (if (> (length global-mark-ring) global-mark-ring-max)
  1191.             (progn
  1192.               (move-marker (car (nthcdr global-mark-ring-max global-mark-ring))
  1193.                            nil buffer)
  1194.               (setcdr (nthcdr (1- global-mark-ring-max) global-mark-ring) nil)))))
  1195.   (or nomsg executing-macro (> (minibuffer-depth) 0)
  1196.       (message "Mark set"))
  1197.   (if activate-region
  1198.       (progn
  1199.     (setq zmacs-region-stays t)
  1200.     (zmacs-activate-region)))
  1201.   nil)
  1202.  
  1203. (defun pop-mark ()
  1204.   "Pop off mark ring into the buffer's actual mark.
  1205. Does not set point.  Does nothing if mark ring is empty."
  1206.   (if mark-ring
  1207.       (progn
  1208.     (setq mark-ring (nconc mark-ring (list (copy-marker (mark-marker t)))))
  1209.     (set-mark (car mark-ring))
  1210.     (move-marker (car mark-ring) nil)
  1211.     (if (null (mark t)) (ding))
  1212.     (setq mark-ring (cdr mark-ring)))))
  1213.  
  1214. (define-function 'exchange-dot-and-mark 'exchange-point-and-mark)
  1215. (defun exchange-point-and-mark (&optional dont-activate-region)
  1216.   "Put the mark where point is now, and point where the mark is now."
  1217.   (interactive nil)
  1218.   (let ((omark (mark t)))
  1219.     (if (null omark)
  1220.     (error "No mark set in this buffer"))
  1221.     (set-mark (point))
  1222.     (goto-char omark)
  1223.     (or dont-activate-region (zmacs-activate-region))
  1224.     nil))
  1225.  
  1226. (defun mark-something (mark-fn movement-fn arg)
  1227.   "internal function used by mark-sexp, mark-word, etc."
  1228.   (push-mark
  1229.    (save-excursion
  1230.      (if (and (eq last-command mark-fn) (mark))
  1231.      (progn
  1232.        (if (< (mark) (point)) (setq arg (- arg)))
  1233.        (goto-char (mark))))
  1234.      (funcall movement-fn arg)
  1235.      (point))
  1236.    nil t))
  1237.  
  1238. (defun pop-global-mark ()
  1239.   "Pop off global mark ring and jump to the top location."
  1240.   (interactive)
  1241.   ;; Pop entries which refer to non-existent buffers.
  1242.   (while (and global-mark-ring (not (marker-buffer (car global-mark-ring))))
  1243.     (setq global-mark-ring (cdr global-mark-ring)))
  1244.   (or global-mark-ring
  1245.       (error "No global mark set"))
  1246.   (let* ((marker (car global-mark-ring))
  1247.      (buffer (marker-buffer marker))
  1248.      (position (marker-position marker)))
  1249.     (setq global-mark-ring (cdr global-mark-ring))
  1250.     (set-buffer buffer)
  1251.     (or (and (>= position (point-min))
  1252.          (<= position (point-max)))
  1253.     (widen))
  1254.     (goto-char position)
  1255.     (switch-to-buffer buffer)))
  1256.  
  1257. ;(defun transient-mark-mode (arg)
  1258. ;  "Toggle Transient Mark mode.
  1259. ;With arg, turn Transient Mark mode on if arg is positive, off otherwise.
  1260. ;
  1261. ;In Transient Mark mode, changing the buffer \"deactivates\" the mark.
  1262. ;While the mark is active, the region is highlighted."
  1263. ;  (interactive "P")
  1264. ;  (setq transient-mark-mode
  1265. ;    (if (null arg)
  1266. ;        (not transient-mark-mode)
  1267. ;      (> (prefix-numeric-value arg) 0))))
  1268.  
  1269. (defvar next-line-add-newlines t
  1270.   "*If non-nil, `next-line' inserts newline to avoid `end of buffer' error.")
  1271.  
  1272. (defun next-line (arg)
  1273.   "Move cursor vertically down ARG lines.
  1274. If there is no character in the target line exactly under the current column,
  1275. the cursor is positioned after the character in that line which spans this
  1276. column, or at the end of the line if it is not long enough.
  1277.  
  1278. If there is no line in the buffer after this one, behavior depends on the
  1279. value of `next-line-add-newlines'.  If non-nil, a newline character is inserted
  1280. to create a line and the cursor moves to that line.  Otherwise the cursor is
  1281. moved to the end of the buffer if it is not already there and an error
  1282. is signaled.
  1283.  
  1284. The command \\[set-goal-column] can be used to create
  1285. a semipermanent goal column to which this command always moves.
  1286. Then it does not try to move vertically.  This goal column is stored
  1287. in `goal-column', which is nil when there is none.
  1288.  
  1289. If you are thinking of using this in a Lisp program, consider
  1290. using `forward-line' instead.  It is usually easier to use
  1291. and more reliable (no dependence on goal column, etc.)."
  1292.   (interactive "_p")
  1293.   (if (and next-line-add-newlines (= arg 1))
  1294.       (let ((opoint (point)))
  1295.     (end-of-line)
  1296.     (if (eobp)
  1297.         (insert ?\n)
  1298.       (goto-char opoint)
  1299.       (line-move arg)))
  1300.     (if (interactive-p)
  1301.     (condition-case nil
  1302.         (line-move arg)
  1303.       ((beginning-of-buffer end-of-buffer) (ding nil 'buffer-bound)))
  1304.       (line-move arg)))
  1305.   nil)
  1306.  
  1307. (defun previous-line (arg)
  1308.   "Move cursor vertically up ARG lines.
  1309. If there is no character in the target line exactly over the current column,
  1310. the cursor is positioned after the character in that line which spans this
  1311. column, or at the end of the line if it is not long enough.
  1312.  
  1313. The command \\[set-goal-column] can be used to create
  1314. a semipermanent goal column to which this command always moves.
  1315. Then it does not try to move vertically.
  1316.  
  1317. If you are thinking of using this in a Lisp program, consider using
  1318. `forward-line' with a negative argument instead.  It is usually easier
  1319. to use and more reliable (no dependence on goal column, etc.)."
  1320.   (interactive "_p")
  1321.   (if (interactive-p)
  1322.       (condition-case nil
  1323.       (line-move (- arg))
  1324.     ((beginning-of-buffer end-of-buffer) (ding nil 'buffer-bound)))
  1325.     (line-move (- arg)))
  1326.   nil)
  1327.  
  1328. (defvar track-eol nil
  1329.   "*Non-nil means vertical motion starting at end of line keeps to ends of lines.
  1330. This means moving to the end of each line moved onto.
  1331. The beginning of a blank line does not count as the end of a line.")
  1332.  
  1333. (defvar goal-column nil
  1334.   "*Semipermanent goal column for vertical motion, as set by \\[set-goal-column], or nil.")
  1335. (make-variable-buffer-local 'goal-column)
  1336.  
  1337. (defvar temporary-goal-column 0
  1338.   "Current goal column for vertical motion.
  1339. It is the column where point was
  1340. at the start of current run of vertical motion commands.
  1341. When the `track-eol' feature is doing its job, the value is 9999.")
  1342.  
  1343. ;; This is the guts of next-line and previous-line.
  1344. ;; Arg says how many lines to move.
  1345. (defun line-move (arg)
  1346.   (if (not (or (eq last-command 'next-line)
  1347.            (eq last-command 'previous-line)))
  1348.       (setq temporary-goal-column
  1349.         (if (and track-eol (eolp)
  1350.              ;; Don't count beg of empty line as end of line
  1351.              ;; unless we just did explicit end-of-line.
  1352.              (or (not (bolp)) (eq last-command 'end-of-line)))
  1353.         9999
  1354.           (current-column))))
  1355.   (if (not (integerp selective-display))
  1356.       (or (if (> arg 0)
  1357.           (progn (if (> arg 1) (forward-line (1- arg)))
  1358.              ;; This way of moving forward ARG lines
  1359.              ;; verifies that we have a newline after
  1360.              ;; the last one.  It doesn't get
  1361.              ;; confused by intangible text.
  1362.              (end-of-line)
  1363.              (zerop (forward-line 1)))
  1364.         (and (zerop (forward-line arg))
  1365.          (bolp)))
  1366.       (signal (if (< arg 0)
  1367.               'beginning-of-buffer
  1368.             'end-of-buffer)
  1369.           nil))
  1370.     ;; Move by arg lines, but ignore invisible ones.
  1371.     (while (> arg 0)
  1372.       (end-of-line)
  1373.       (and (zerop (vertical-motion 1))
  1374.        (signal 'end-of-buffer nil))
  1375.       (setq arg (1- arg)))
  1376.     (while (< arg 0)
  1377.       (beginning-of-line)
  1378.       (and (zerop (vertical-motion -1))
  1379.        (signal 'beginning-of-buffer nil))
  1380.       (setq arg (1+ arg))))
  1381.   (move-to-column (or goal-column temporary-goal-column))
  1382.   nil)
  1383.  
  1384. ;;; Many people have said they rarely use this feature, and often type
  1385. ;;; it by accident.  Maybe it shouldn't even be on a key.
  1386. (put 'set-goal-column 'disabled t)
  1387.  
  1388. (defun set-goal-column (arg)
  1389.   "Set the current horizontal position as a goal for \\[next-line] and \\[previous-line].
  1390. Those commands will move to this position in the line moved to
  1391. rather than trying to keep the same horizontal position.
  1392. With a non-nil argument, clears out the goal column
  1393. so that \\[next-line] and \\[previous-line] resume vertical motion.
  1394. The goal column is stored in the variable `goal-column'."
  1395.   (interactive "_P")
  1396.   (if arg
  1397.       (progn
  1398.         (setq goal-column nil)
  1399.         (message "No goal column"))
  1400.     (setq goal-column (current-column))
  1401.     (message (substitute-command-keys
  1402.           "Goal column %d (use \\[set-goal-column] with an arg to unset it)")
  1403.          goal-column))
  1404.   nil)
  1405.  
  1406. ;;;#### FSFmacs terminal randomness
  1407. ;;; Partial support for horizontal autoscrolling.  Someday, this feature
  1408. ;;; will be built into the C level and all the (hscroll-point-visible) calls
  1409. ;;; will go away.
  1410.  
  1411. ;(defvar hscroll-step 0
  1412. ;   "*The number of columns to try scrolling a window by when point moves out.
  1413. ;If that fails to bring point back on frame, point is centered instead.
  1414. ;If this is zero, point is always centered after it moves off frame.")
  1415. ;
  1416. ;(defun hscroll-point-visible ()
  1417. ;  "Scrolls the selected window horizontally to make point visible."
  1418. ;  (save-excursion
  1419. ;    (set-buffer (window-buffer))
  1420. ;    (if (not (or truncate-lines
  1421. ;         (> (window-hscroll) 0)
  1422. ;         (and truncate-partial-width-windows
  1423. ;              (< (window-width) (frame-width)))))
  1424. ;    ;; Point is always visible when lines are wrapped.
  1425. ;    ()
  1426. ;      ;; If point is on the invisible part of the line before window-start,
  1427. ;      ;; then hscrolling can't bring it back, so reset window-start first.
  1428. ;      (and (< (point) (window-start))
  1429. ;       (let ((ws-bol (save-excursion
  1430. ;               (goto-char (window-start))
  1431. ;               (beginning-of-line)
  1432. ;               (point))))
  1433. ;         (and (>= (point) ws-bol)
  1434. ;          (set-window-start nil ws-bol))))
  1435. ;      (let* ((here (hscroll-window-column))
  1436. ;         (left (min (window-hscroll) 1))
  1437. ;         (right (1- (window-width))))
  1438. ;    ;; Allow for the truncation glyph, if we're not exactly at eol.
  1439. ;    (if (not (and (= here right)
  1440. ;              (= (following-char) ?\n)))
  1441. ;        (setq right (1- right)))
  1442. ;    (cond
  1443. ;     ;; If too far away, just recenter.  But don't show too much
  1444. ;     ;; white space off the end of the line.
  1445. ;     ((or (< here (- left  hscroll-step))
  1446. ;          (> here (+ right hscroll-step)))
  1447. ;      (let ((eol (save-excursion (end-of-line) (hscroll-window-column))))
  1448. ;        (scroll-left (min (- here (/ (window-width) 2))
  1449. ;                  (- eol (window-width) -5)))))
  1450. ;     ;; Within range.  Scroll by one step (or maybe not at all).
  1451. ;     ((< here left)
  1452. ;      (scroll-right hscroll-step))
  1453. ;     ((> here right)
  1454. ;      (scroll-left hscroll-step))))))
  1455. ;
  1456. ;;; this function returns the window's idea of the display column of point,
  1457. ;;; assuming that the window is already known to be truncated rather than
  1458. ;;; wrapped, and that we've already handled the case where point is on the
  1459. ;;; part of the line before window-start.  we ignore window-width; if point
  1460. ;;; is beyond the right margin, we want to know how far.  the return value
  1461. ;;; includes the effects of window-hscroll, window-start, and the prompt
  1462. ;;; string in the minibuffer.  it may be negative due to hscroll.
  1463. ;(defun hscroll-window-column ()
  1464. ;  (let* ((hscroll (window-hscroll))
  1465. ;     (startpos (save-excursion
  1466. ;             (beginning-of-line)
  1467. ;             (if (= (point) (save-excursion
  1468. ;                      (goto-char (window-start))
  1469. ;                      (beginning-of-line)
  1470. ;                      (point)))
  1471. ;             (goto-char (window-start)))
  1472. ;             (point)))
  1473. ;     (hpos (+ (if (and (eq (selected-window) (minibuffer-window))
  1474. ;               (= 1 (window-start))
  1475. ;               (= startpos (point-min)))
  1476. ;              (minibuffer-prompt-width)
  1477. ;            0)
  1478. ;          (min 0 (- 1 hscroll))))
  1479. ;     val)
  1480. ;    (car (cdr (compute-motion startpos (cons hpos 0)
  1481. ;                  (point) (cons 0 1)
  1482. ;                  1000000 (cons hscroll 0) nil)))))
  1483. ;  
  1484. ;; rms: (1) The definitions of arrow keys should not simply restate
  1485. ;; what keys they are.  The arrow keys should run the ordinary commands.
  1486. ;; (2) The arrow keys are just one of many common ways of moving point
  1487. ;; within a line.  Real horizontal autoscrolling would be a good feature,
  1488. ;; but supporting it only for arrow keys is too incomplete to be desirable.
  1489.  
  1490. ;;;;; Make arrow keys do the right thing for improved terminal support
  1491. ;;;;; When we implement true horizontal autoscrolling, right-arrow and
  1492. ;;;;; left-arrow can lose the (if truncate-lines ...) clause and become
  1493. ;;;;; aliases.  These functions are bound to the corresponding keyboard
  1494. ;;;;; events in loaddefs.el.
  1495.  
  1496. ;;(defun right-arrow (arg)
  1497. ;;  "Move right one character on the screen (with prefix ARG, that many chars).
  1498. ;;Scroll right if needed to keep point horizontally onscreen."
  1499. ;;  (interactive "P")
  1500. ;;  (forward-char arg)
  1501. ;;  (hscroll-point-visible))
  1502.  
  1503. ;;(defun left-arrow (arg)
  1504. ;;  "Move left one character on the screen (with prefix ARG, that many chars).
  1505. ;;Scroll left if needed to keep point horizontally onscreen."
  1506. ;;  (interactive "P")
  1507. ;;  (backward-char arg)
  1508. ;;  (hscroll-point-visible))
  1509.  
  1510. (defun scroll-other-window-down (lines)
  1511.   "Scroll the \"other window\" down."
  1512.   (interactive "P")
  1513.   (scroll-other-window
  1514.    ;; Just invert the argument's meaning.
  1515.    ;; We can do that without knowing which window it will be.
  1516.    (if (eq lines '-) nil
  1517.      (if (null lines) '-
  1518.        (- (prefix-numeric-value lines))))))
  1519.  
  1520. (defun beginning-of-buffer-other-window (arg)
  1521.   "Move point to the beginning of the buffer in the other window.
  1522. Leave mark at previous position.
  1523. With arg N, put point N/10 of the way from the true beginning."
  1524.   (interactive "P")
  1525.   (let ((orig-window (selected-window))
  1526.     (window (other-window-for-scrolling)))
  1527.     ;; We use unwind-protect rather than save-window-excursion
  1528.     ;; because the latter would preserve the things we want to change.
  1529.     (unwind-protect
  1530.     (progn
  1531.       (select-window window)
  1532.       ;; Set point and mark in that window's buffer.
  1533.       (beginning-of-buffer arg)
  1534.       ;; Set point accordingly.
  1535.       (recenter '(t)))
  1536.       (select-window orig-window))))
  1537.  
  1538. (defun end-of-buffer-other-window (arg)
  1539.   "Move point to the end of the buffer in the other window.
  1540. Leave mark at previous position.
  1541. With arg N, put point N/10 of the way from the true end."
  1542.   (interactive "P")
  1543.   ;; See beginning-of-buffer-other-window for comments.
  1544.   (let ((orig-window (selected-window))
  1545.     (window (other-window-for-scrolling)))
  1546.     (unwind-protect
  1547.     (progn
  1548.       (select-window window)
  1549.       (end-of-buffer arg)
  1550.       (recenter '(t)))
  1551.       (select-window orig-window))))
  1552.  
  1553. (defun transpose-chars (arg)
  1554.   "Interchange characters around point, moving forward one character.
  1555. With prefix arg ARG, effect is to take character before point
  1556. and drag it forward past ARG other characters (backward if ARG negative).
  1557. If no argument and at end of line, the previous two chars are exchanged."
  1558.   (interactive "*P")
  1559.   (and (null arg) (eolp) (forward-char -1))
  1560.   (transpose-subr 'forward-char (prefix-numeric-value arg)))
  1561.  
  1562. (defun transpose-words (arg)
  1563.   "Interchange words around point, leaving point at end of them.
  1564. With prefix arg ARG, effect is to take word before or around point
  1565. and drag it forward past ARG other words (backward if ARG negative).
  1566. If ARG is zero, the words around or after point and around or after mark
  1567. are interchanged."
  1568.   (interactive "*p")
  1569.   (transpose-subr 'forward-word arg))
  1570.  
  1571. (defun transpose-sexps (arg)
  1572.   "Like \\[transpose-words] but applies to sexps.
  1573. Does not work on a sexp that point is in the middle of
  1574. if it is a list or string."
  1575.   (interactive "*p")
  1576.   (transpose-subr 'forward-sexp arg))
  1577.  
  1578. (defun transpose-lines (arg)
  1579.   "Exchange current line and previous line, leaving point after both.
  1580. With argument ARG, takes previous line and moves it past ARG lines.
  1581. With argument 0, interchanges line point is in with line mark is in."
  1582.   (interactive "*p")
  1583.   (transpose-subr #'(lambda (arg)
  1584.              (if (= arg 1)
  1585.              (progn
  1586.                ;; Move forward over a line,
  1587.                ;; but create a newline if none exists yet.
  1588.                (end-of-line)
  1589.                (if (eobp)
  1590.                    (newline)
  1591.                  (forward-char 1)))
  1592.                (forward-line arg)))
  1593.           arg))
  1594.  
  1595. (eval-when-compile
  1596.   ;; avoid byte-compiler warnings...
  1597.   (defvar start1)
  1598.   (defvar start2)
  1599.   (defvar end1)
  1600.   (defvar end2))
  1601.  
  1602. ; start[12] and end[12] used in transpose-subr-1 below
  1603. (defun transpose-subr (mover arg)
  1604.   (let (start1 end1 start2 end2)
  1605.     (if (= arg 0)
  1606.     (progn
  1607.       (save-excursion
  1608.         (funcall mover 1)
  1609.         (setq end2 (point))
  1610.         (funcall mover -1)
  1611.         (setq start2 (point))
  1612.         (goto-char (mark t))
  1613.         (funcall mover 1)
  1614.         (setq end1 (point))
  1615.         (funcall mover -1)
  1616.         (setq start1 (point))
  1617.         (transpose-subr-1))
  1618.       (exchange-point-and-mark t)))
  1619.     (while (> arg 0)
  1620.       (funcall mover -1)
  1621.       (setq start1 (point))
  1622.       (funcall mover 1)
  1623.       (setq end1 (point))
  1624.       (funcall mover 1)
  1625.       (setq end2 (point))
  1626.       (funcall mover -1)
  1627.       (setq start2 (point))
  1628.       (transpose-subr-1)
  1629.       (goto-char end2)
  1630.       (setq arg (1- arg)))
  1631.     (while (< arg 0)
  1632.       (funcall mover -1)
  1633.       (setq start2 (point))
  1634.       (funcall mover -1)
  1635.       (setq start1 (point))
  1636.       (funcall mover 1)
  1637.       (setq end1 (point))
  1638.       (funcall mover 1)
  1639.       (setq end2 (point))
  1640.       (transpose-subr-1)
  1641.       (setq arg (1+ arg)))))
  1642.  
  1643. ; start[12] and end[12] used free
  1644. (defun transpose-subr-1 ()
  1645.   (if (> (min end1 end2) (max start1 start2))
  1646.       (error "Don't have two things to transpose"))
  1647.   (let ((word1 (buffer-substring start1 end1))
  1648.     (word2 (buffer-substring start2 end2)))
  1649.     (delete-region start2 end2)
  1650.     (goto-char start2)
  1651.     (insert word1)
  1652.     (goto-char (if (< start1 start2) start1
  1653.          (+ start1 (- (length word1) (length word2)))))
  1654.     (delete-char (length word1))
  1655.     (insert word2)))
  1656.  
  1657. (defvar comment-column 32
  1658.   "*Column to indent right-margin comments to.
  1659. Setting this variable automatically makes it local to the current buffer.
  1660. Each mode establishes a different default value for this variable; you
  1661. can set the value for a particular mode using that mode's hook.")
  1662. (make-variable-buffer-local 'comment-column)
  1663.  
  1664. (defvar comment-start nil
  1665.   "*String to insert to start a new comment, or nil if no comment syntax defined.")
  1666.  
  1667. (defvar comment-start-skip nil
  1668.   "*Regexp to match the start of a comment plus everything up to its body.
  1669. If there are any \\(...\\) pairs, the comment delimiter text is held to begin
  1670. at the place matched by the close of the first pair.")
  1671.  
  1672. (defvar comment-end ""
  1673.   "*String to insert to end a new comment.
  1674. Should be an empty string if comments are terminated by end-of-line.")
  1675.  
  1676. (defconst comment-indent-hook nil
  1677.   "Obsolete variable for function to compute desired indentation for a comment.
  1678. Use `comment-indent-function' instead.
  1679. This function is called with no args with point at the beginning of
  1680. the comment's starting delimiter.")
  1681.  
  1682. (defvar comment-indent-function
  1683.   ;; XEmacs - add at least one space after the end of the text on the
  1684.   ;; current line...  
  1685.   #'(lambda ()
  1686.       (save-excursion 
  1687.     (beginning-of-line) 
  1688.     (let ((eol (save-excursion (end-of-line) (point))))
  1689.       (and comment-start-skip
  1690.            (re-search-forward comment-start-skip eol t)
  1691.            (setq eol (match-beginning 0)))
  1692.       (goto-char eol)
  1693.       (skip-chars-backward " \t")
  1694.       (max comment-column (1+ (current-column))))))
  1695.   "Function to compute desired indentation for a comment.
  1696. This function is called with no args with point at the beginning of
  1697. the comment's starting delimiter.")
  1698.  
  1699. (defun indent-for-comment ()
  1700.   "Indent this line's comment to comment column, or insert an empty comment."
  1701.   (interactive "*")
  1702.   (beginning-of-line 1)
  1703.   (if (null comment-start)
  1704.       (error "No comment syntax defined")
  1705.     (let* ((eolpos (save-excursion (end-of-line) (point)))
  1706.        cpos indent begpos)
  1707.       (if (re-search-forward comment-start-skip eolpos 'move)
  1708.       (progn (setq cpos (point-marker))
  1709.          ;; Find the start of the comment delimiter.
  1710.          ;; If there were paren-pairs in comment-start-skip,
  1711.          ;; position at the end of the first pair.
  1712.          (if (match-end 1)
  1713.              (goto-char (match-end 1))
  1714.            ;; If comment-start-skip matched a string with
  1715.            ;; internal whitespace (not final whitespace) then
  1716.            ;; the delimiter start at the end of that
  1717.            ;; whitespace.  Otherwise, it starts at the
  1718.            ;; beginning of what was matched.
  1719.            (skip-syntax-backward " " (match-beginning 0))
  1720.            (skip-syntax-backward "^ " (match-beginning 0)))))
  1721.       (setq begpos (point))
  1722.       ;; Compute desired indent.
  1723.       (if (= (current-column)
  1724.          (setq indent (if comment-indent-hook
  1725.                               ;; old name
  1726.                   (funcall comment-indent-hook)
  1727.                 (funcall comment-indent-function))))
  1728.       (goto-char begpos)
  1729.     ;; If that's different from current, change it.
  1730.     (skip-chars-backward " \t")
  1731.     (delete-region (point) begpos)
  1732.     (indent-to indent))
  1733.       ;; An existing comment?
  1734.       (if cpos 
  1735.       (progn (goto-char cpos)
  1736.          (set-marker cpos nil))
  1737.     ;; No, insert one.
  1738.     (insert comment-start)
  1739.     (save-excursion
  1740.       (insert comment-end))))))
  1741.  
  1742. (defun set-comment-column (arg)
  1743.   "Set the comment column based on point.
  1744. With no arg, set the comment column to the current column.
  1745. With just minus as arg, kill any comment on this line.
  1746. With any other arg, set comment column to indentation of the previous comment
  1747.  and then align or create a comment on this line at that column."
  1748.   (interactive "P")
  1749.   (if (eq arg '-)
  1750.       (kill-comment nil)
  1751.     (if arg
  1752.     (progn
  1753.       (save-excursion
  1754.         (beginning-of-line)
  1755.         (re-search-backward comment-start-skip)
  1756.         (beginning-of-line)
  1757.         (re-search-forward comment-start-skip)
  1758.         (goto-char (match-beginning 0))
  1759.         (setq comment-column (current-column))
  1760.         (message "Comment column set to %d" comment-column))
  1761.       (indent-for-comment))
  1762.       (setq comment-column (current-column))
  1763.       (message "Comment column set to %d" comment-column))))
  1764.  
  1765. (defun kill-comment (arg)
  1766.   "Kill the comment on this line, if any.
  1767. With argument, kill comments on that many lines starting with this one."
  1768.   ;; this function loses in a lot of situations.  it incorrectly recognises
  1769.   ;; comment delimiters sometimes (ergo, inside a string), doesn't work
  1770.   ;; with multi-line comments, can kill extra whitespace if comment wasn't
  1771.   ;; through end-of-line, et cetera.
  1772.   (interactive "*P")
  1773.   (or comment-start-skip (error "No comment syntax defined"))
  1774.   (let ((count (prefix-numeric-value arg)) endc)
  1775.     (while (> count 0)
  1776.       (save-excursion
  1777.     (end-of-line)
  1778.     (setq endc (point))
  1779.     (beginning-of-line)
  1780.     (and (string< "" comment-end)
  1781.          (setq endc
  1782.            (progn
  1783.              (re-search-forward (regexp-quote comment-end) endc 'move)
  1784.              (skip-chars-forward " \t")
  1785.              (point))))
  1786.     (beginning-of-line)
  1787.     (if (re-search-forward comment-start-skip endc t)
  1788.         (progn
  1789.           (goto-char (match-beginning 0))
  1790.           (skip-chars-backward " \t")
  1791.           (kill-region (point) endc)
  1792.           ;; to catch comments a line beginnings
  1793.           (indent-according-to-mode))))
  1794.       (if arg (forward-line 1))
  1795.       (setq count (1- count)))))
  1796.  
  1797. (defun comment-region (beg end &optional arg)
  1798.   "Comment or uncomment each line in the region.
  1799. With just C-u prefix arg, uncomment each line in region.
  1800. Numeric prefix arg ARG means use ARG comment characters.
  1801. If ARG is negative, delete that many comment characters instead.
  1802. Comments are terminated on each line, even for syntax in which newline does
  1803. not end the comment.  Blank lines do not get comments."
  1804.   ;; if someone wants it to only put a comment-start at the beginning and
  1805.   ;; comment-end at the end then typing it, C-x C-x, closing it, C-x C-x
  1806.   ;; is easy enough.  No option is made here for other than commenting
  1807.   ;; every line.
  1808.   (interactive "r\nP")
  1809.   (or comment-start (error "No comment syntax is defined"))
  1810.   (if (> beg end) (let (mid) (setq mid beg beg end end mid)))
  1811.   (save-excursion
  1812.     (save-restriction
  1813.       (let ((cs comment-start) (ce comment-end)
  1814.         numarg)
  1815.         (if (consp arg) (setq numarg t)
  1816.       (setq numarg (prefix-numeric-value arg))
  1817.       ;; For positive arg > 1, replicate the comment delims now,
  1818.       ;; then insert the replicated strings just once.
  1819.       (while (> numarg 1)
  1820.         (setq cs (concat cs comment-start)
  1821.           ce (concat ce comment-end))
  1822.         (setq numarg (1- numarg))))
  1823.     ;; Loop over all lines from BEG to END.
  1824.         (narrow-to-region beg end)
  1825.         (goto-char beg)
  1826.         (while (not (eobp))
  1827.           (if (or (eq numarg t) (< numarg 0))
  1828.           (progn
  1829.         ;; Delete comment start from beginning of line.
  1830.         (if (eq numarg t)
  1831.             (while (looking-at (regexp-quote cs))
  1832.               (delete-char (length cs)))
  1833.           (let ((count numarg))
  1834.             (while (and (> 1 (setq count (1+ count)))
  1835.                 (looking-at (regexp-quote cs)))
  1836.               (delete-char (length cs)))))
  1837.         ;; Delete comment end from end of line.
  1838.                 (if (string= "" ce)
  1839.             nil
  1840.           (if (eq numarg t)
  1841.               (progn
  1842.             (end-of-line)
  1843.             ;; This is questionable if comment-end ends in
  1844.             ;; whitespace.  That is pretty brain-damaged,
  1845.             ;; though.
  1846.             (skip-chars-backward " \t")
  1847.             (if (and (>= (- (point) (point-min)) (length ce))
  1848.                  (save-excursion
  1849.                    (backward-char (length ce))
  1850.                    (looking-at (regexp-quote ce))))
  1851.                 (delete-char (- (length ce)))))
  1852.             (let ((count numarg))
  1853.               (while (> 1 (setq count (1+ count)))
  1854.             (end-of-line)
  1855.             ;; This is questionable if comment-end ends in
  1856.             ;; whitespace.  That is pretty brain-damaged though
  1857.             (skip-chars-backward " \t")
  1858.             (save-excursion
  1859.               (backward-char (length ce))
  1860.               (if (looking-at (regexp-quote ce))
  1861.                   (delete-char (length ce))))))))
  1862.         (forward-line 1))
  1863.         ;; Insert at beginning and at end.
  1864.             (if (looking-at "[ \t]*$") ()
  1865.               (insert cs)
  1866.               (if (string= "" ce) ()
  1867.                 (end-of-line)
  1868.                 (insert ce)))
  1869.             (search-forward "\n" nil 'move)))))))
  1870.  
  1871. (defun prefix-region (prefix)
  1872.   "Add a prefix string to each line between mark and point."
  1873.   (interactive "sPrefix string: ")
  1874.   (if prefix
  1875.       (let ((count (count-lines (mark) (point))))
  1876.      (goto-char (min (mark) (point)))
  1877.      (while (> count 0)
  1878.           (setq count (1- count))
  1879.        (beginning-of-line 1)
  1880.        (insert prefix)
  1881.        (end-of-line 1)
  1882.        (forward-char 1)))))
  1883.  
  1884.  
  1885. (defun backward-word (arg &optional buffer)
  1886.   "Move backward until encountering the end of a word.
  1887. With argument, do this that many times.
  1888. In programs, it is faster to call `forward-word' with negative arg."
  1889.   (interactive "_p")
  1890.   (forward-word (- arg) buffer))
  1891.  
  1892. (defun mark-word (arg)
  1893.   "Set mark arg words away from point."
  1894.   (interactive "p")
  1895.   (mark-something 'mark-word 'forward-word arg))
  1896.  
  1897. (defun kill-word (arg)
  1898.   "Kill characters forward until encountering the end of a word.
  1899. With argument, do this that many times."
  1900.   (interactive "*p")
  1901.   (kill-region (point) (save-excursion (forward-word arg) (point))))
  1902.  
  1903. (defun backward-kill-word (arg)
  1904.   "Kill characters backward until encountering the end of a word.
  1905. With argument, do this that many times."
  1906.   (interactive "*p")
  1907.   (kill-word (- arg)))
  1908.  
  1909. (defun current-word (&optional strict)
  1910.   "Return the word point is on (or a nearby word) as a string.
  1911. If optional arg STRICT is non-nil, return nil unless point is within
  1912. or adjacent to a word.
  1913. If point is not between two word-constituent characters, but immediately
  1914. follows one, move back first.
  1915. Otherwise, if point precedes a word constituent, move forward first.
  1916. Otherwise, move backwards until a word constituent is found and get that word;
  1917. if you a newlines is reached first, move forward instead."
  1918.   (save-excursion
  1919.     (let ((oldpoint (point)) (start (point)) (end (point)))
  1920.       (skip-syntax-backward "w_") (setq start (point))
  1921.       (goto-char oldpoint)
  1922.       (skip-syntax-forward "w_") (setq end (point))
  1923.       (if (and (eq start oldpoint) (eq end oldpoint))
  1924.       ;; Point is neither within nor adjacent to a word.
  1925.       (and (not strict)
  1926.                (progn
  1927.                  ;; Look for preceding word in same line.
  1928.                  (skip-syntax-backward "^w_"
  1929.                                        (save-excursion
  1930.                                          (beginning-of-line) (point)))
  1931.                  (if (bolp)
  1932.              ;; No preceding word in same line.
  1933.              ;; Look for following word in same line.
  1934.                      (progn
  1935.                        (skip-syntax-forward "^w_"
  1936.                         (save-excursion
  1937.                                               (end-of-line) (point)))
  1938.                        (setq start (point))
  1939.                        (skip-syntax-forward "w_")
  1940.                        (setq end (point)))
  1941.                      (setq end (point))
  1942.                      (skip-syntax-backward "w_")
  1943.                      (setq start (point)))
  1944.          (buffer-substring start end)))
  1945.           (buffer-substring start end)))))
  1946.  
  1947. (defvar fill-prefix nil
  1948.   "*String for filling to insert at front of new line, or nil for none.
  1949. Setting this variable automatically makes it local to the current buffer.")
  1950. (make-variable-buffer-local 'fill-prefix)
  1951.  
  1952. (defvar auto-fill-inhibit-regexp nil
  1953.   "*Regexp to match lines which should not be auto-filled.")
  1954.  
  1955. (defun do-auto-fill ()
  1956.   (let (give-up)
  1957.     (or (and auto-fill-inhibit-regexp
  1958.          (save-excursion (beginning-of-line)
  1959.                  (looking-at auto-fill-inhibit-regexp)))
  1960.     (while (and (not give-up) (> (current-column) fill-column))
  1961.       ;; Determine where to split the line.
  1962.       (let ((fill-prefix fill-prefix)
  1963.         (fill-point
  1964.          (let ((opoint (point))
  1965.                bounce
  1966.                (first t))
  1967.            (save-excursion
  1968.              (move-to-column (1+ fill-column))
  1969.              ;; Move back to a word boundary.
  1970.              (while (or first
  1971.                 ;; If this is after period and a single space,
  1972.                 ;; move back once more--we don't want to break
  1973.                 ;; the line there and make it look like a
  1974.                 ;; sentence end.
  1975.                 (and (not (bobp))
  1976.                      (not bounce)
  1977.                      sentence-end-double-space
  1978.                      (save-excursion (forward-char -1)
  1979.                              (and (looking-at "\\. ")
  1980.                               (not (looking-at "\\.  "))))))
  1981.                (setq first nil)
  1982.                (skip-chars-backward "^ \t\n")
  1983.                ;; If we find nowhere on the line to break it,
  1984.                ;; break after one word.  Set bounce to t
  1985.                ;; so we will not keep going in this while loop.
  1986.                (if (bolp)
  1987.                (progn
  1988.                  (re-search-forward "[ \t]" opoint t)
  1989.                  (setq bounce t)))
  1990.                (skip-chars-backward " \t"))
  1991.              ;; Let fill-point be set to the place where we end up.
  1992.              (point)))))
  1993.  
  1994.         ;; I'm not sure why Stig made this change but it breaks
  1995.         ;; auto filling in at least C mode so I'm taking it back
  1996.         ;; out.  --cet
  1997.         ;; (maybe-adapt-fill-prefix)    ; XEmacs - adaptive fill.
  1998.  
  1999.         ;; If that place is not the beginning of the line,
  2000.         ;; break the line there.
  2001.         (if (save-excursion
  2002.           (goto-char fill-point)
  2003.           (not (bolp)))
  2004.         (let ((prev-column (current-column)))
  2005.           ;; If point is at the fill-point, do not `save-excursion'.
  2006.           ;; Otherwise, if a comment prefix or fill-prefix is inserted,
  2007.           ;; point will end up before it rather than after it.
  2008.           (if (save-excursion
  2009.             (skip-chars-backward " \t")
  2010.             (= (point) fill-point))
  2011.               (indent-new-comment-line)
  2012.             (save-excursion
  2013.               (goto-char fill-point)
  2014.               (indent-new-comment-line)))
  2015.           ;; If making the new line didn't reduce the hpos of
  2016.           ;; the end of the line, then give up now;
  2017.           ;; trying again will not help.
  2018.           (if (>= (current-column) prev-column)
  2019.               (setq give-up t)))
  2020.           ;; No place to break => stop trying.
  2021.           (setq give-up t)))))))
  2022.  
  2023. (defvar comment-multi-line t ; XEmacs - this works well with adaptive fill
  2024.   "*Non-nil means \\[indent-new-comment-line] should continue same comment
  2025. on new line, with no new terminator or starter.
  2026. This is obsolete because you might as well use \\[newline-and-indent].")
  2027.  
  2028. (defun indent-new-comment-line ()
  2029.   "Break line at point and indent, continuing comment if within one.
  2030. This indents the body of the continued comment
  2031. under the previous comment line.
  2032.  
  2033. This command is intended for styles where you write a comment per line,
  2034. starting a new comment (and terminating it if necessary) on each line.
  2035. If you want to continue one comment across several lines, use \\[newline-and-indent]."
  2036.   (interactive "*")
  2037.   (let (comcol comstart)
  2038.     (skip-chars-backward " \t")
  2039.     (delete-region (point)
  2040.            (progn (skip-chars-forward " \t")
  2041.               (point)))
  2042.     (insert ?\n)
  2043.     ;; #### - Eric Eide reverts to v18 semantics for this function in
  2044.     ;; fa-extras, which I'm not gonna do.  His changes are to (1) execute
  2045.     ;; the save-excursion below unconditionally, and (2) uncomment the check
  2046.     ;; for (not comment-multi-line) further below.  --Stig 
  2047.     (if (not comment-multi-line)
  2048.     (save-excursion
  2049.       (if (and comment-start-skip
  2050.            (let ((opoint (point)))
  2051.              (forward-line -1)
  2052.              (re-search-forward comment-start-skip opoint t)))
  2053.           ;; The old line is a comment.
  2054.           ;; Set WIN to the pos of the comment-start.
  2055.           ;; But if the comment is empty, look at preceding lines
  2056.           ;; to find one that has a nonempty comment.
  2057.           (let ((win (match-beginning 0)))
  2058.         (while (and (eolp) (not (bobp))
  2059.                 (let (opoint)
  2060.                   (beginning-of-line)
  2061.                   (setq opoint (point))
  2062.                   (forward-line -1)
  2063.                   (re-search-forward comment-start-skip opoint t)))
  2064.           (setq win (match-beginning 0)))
  2065.         ;; Indent this line like what we found.
  2066.         (goto-char win)
  2067.         (setq comcol (current-column))
  2068.         (setq comstart (buffer-substring (point) (match-end 0)))))))
  2069.     (if (and comcol (not fill-prefix))    ; XEmacs - (ENE) from fa-extras.
  2070.     (let ((comment-column comcol)
  2071.           (comment-start comstart)
  2072.           (comment-end comment-end))
  2073.       (and comment-end (not (equal comment-end ""))
  2074. ;           (if (not comment-multi-line)
  2075.            (progn
  2076.              (forward-char -1)
  2077.              (insert comment-end)
  2078.              (forward-char 1))
  2079. ;         (setq comment-column (+ comment-column (length comment-start))
  2080. ;               comment-start "")
  2081. ;           )
  2082.            )
  2083.       (if (not (eolp))
  2084.           (setq comment-end ""))
  2085.       (insert ?\n)
  2086.       (forward-char -1)
  2087.       (indent-for-comment)
  2088.       (save-excursion
  2089.         ;; Make sure we delete the newline inserted above.
  2090.         (end-of-line)
  2091.         (delete-char 1)))
  2092.       (if fill-prefix
  2093.       (insert fill-prefix)
  2094.     (indent-according-to-mode)))))
  2095.  
  2096. (defun auto-fill-mode (&optional arg)
  2097.   "Toggle auto-fill mode.
  2098. With arg, turn auto-fill mode on if and only if arg is positive.
  2099. In auto-fill mode, inserting a space at a column beyond `fill-column'
  2100. automatically breaks the line at a previous space."
  2101.   (interactive "P")
  2102.   (prog1 (setq auto-fill-function
  2103.            (if (if (null arg)
  2104.                (not auto-fill-function)
  2105.                (> (prefix-numeric-value arg) 0))
  2106.            'do-auto-fill
  2107.            nil))
  2108.     (redraw-modeline)))
  2109.  
  2110. ;; This holds a document string used to document auto-fill-mode.
  2111. (defun auto-fill-function ()
  2112.   "Automatically break line at a previous space, in insertion of text."
  2113.   nil)
  2114.  
  2115. (defun turn-on-auto-fill ()
  2116.   "Unconditionally turn on Auto Fill mode."
  2117.   (auto-fill-mode 1))
  2118.  
  2119. (defun set-fill-column (arg)
  2120.   "Set `fill-column' to current column, or to argument if given.
  2121. The variable `fill-column' has a separate value for each buffer."
  2122.   (interactive "_P")
  2123.   (setq fill-column (if (integerp arg) arg (current-column)))
  2124.   (message "fill-column set to %d" fill-column))
  2125.  
  2126. (defun set-selective-display (arg)
  2127.   "Set `selective-display' to ARG; clear it if no arg.
  2128. When the value of `selective-display' is a number > 0,
  2129. lines whose indentation is >= that value are not displayed.
  2130. The variable `selective-display' has a separate value for each buffer."
  2131.   (interactive "P")
  2132.   (if (eq selective-display t)
  2133.       (error "selective-display already in use for marked lines"))
  2134.   (let ((current-vpos
  2135.      (save-restriction
  2136.        (narrow-to-region (point-min) (point))
  2137.        (goto-char (window-start))
  2138.        (vertical-motion (window-height)))))
  2139.     (setq selective-display
  2140.       (and arg (prefix-numeric-value arg)))
  2141.     (recenter current-vpos))
  2142.   (set-window-start (selected-window) (window-start (selected-window)))
  2143.   ;; #### doesn't localize properly:
  2144.   (princ "selective-display set to " t)
  2145.   (prin1 selective-display t)
  2146.   (princ "." t))
  2147.  
  2148. (defun nuke-selective-display ()
  2149.   "Ensure that the buffer is not in selective-display mode.
  2150. If `selective-display' is t, then restore the buffer text to it's original
  2151. state before disabling selective display." 
  2152.   ;; by Stig@hackvan.com
  2153.   (interactive)
  2154.   (and (eq t selective-display)
  2155.        (save-excursion
  2156.      (save-restriction
  2157.        (widen)
  2158.        (goto-char (point-min))
  2159.        (let ((mod-p (buffer-modified-p))
  2160.          (buffer-read-only nil))
  2161.          (while (search-forward "\r" nil t)
  2162.            (delete-char -1)
  2163.            (insert "\n"))
  2164.          (set-buffer-modified-p mod-p)
  2165.          ))))
  2166.   (setq selective-display nil))
  2167.  
  2168. (add-hook 'change-major-mode-hook 'nuke-selective-display)
  2169.  
  2170. (defvar overwrite-mode-textual (purecopy " Ovwrt")
  2171.   "The string displayed in the modeline when in overwrite mode.")
  2172. (defvar overwrite-mode-binary (purecopy " Bin Ovwrt")
  2173.   "The string displayed in the modeline when in binary overwrite mode.")
  2174.  
  2175. (defun overwrite-mode (arg)
  2176.   "Toggle overwrite mode.
  2177. With arg, turn overwrite mode on iff arg is positive.
  2178. In overwrite mode, printing characters typed in replace existing text
  2179. on a one-for-one basis, rather than pushing it to the right.  At the
  2180. end of a line, such characters extend the line.  Before a tab,
  2181. such characters insert until the tab is filled in.
  2182. \\[quoted-insert] still inserts characters in overwrite mode; this
  2183. is supposed to make it easier to insert characters when necessary."
  2184.   (interactive "P")
  2185.   (setq overwrite-mode
  2186.     (if (if (null arg) (not overwrite-mode)
  2187.           (> (prefix-numeric-value arg) 0))
  2188.         'overwrite-mode-textual))
  2189.   (redraw-modeline))
  2190.  
  2191. (defun binary-overwrite-mode (arg)
  2192.   "Toggle binary overwrite mode.
  2193. With arg, turn binary overwrite mode on iff arg is positive.
  2194. In binary overwrite mode, printing characters typed in replace
  2195. existing text.  Newlines are not treated specially, so typing at the
  2196. end of a line joins the line to the next, with the typed character
  2197. between them.  Typing before a tab character simply replaces the tab
  2198. with the character typed.
  2199. \\[quoted-insert] replaces the text at the cursor, just as ordinary
  2200. typing characters do.
  2201.  
  2202. Note that binary overwrite mode is not its own minor mode; it is a
  2203. specialization of overwrite-mode, entered by setting the
  2204. `overwrite-mode' variable to `overwrite-mode-binary'."
  2205.   (interactive "P")
  2206.   (setq overwrite-mode
  2207.     (if (if (null arg)
  2208.         (not (eq overwrite-mode 'overwrite-mode-binary))
  2209.           (> (prefix-numeric-value arg) 0))
  2210.         'overwrite-mode-binary))
  2211.   (redraw-modeline))
  2212.  
  2213. ;(defvar line-number-mode nil
  2214. ;  "*Non-nil means display line number in modeline.")
  2215.  
  2216. (defun line-number-mode (arg)
  2217.   "Toggle Line Number mode.
  2218. With arg, turn Line Number mode on iff arg is positive.
  2219. When Line Number mode is enabled, the line number appears
  2220. in the modeline."
  2221.   (interactive "P")
  2222.   (setq line-number-mode
  2223.     (if (null arg) (not line-number-mode)
  2224.       (> (prefix-numeric-value arg) 0)))
  2225.   (redraw-modeline))
  2226.  
  2227.  
  2228. (defvar blink-matching-paren t
  2229.   "*Non-nil means show matching open-paren when close-paren is inserted.")
  2230.  
  2231. (defvar blink-matching-paren-distance 12000
  2232.   "*If non-nil, is maximum distance to search for matching open-paren.")
  2233.  
  2234. (defun blink-matching-open ()
  2235.   "Move cursor momentarily to the beginning of the sexp before point."
  2236.   (interactive "_")
  2237.   (and (> (point) (1+ (point-min)))
  2238.        (not (memq (char-syntax (char-after (- (point) 2))) '(?/ ?\\ )))
  2239.        blink-matching-paren
  2240.        (let* ((oldpos (point))
  2241.           (parse-sexp-ignore-comments t) ; to avoid C++ lossage
  2242.           (blinkpos)
  2243.           (mismatch))
  2244.      (save-excursion
  2245.        (save-restriction
  2246.          (if blink-matching-paren-distance
  2247.          (narrow-to-region (max (point-min)
  2248.                     (- (point) blink-matching-paren-distance))
  2249.                    oldpos))
  2250.          (condition-case ()
  2251.          (setq blinkpos (scan-sexps oldpos -1))
  2252.            (error nil)))
  2253.        (and blinkpos (/= (char-syntax (char-after blinkpos))
  2254.                  ?\$)
  2255.         (setq mismatch
  2256.               (/= (char-after (1- oldpos))
  2257.               (matching-paren (char-after blinkpos)))))
  2258.        (if mismatch (setq blinkpos nil))
  2259.        (if blinkpos
  2260.            (progn
  2261.         (goto-char blinkpos)
  2262.         (if (pos-visible-in-window-p)
  2263.             (sit-for 1)
  2264.           (goto-char blinkpos)
  2265.           (message
  2266.            "Matches %s"
  2267.            ;; Show what precedes the open in its line, if anything.
  2268.            (if (save-excursion
  2269.              (skip-chars-backward " \t")
  2270.              (not (bolp)))
  2271.                (buffer-substring (progn (beginning-of-line) (point))
  2272.                      (1+ blinkpos))
  2273.              ;; Show what follows the open in its line, if anything.
  2274.              (if (save-excursion
  2275.                (forward-char 1)
  2276.                (skip-chars-forward " \t")
  2277.                (not (eolp)))
  2278.                          (buffer-substring blinkpos
  2279.                                            (progn (end-of-line) (point)))
  2280.                ;; Otherwise show the previous nonblank line.
  2281.                (concat
  2282.             (buffer-substring (progn
  2283.                        (backward-char 1)
  2284.                        (skip-chars-backward "\n \t")
  2285.                        (beginning-of-line)
  2286.                        (point))
  2287.                       (progn (end-of-line)
  2288.                          (skip-chars-backward " \t")
  2289.                          (point)))
  2290.             ;; Replace the newline and other whitespace with `...'.
  2291.             "..."
  2292.             (buffer-substring blinkpos (1+ blinkpos))))))))
  2293.          (cond (mismatch
  2294.             (message "Mismatched parentheses"))
  2295.            ((not blink-matching-paren-distance)
  2296.             (message "Unmatched parenthesis"))))))))
  2297.  
  2298. ;Turned off because it makes dbx bomb out.
  2299. (setq blink-paren-function 'blink-matching-open)
  2300.  
  2301. (eval-when-compile (defvar myhelp))    ; suppress compiler warning
  2302.  
  2303. (defun set-variable (var val)
  2304.   "Set VARIABLE to VALUE.  VALUE is a Lisp object.
  2305. When using this interactively, supply a Lisp expression for VALUE.
  2306. If you want VALUE to be a string, you must surround it with doublequotes.
  2307.  
  2308. If VARIABLE has a `variable-interactive' property, that is used as if
  2309. it were the arg to `interactive' (which see) to interactively read the value."
  2310.   (interactive
  2311.    (let* ((var (read-variable "Set variable: "))
  2312.       ;; #### - yucky code replication here.  This should use something
  2313.       ;; from help.el or hyper-apropos.el 
  2314.       (minibuffer-help-form
  2315.        '(funcall myhelp))
  2316.       (myhelp
  2317.        #'(lambda ()
  2318.           (with-output-to-temp-buffer "*Help*"
  2319.         (prin1 var)
  2320.         (princ "\nDocumentation:\n")
  2321.         (princ (substring (documentation-property var 'variable-documentation)
  2322.                   1))
  2323.         (if (boundp var)
  2324.             (let ((print-length 20))
  2325.               (princ "\n\nCurrent value: ")
  2326.               (prin1 (symbol-value var))))
  2327.         nil))))
  2328.      (list var
  2329.        (let ((prop (get var 'variable-interactive)))
  2330.          (if prop
  2331.          ;; Use VAR's `variable-interactive' property
  2332.          ;; as an interactive spec for prompting.
  2333.          (call-interactively (list 'lambda '(arg)
  2334.                        (list 'interactive prop)
  2335.                        'arg))
  2336.            (eval-minibuffer (format "Set %s to value: " var)))))))
  2337.   (set var val))
  2338.  
  2339. (defun activate-region ()
  2340.   "Activate the region, if `zmacs-regions' is true.
  2341. Setting `zmacs-regions' to true causes LISPM-style active regions to be used.
  2342. This function has no effect if `zmacs-regions' is false."
  2343.   (interactive)
  2344.   (and zmacs-regions (zmacs-activate-region)))
  2345.  
  2346. (defsubst region-exists-p ()
  2347.   "Non-nil iff the region exists.
  2348. If active regions are in use (i.e. `zmacs-regions' is true), this means that
  2349.  the region is active.  Otherwise, this means that the user has pushed
  2350.  a mark in this buffer at some point in the past.
  2351. The functions `region-beginning' and `region-end' can be used to find the
  2352.  limits of the region."
  2353.   (not (null (mark))))
  2354.  
  2355. (defun region-active-p ()
  2356.   "Non-nil iff the region is active.
  2357. If `zmacs-regions' is true, this is equivalent to `region-exists-p'.
  2358. Otherwise, this function always returns false."
  2359.   (and zmacs-regions zmacs-region-extent))
  2360.  
  2361. (defun capitalize-region-or-word (arg)
  2362.   "Capitalize the selected region or the following word (or ARG words)."
  2363.   (interactive "p")
  2364.   (if (region-active-p) (capitalize-region (region-beginning) (region-end))
  2365.     (capitalize-word arg)))
  2366.  
  2367. (defun upcase-region-or-word (arg)
  2368.   "Upcase the selected region or the following word (or ARG words)."
  2369.   (interactive "p")
  2370.   (if (region-active-p) (upcase-region (region-beginning) (region-end))
  2371.     (upcase-word arg)))
  2372.  
  2373. (defun downcase-region-or-word (arg)
  2374.   "Downcase the selected region or the following word (or ARG words)."
  2375.   (interactive "p")
  2376.   (if (region-active-p) (downcase-region (region-beginning) (region-end))
  2377.     (downcase-word arg)))
  2378.  
  2379. ;;;
  2380. ;;; Most of the zmacs code is now in elisp.  The only thing left in C
  2381. ;;; are the variables zmacs-regions, zmacs-region-active-p and
  2382. ;;; zmacs-region-stays plus the function zmacs_update_region which
  2383. ;;; calls the lisp level zmacs-update-region.  It must remain since it
  2384. ;;; must be called by core C code.
  2385. ;;;
  2386.  
  2387. (defvar zmacs-activate-region-hook nil
  2388.   "Function or functions called when the region becomes active;
  2389. see the variable `zmacs-regions'.")
  2390.  
  2391. (defvar zmacs-deactivate-region-hook nil
  2392.   "Function or functions called when the region becomes inactive;
  2393. see the variable `zmacs-regions'.")
  2394.  
  2395. (defvar zmacs-update-region-hook nil
  2396.   "Function or functions called when the active region changes.
  2397. This is called after each command that sets `zmacs-region-stays' to t.
  2398. See the variable `zmacs-regions'.")
  2399.  
  2400. (defvar zmacs-region-extent nil
  2401.   "The extent of the zmacs region; don't use this.")
  2402.  
  2403. (defvar zmacs-region-rectangular-p nil
  2404.   "Whether the zmacs region is a rectangle; don't use this.")
  2405.  
  2406. (defun zmacs-make-extent-for-region (region)
  2407.   ;; Given a region, this makes an extent in the buffer which holds that
  2408.   ;; region, for highlighting purposes.  If the region isn't associated
  2409.   ;; with a buffer, this does nothing.
  2410.   (let ((buffer nil)
  2411.     (valid (and (extentp zmacs-region-extent)
  2412.             (extent-buffer zmacs-region-extent)
  2413.             (buffer-live-p (extent-buffer zmacs-region-extent))))
  2414.     start end)
  2415.     (cond ((consp region)
  2416.        (setq start (min (car region) (cdr region))
  2417.          end (max (car region) (cdr region))
  2418.          valid (and valid
  2419.                 (eq (marker-buffer (car region))
  2420.                 (extent-buffer zmacs-region-extent)))
  2421.          buffer (marker-buffer (car region))))
  2422.       (t
  2423.        (signal 'error (list "invalid region" region))))
  2424.  
  2425.     (if valid
  2426.     nil
  2427.       ;; The condition case is in case any of the extents are dead or
  2428.       ;; otherwise incapacitated.
  2429.       (condition-case ()
  2430.       (if (listp zmacs-region-extent)
  2431.           (mapcar 'delete-extent zmacs-region-extent)
  2432.         (delete-extent zmacs-region-extent))
  2433.     (error nil)))
  2434.  
  2435.     (if valid
  2436.     (set-extent-endpoints zmacs-region-extent start end)
  2437.       (setq zmacs-region-extent (make-extent start end buffer))
  2438.  
  2439.       ;; Make the extent be closed on the right, which means that if
  2440.       ;; characters are inserted exactly at the end of the extent, the
  2441.       ;; extent will grow to cover them.  This is important for shell
  2442.       ;; buffers - suppose one makes a region, and one end is at point-max.
  2443.       ;; If the shell produces output, that marker will remain at point-max
  2444.       ;; (its position will increase).  So it's important that the extent
  2445.       ;; exhibit the same behavior, lest the region covered by the extent
  2446.       ;; (the visual indication), and the region between point and mark
  2447.       ;; (the actual region value) become different!
  2448.       (set-extent-property zmacs-region-extent 'end-open nil)
  2449.  
  2450.       ;; use same priority as mouse-highlighting so that conflicts between
  2451.       ;; the region extent and a mouse-highlighted extent are resolved by
  2452.       ;; the usual size-and-endpoint-comparison method.
  2453.       (set-extent-priority zmacs-region-extent mouse-highlight-priority)
  2454.       (set-extent-face zmacs-region-extent 'zmacs-region)
  2455.  
  2456.       ;; #### It might be better to actually break
  2457.       ;; default-mouse-track-next-move-rect out of mouse.el so that we
  2458.       ;; can use its logic here.
  2459.       (cond
  2460.        (zmacs-region-rectangular-p
  2461.     (setq zmacs-region-extent (list zmacs-region-extent))
  2462.     (default-mouse-track-next-move-rect start end zmacs-region-extent)
  2463.     ))
  2464.  
  2465.       zmacs-region-extent)))
  2466.  
  2467. (defun zmacs-activate-region ()
  2468.   "Make the region between `point' and `mark' be active (highlighted),
  2469. if `zmacs-regions' is true.  Only a very small number of commands
  2470. should ever do this.  Calling this function will call the hook
  2471. `zmacs-activate-region-hook', if the region was previously inactive.
  2472. Calling this function ensures that the region stays active after the
  2473. current command terminates, even if `zmacs-region-stays' is not set.
  2474. Returns t if the region was activated (i.e. if `zmacs-regions' if t)."
  2475.   (if (not zmacs-regions)
  2476.       nil
  2477.     (setq zmacs-region-active-p t
  2478.       zmacs-region-stays t
  2479.       zmacs-region-rectangular-p (and (boundp 'mouse-track-rectangle-p)
  2480.                       mouse-track-rectangle-p))
  2481.     (if (marker-buffer (mark-marker t))
  2482.     (zmacs-make-extent-for-region (cons (point-marker t) (mark-marker t))))
  2483.     (run-hooks 'zmacs-activate-region-hook)
  2484.     t))
  2485.  
  2486. (defun zmacs-deactivate-region ()
  2487.   "Make the region between `point' and `mark' no longer be active,
  2488. if `zmacs-regions' is true.  You shouldn't need to call this; the
  2489. command loop calls it when appropriate.  Calling this function will
  2490. call the hook `zmacs-deactivate-region-hook', if the region was
  2491. previously active.  Returns t if the region had been active, nil
  2492. otherwise."
  2493.   (if (not zmacs-region-active-p)
  2494.       nil
  2495.     (setq zmacs-region-active-p nil
  2496.       zmacs-region-stays nil
  2497.       zmacs-region-rectangular-p nil)
  2498.     (if zmacs-region-extent
  2499.     (let ((inhibit-quit t))
  2500.       (if (listp zmacs-region-extent)
  2501.           (mapcar 'delete-extent zmacs-region-extent)
  2502.         (delete-extent zmacs-region-extent))
  2503.       (setq zmacs-region-extent nil)))
  2504.     (run-hooks 'zmacs-deactivate-region-hook)
  2505.     t))
  2506.  
  2507. (defun zmacs-update-region ()
  2508.   "Update the highlighted region between `point' and `mark'.
  2509. You shouldn't need to call this; the command loop calls it
  2510. when appropriate.  Calling this function will call the hook
  2511. `zmacs-update-region-hook', if the region is active."
  2512.   (if zmacs-region-active-p
  2513.       (progn
  2514.     (if (marker-buffer (mark-marker t))
  2515.         (zmacs-make-extent-for-region (cons (point-marker t)
  2516.                         (mark-marker t))))
  2517.     (run-hooks 'zmacs-update-region-hook))))
  2518.  
  2519. ;;;;;;
  2520. ;;;;;; echo area stuff
  2521. ;;;;;;
  2522.  
  2523. ;;; The `message-stack' is an alist of labels with messages; the first
  2524. ;;; message in this list is always in the echo area.  A call to
  2525. ;;; `display-message' inserts a label/message pair at the head of the
  2526. ;;; list, and removes any other pairs with that label.  Calling
  2527. ;;; `clear-message' causes any pair with matching label to be removed,
  2528. ;;; and this may cause the displayed message to change or vanish.  If
  2529. ;;; the label arg is nil, the entire message stack is cleared.
  2530. ;;;
  2531. ;;; Message/error filtering will be a little tricker to implement than
  2532. ;;; logging, since messages can be built up incrementally
  2533. ;;; using clear-message followed by repeated calls to append-message
  2534. ;;; (this happens with error messages).  For messages which aren't
  2535. ;;; created this way, filtering could be implemented at display-message
  2536. ;;; very easily.
  2537. ;;;
  2538. ;;; Bits of the logging code are borrowed from log-messages.el by
  2539. ;;; Robert Potter (rpotter@grip.cis.upenn.edu).
  2540.  
  2541. ;; need this to terminate the currently-displayed message
  2542. ;; ("Loading simple.el ...")
  2543. (and purify-flag (send-string-to-terminal "\n"))
  2544.  
  2545. (defvar message-stack nil
  2546.   "An alist of label/string pairs representing active echo-area messages.
  2547. The first element in the list is currently displayed in the echo area.
  2548. Do not modify this directly--use the `message' or 
  2549. `display-message'/`clear-message' functions.")
  2550.  
  2551. (defvar remove-message-hook 'log-message
  2552.   "A function or list of functions to be called when a message is removed
  2553. from the echo area at the bottom of the frame.  The label of the removed
  2554. message is passed as the first argument, and the text of the message
  2555. as the second argument.")
  2556.  
  2557. (defvar log-message-max-size 50000
  2558.   "Maximum size of the \" *Message-Log*\" buffer.  See `log-message'.")
  2559.  
  2560. (defvar log-message-ignore-regexps
  2561.   '("^Mark set$"
  2562.     "^Undo!$"
  2563.     "^Quit$"
  2564.     "^\\(Beginning\\|End\\) of buffer$"
  2565.     "^Fontifying"
  2566.     "^\\(Failing \\)?\\([Ww]rapped \\)?\\([Rr]egexp \\)?I-search\\( backward\\)?:"
  2567.     "^Mark saved where search started$"
  2568.     "^Making completion list"
  2569.     "^Matches "                    ; paren-matching message
  2570.     "^Type .* to \\(remove help\\|restore the other\\) window."
  2571.     "^M-x .* (bound to key"            ; teach-extended-commands
  2572.     "^(No changes need to be saved)$"
  2573.     "^(No files need saving)$"
  2574.     "^\\(Parsing messages\\|Reading attributes\\|Generating summary\\|Building threads\\|Converting\\)\\.\\.\\. [0-9]+$"    ; vm
  2575.     "^End of message \d+"            ; vm
  2576.     "^Parsing error messages\\.\\.\\.[0-9]+"    ; compile
  2577.     "^Parsed [0-9]+ of [0-9]+ ([0-9]+%)$"    ; w3
  2578.     "^\\(Formatting Summary\\|Reading active file\\|Checking new news\\|Looking for crossposts\\|Marking crossposts\\|MHSPOOL:\\|NNSPOOL:\\|NNTP:\\|\\(Uns\\|S\\)ubscribing new newsgroups\\)\\.\\.\\. *[0-9]+%$"    ; gnus
  2579.     "^Adding glyphs\\.\\.\\. ([0-9]+%)\\( done\\)?$"    ; outl-mouse
  2580.     "^->"                        ; bbdb prompt
  2581.     )
  2582.   "List of regular expressions matching messages which shouldn't be logged.
  2583. See `log-message'.  
  2584.  
  2585. Ideally, packages which generate messages which might need to be ignored
  2586. should label them with 'progress, 'prompt, or 'no-log, so they can be 
  2587. filtered by the log-message-ignore-labels.")
  2588.  
  2589. (defvar log-message-ignore-labels 
  2590.   '(help-echo command progress prompt no-log garbage-collecting auto-saving)
  2591.   "List of symbols indicating labels of messages which shouldn't be logged.
  2592. See `display-message' for some common labels.  See also `log-message'.")
  2593.  
  2594. (defun show-message-log ()
  2595.   "Show the \" *Message-Log*\" buffer, which contains old messages and errors."
  2596.   (interactive)
  2597.   (pop-to-buffer " *Message-Log*"))
  2598.  
  2599. (defvar log-message-filter-function 'log-message-filter
  2600.   "Value must be a function of two arguments: a symbol (label) and 
  2601. a string (messsage).  It should return non-nil to indicate a message
  2602. should be logged.  Possible values include 'log-message-filter and
  2603. 'log-message-filter-errors-only.")
  2604.  
  2605. (defun log-message-filter (label message)
  2606.   "Default value of log-message-filter-function.
  2607. Mesages whose text matches one of the log-message-ignore-regexps
  2608. or whose label appears in log-message-ignore-labels are not saved."
  2609.   (let ((r  log-message-ignore-regexps)
  2610.     (ok (not (memq label log-message-ignore-labels))))
  2611.     (while (and r ok)
  2612.       (if (save-match-data (string-match (car r) message))
  2613.       (setq ok nil))
  2614.       (setq r (cdr r)))
  2615.     ok))
  2616.  
  2617. (defun log-message-filter-errors-only (label message)
  2618.   "For use as the log-message-filter-function.  Only logs error messages."
  2619.   (eq label 'error))
  2620.  
  2621. (defun log-message (label message)
  2622.   "Stuff a copy of the message into the \" *Message-Log*\" buffer,
  2623. if it satisfies the log-message-filter-function.
  2624.  
  2625. For use on remove-message-hook."
  2626.   (if (and (not noninteractive)
  2627.        (funcall log-message-filter-function label message))
  2628.       (save-excursion
  2629.     (set-buffer (get-buffer-create " *Message-Log*"))
  2630.     (goto-char (point-max))
  2631.     ;; (insert (concat (upcase (symbol-name label)) ": "  message "\n"))
  2632.     (insert message "\n")
  2633.     (if (> (point-max) (max log-message-max-size (point-min)))
  2634.         (progn
  2635.           ;; trim log to ~90% of max size
  2636.           (goto-char (max (- (point-max)
  2637.                  (truncate (* 0.9 log-message-max-size)))
  2638.                   (point-min)))
  2639.           (forward-line 1)
  2640.           (delete-region (point-min) (point)))))))
  2641.  
  2642. (defun message-displayed-p (&optional return-string frame)
  2643.   "Return a non-nil value if a message is presently displayed in the\n\
  2644. minibuffer's echo area.  If optional argument RETURN-STRING is non-nil,\n\
  2645. return a string containing the message, otherwise just return t."
  2646.   ;; by definition, a message is displayed if the echo area buffer is
  2647.   ;; non-empty (see also echo_area_active()).  It had better also
  2648.   ;; be the case that message-stack is nil exactly when the echo area
  2649.   ;; is non-empty.
  2650.   (let ((buffer (get-buffer " *Echo Area*")))
  2651.     (and (< (point-min buffer) (point-max buffer))
  2652.      (if return-string
  2653.          (buffer-substring nil nil buffer)
  2654.        t))))
  2655.  
  2656. ;;; Returns the string which remains in the echo area, or nil if none.
  2657. ;;; If label is nil, the whole message stack is cleared.
  2658. (defun clear-message (&optional label frame stdout-p no-restore)
  2659.   "Remove any message with the given LABEL from the message-stack,
  2660. erasing it from the echo area if it's currently displayed there.
  2661. If a message remains at the head of the message-stack and NO-RESTORE
  2662. is nil, it will be displayed.  The string which remains in the echo
  2663. area will be returned, or nil if the message-stack is now empty.
  2664. If LABEL is nil, the entire message-stack is cleared.
  2665.  
  2666. Unless you need the return value or you need to specify a lable,
  2667. you should just use (message nil)."
  2668.   (or frame (setq frame (selected-frame)))
  2669.   (let ((clear-stream  (and message-stack (eq 'stream (frame-type frame)))))
  2670.     (remove-message label frame)
  2671.     (let ((buffer (get-buffer " *Echo Area*"))
  2672.       (zmacs-region-stays zmacs-region-stays)) ; preserve from change
  2673.       (erase-buffer buffer))
  2674.     (if clear-stream
  2675.     (send-string-to-terminal ?\n stdout-p))
  2676.     (if no-restore
  2677.     nil            ; just preparing to put another msg up
  2678.       (if message-stack
  2679.       (let ((oldmsg  (cdr (car message-stack))))
  2680.         (raw-append-message oldmsg frame stdout-p)
  2681.         oldmsg)
  2682.     ;; ### should we (redisplay-echo-area) here?  messes some things up.
  2683.     nil))))
  2684.  
  2685. (defun remove-message (&optional label frame)
  2686.   ;; If label is nil, we want to remove all matching messages.
  2687.   ;; Must reverse the stack first to log them in the right order.
  2688.   (let ((log nil))
  2689.     (while (and message-stack
  2690.         (or (null label)    ; null label means clear whole stack
  2691.             (eq label (car (car message-stack)))))
  2692.       (setq log (cons (car message-stack) log))
  2693.     (setq message-stack (cdr message-stack)))
  2694.     (let ((s  message-stack))
  2695.       (while (cdr s)
  2696.     (let ((msg (car (cdr s))))
  2697.       (if (eq label (car msg))
  2698.           (progn
  2699.         (setq log (cons msg log))
  2700.         (setcdr s (cdr (cdr s))))
  2701.         (setq s (cdr s))))))
  2702.     ;; (possibly) log each removed message
  2703.     (while log
  2704.       (condition-case e
  2705.       (run-hook-with-args 'remove-message-hook
  2706.                   (car (car log)) (cdr (car log)))
  2707.     (error (setq remove-message-hook nil)
  2708.            (message "remove-message-hook error: %s" e)
  2709.            (sit-for 2)
  2710.            (erase-buffer (get-buffer " *Echo Area*"))
  2711.            (signal (car e) (cdr e))))
  2712.       (setq log (cdr log)))))
  2713.  
  2714. (defun append-message (label message &optional frame stdout-p)
  2715.   (or frame (setq frame (selected-frame)))
  2716.   ;; add a new entry to the message-stack, or modify an existing one
  2717.   (let ((top (car message-stack)))
  2718.     (if (eq label (car top))
  2719.     (setcdr top (concat (cdr top) message))
  2720.       (setq message-stack (cons (cons label message) message-stack))))
  2721.   (raw-append-message message frame stdout-p))
  2722.  
  2723. ;; really append the message to the echo area.  no fiddling with message-stack.
  2724. (defun raw-append-message (message &optional frame stdout-p)
  2725.   (if (eq message "") nil
  2726.     (let ((buffer (get-buffer " *Echo Area*"))
  2727.       (zmacs-region-stays zmacs-region-stays)) ; preserve from change
  2728.       (save-excursion
  2729.     (set-buffer buffer)
  2730.     (insert message))
  2731.       ;; Conditionalizing on the device type in this way is not that clean,
  2732.       ;; but neither is having a device method, as I originally implemented
  2733.       ;; it: all non-stream devices behave in the same way.  Perhaps
  2734.       ;; the cleanest way is to make the concept of a "redisplayable"
  2735.       ;; device, which stream devices are not.  Look into this more if
  2736.       ;; we ever create another non-redisplayable device type (e.g.
  2737.       ;; processes?  printers?).
  2738.       (if (eq 'stream (frame-type frame))
  2739.       (send-string-to-terminal message stdout-p)
  2740.     (redisplay-echo-area)))))
  2741.  
  2742. (defun display-message (label message &optional frame stdout-p)
  2743.   "Print a one-line message at the bottom of the frame.  First argument
  2744. LABEL is an identifier for this message.  MESSAGE is the string to display.
  2745. Use `clear-message' to remove a labelled message.
  2746.  
  2747. Here are some standard labels (those marked with `*' are not logged
  2748. by default--see the `log-message-ignore-labels' variable):
  2749.     message       default label used by the `message' function
  2750.     error         default label used for reporting errors
  2751.   * progress      progress indicators like \"Converting... 45%\"
  2752.   * prompt        prompt-like messages like \"I-search: foo\"
  2753.   * no-log        messages that should never be logged"
  2754.   (clear-message label frame stdout-p t)
  2755.   (append-message label message frame stdout-p))
  2756.  
  2757. ;;; may eventually be frame-dependent
  2758. (defun current-message-label (frame)
  2759.   (if message-stack
  2760.       (car (car message-stack))
  2761.     nil))
  2762.  
  2763. (defun message (fmt &rest args)
  2764.   "Print a one-line message at the bottom of the frame.
  2765. The arguments are the same as to `format'.
  2766.  
  2767. If the only argument is nil, clear any existing message; let the
  2768. minibuffer contents show."
  2769.   ;; questionable junk in the C code
  2770.   ;; (if (framep default-minibuffer-frame)
  2771.   ;;     (make-frame-visible default-minibuffer-frame))
  2772.   (if (and (null fmt) (null args))
  2773.       (progn
  2774.     (clear-message nil)
  2775.     nil)
  2776.     (let ((str (apply 'format fmt args)))
  2777.       (display-message 'message str)
  2778.       str)))
  2779.  
  2780. ;;;;;;
  2781. ;;;;;; warning stuff
  2782. ;;;;;;
  2783.  
  2784. (defvar log-warning-minimum-level 'info
  2785.   "Minimum level of warnings that should be logged.
  2786. The warnings in levels below this are completely ignored, as if they never
  2787. happened.
  2788.  
  2789. The recognized warning levels, in decreasing order of priority, are
  2790. 'emergency, 'alert, 'critical, 'error, 'warning, 'notice, 'info, and
  2791. 'debug.
  2792.  
  2793. See also `display-warning-minimum-level'.
  2794.  
  2795. You can also control which warnings are displayed on a class-by-class
  2796. basis.  See `display-warning-suppressed-classes' and
  2797. `log-warning-suppressed-classes'.")
  2798.  
  2799. (defvar display-warning-minimum-level 'info
  2800.   "Minimum level of warnings that should be displayed.
  2801. The warnings in levels below this are completely ignored, as if they never
  2802. happened.
  2803.  
  2804. The recognized warning levels, in decreasing order of priority, are
  2805. 'emergency, 'alert, 'critical, 'error, 'warning, 'notice, 'info, and
  2806. 'debug.
  2807.  
  2808. See also `log-warning-minimum-level'.
  2809.  
  2810. You can also control which warnings are displayed on a class-by-class
  2811. basis.  See `display-warning-suppressed-classes' and
  2812. `log-warning-suppressed-classes'.")
  2813.  
  2814. (defvar log-warning-suppressed-classes nil
  2815.   "List of classes of warnings that shouldn't be logged or displayed.
  2816. If any of the CLASS symbols associated with a warning is the same as
  2817. any of the symbols listed here, the warning will be completely ignored,
  2818. as it they never happened.
  2819.  
  2820. NOTE: In most circumstances, you should *not* set this variable.
  2821. Set `display-warning-suppressed-classes' instead.  That way the suppressed
  2822. warnings are not displayed but are still unobtrusively logged.
  2823.  
  2824. See also `log-warning-minimum-level' and `display-warning-minimum-level'.")
  2825.  
  2826. (defvar display-warning-suppressed-classes nil
  2827.   "List of classes of warnings that shouldn't be displayed.
  2828. If any of the CLASS symbols associated with a warning is the same as
  2829. any of the symbols listed here, the warning will not be displayed.
  2830. The warning will still logged in the *Warnings* buffer (unless also
  2831. contained in `log-warning-suppressed-classes'), but the buffer will
  2832. not be automatically popped up.
  2833.  
  2834. See also `log-warning-minimum-level' and `display-warning-minimum-level'.")
  2835.  
  2836. (defvar warning-count 0
  2837.   "Count of the number of warning messages displayed so far.")
  2838.  
  2839. (defconst warning-level-alist '((emergency . 8)
  2840.                 (alert . 7)
  2841.                 (critical . 6)
  2842.                 (error . 5)
  2843.                 (warning . 4)
  2844.                 (notice . 3)
  2845.                 (info . 2)
  2846.                 (debug . 1)))
  2847.  
  2848. (defun warning-level-p (level)
  2849.   "Non-nil if LEVEL specifies a warning level."
  2850.   (and (symbolp level) (assq level warning-level-alist)))
  2851.  
  2852. ;; If you're interested in rewriting this function, be aware that it
  2853. ;; could be called at arbitrary points in a Lisp program (when a
  2854. ;; built-in function wants to issue a warning, it will call out to
  2855. ;; this function the next time some Lisp code is evaluated).  Therefore,
  2856. ;; this function *must* not permanently modify any global variables
  2857. ;; (e.g. the current buffer) except those that specifically apply
  2858. ;; to the warning system.
  2859.  
  2860. (defvar before-init-deferred-warnings nil)
  2861.  
  2862. (defun after-init-display-warnings ()
  2863.   "Display warnings deferred till after the init file is run.
  2864. Warnings that occur before then are deferred so that warning
  2865. suppression in the .emacs file will be honored."
  2866.   (while before-init-deferred-warnings
  2867.     (apply 'display-warning (car before-init-deferred-warnings))
  2868.     (setq before-init-deferred-warnings
  2869.       (cdr before-init-deferred-warnings))))
  2870.  
  2871. (add-hook 'after-init-hook 'after-init-display-warnings)
  2872.  
  2873. (defun display-warning (class message &optional level)
  2874.   "Display a warning message.
  2875. CLASS should be a symbol describing what sort of warning this is, such
  2876. as `resource' or `key-mapping'.  A list of such symbols is also
  2877. accepted. (Individual classes can be suppressed; see
  2878. `display-warning-suppressed-classes'.) Optional argument LEVEL can
  2879. be used to specify a priority for the warning, other than default priority
  2880. `warning'. (See `display-warning-minimum-level').  The message is
  2881. inserted into the *Warnings* buffer, which is made visible at appropriate
  2882. times."
  2883.   (or level (setq level 'warning))
  2884.   (or (listp class) (setq class (list class)))
  2885.   (check-argument-type 'warning-level-p level)
  2886.   (if (not init-file-loaded)
  2887.       (setq before-init-deferred-warnings
  2888.         (cons (list class message level) before-init-deferred-warnings))
  2889.     (catch 'ignored
  2890.       (let ((display-p t)
  2891.         (level-num (cdr (assq level warning-level-alist))))
  2892.     (if (< level-num (cdr (assq log-warning-minimum-level
  2893.                     warning-level-alist)))
  2894.         (throw 'ignored nil))
  2895.     (if (intersection class log-warning-suppressed-classes)
  2896.         (throw 'ignored nil))
  2897.     
  2898.     (if (< level-num (cdr (assq display-warning-minimum-level
  2899.                     warning-level-alist)))
  2900.         (setq display-p nil))
  2901.     (if (and display-p
  2902.          (intersection class display-warning-suppressed-classes))
  2903.         (setq display-p nil))
  2904.     (save-excursion
  2905.       (let ((buffer (get-buffer-create "*Warnings*")))
  2906.         (if display-p
  2907.         ;; The C code looks at display-warning-tick to determine
  2908.         ;; when it should call `display-warning-buffer'.  Change it
  2909.         ;; to get the C code's attention.
  2910.         (setq display-warning-tick (1+ display-warning-tick)))
  2911.         (set-buffer buffer)
  2912.         (goto-char (point-max))
  2913.         (setq warning-count (1+ warning-count))
  2914.         (princ (format "(%d) (%s/%s) "
  2915.                warning-count
  2916.                (mapconcat 'symbol-name class ",")
  2917.                level) buffer)
  2918.         (princ message buffer)
  2919.         (terpri buffer)
  2920.         (terpri buffer)))))))
  2921.  
  2922. (defun warn (&rest args)
  2923.   "Display a warning message.
  2924. The message is constructed by passing all args to `format'.  The message
  2925. is placed in the *Warnings* buffer, which will be popped up at the next
  2926. redisplay.  The class of the warning is `warning'.  See also
  2927. `display-warning'."
  2928.   (display-warning 'warning (apply 'format args)))
  2929.  
  2930. (defvar warning-marker nil)
  2931.  
  2932. ;; When this function is called by the C code, all non-local exits are
  2933. ;; trapped and C-g is inhibited; therefore, it would be a very, very
  2934. ;; bad idea for this function to get into an infinite loop.
  2935.  
  2936. (defun display-warning-buffer ()
  2937.   "Make the buffer that contains the warnings be visible.
  2938. The C code calls this periodically, right before redisplay."
  2939.   (let ((buffer (get-buffer-create "*Warnings*")))
  2940.     (if (not warning-marker)
  2941.     (progn
  2942.       (setq warning-marker (make-marker))
  2943.       (set-marker warning-marker 1 buffer)))
  2944.     (set-window-start (display-buffer buffer) warning-marker)
  2945.     (set-marker warning-marker (point-max buffer) buffer)))
  2946.