comparison lisp/simple.el @ 209:41ff10fd062f r20-4b3

Import from CVS: tag r20-4b3
author cvs
date Mon, 13 Aug 2007 10:04:58 +0200
parents
children 1f0dabaa0855
comparison
equal deleted inserted replaced
208:f427b8ec4379 209:41ff10fd062f
1 ;;; simple.el --- basic editing commands for XEmacs
2
3 ;; Copyright (C) 1985-7, 1993-5, 1997 Free Software Foundation, Inc.
4 ;; Copyright (C) 1995 Tinker Systems and INS Engineering Corp.
5
6 ;; Maintainer: XEmacs Development Team
7 ;; Keywords: lisp, extensions, internal, dumped
8
9 ;; This file is part of XEmacs.
10
11 ;; XEmacs is free software; you can redistribute it and/or modify it
12 ;; under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 2, or (at your option)
14 ;; any later version.
15
16 ;; XEmacs is distributed in the hope that it will be useful, but
17 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 ;; General Public License for more details.
20
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with XEmacs; see the file COPYING. If not, write to the Free
23 ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
24 ;; 02111-1307, USA.
25
26 ;;; Synched up with: FSF 19.34 [But not very closely].
27
28 ;;; Commentary:
29
30 ;; This file is dumped with XEmacs.
31
32 ;; A grab-bag of basic XEmacs commands not specifically related to some
33 ;; major mode or to file-handling.
34
35 ;; Changes for zmacs-style active-regions:
36 ;;
37 ;; beginning-of-buffer, end-of-buffer, count-lines-region,
38 ;; count-lines-buffer, what-line, what-cursor-position, set-goal-column,
39 ;; set-fill-column, prefix-arg-internal, and line-move (which is used by
40 ;; next-line and previous-line) set zmacs-region-stays to t, so that they
41 ;; don't affect the current region-hilighting state.
42 ;;
43 ;; mark-whole-buffer, mark-word, exchange-point-and-mark, and
44 ;; set-mark-command (without an argument) call zmacs-activate-region.
45 ;;
46 ;; mark takes an optional arg like the new Fmark_marker() does. When
47 ;; the region is not active, mark returns nil unless the optional arg is true.
48 ;;
49 ;; push-mark, pop-mark, exchange-point-and-mark, and set-marker, and
50 ;; set-mark-command use (mark t) so that they can access the mark whether
51 ;; the region is active or not.
52 ;;
53 ;; shell-command, shell-command-on-region, yank, and yank-pop (which all
54 ;; push a mark) have been altered to call exchange-point-and-mark with an
55 ;; argument, meaning "don't activate the region". These commands only use
56 ;; exchange-point-and-mark to position the newly-pushed mark correctly, so
57 ;; this isn't a user-visible change. These functions have also been altered
58 ;; to use (mark t) for the same reason.
59
60 ;; 97/3/14 Jareth Hein (jhod@po.iijnet.or.jp) added kinsoku processing (support
61 ;; for filling of Asian text) into the fill code. This was ripped bleeding from
62 ;; Mule-2.3, and could probably use some feature additions (like additional wrap
63 ;; styles, etc)
64
65 ;; 97/06/11 Steve Baur (steve@altair.xemacs.org) Convert use of
66 ;; (preceding|following)-char to char-(after|before).
67
68 ;;; Code:
69
70 (defgroup editing-basics nil
71 "Most basic editing variables."
72 :group 'editing)
73
74 (defgroup killing nil
75 "Killing and yanking commands."
76 :group 'editing)
77
78 (defgroup fill-comments nil
79 "Indenting and filling of comments."
80 :prefix "comment-"
81 :group 'fill)
82
83 (defgroup paren-matching nil
84 "Highlight (un)matching of parens and expressions."
85 :prefix "paren-"
86 :group 'matching)
87
88 (defgroup log-message nil
89 "Messages logging and display customizations."
90 :group 'minibuffer)
91
92 (defgroup warnings nil
93 "Warnings customizations."
94 :group 'minibuffer)
95
96
97 (defun newline (&optional arg)
98 "Insert a newline, and move to left margin of the new line if it's blank.
99 The newline is marked with the text-property `hard'.
100 With arg, insert that many newlines.
101 In Auto Fill mode, if no numeric arg, break the preceding line if it's long."
102 (interactive "*P")
103 (barf-if-buffer-read-only nil (point))
104 ;; Inserting a newline at the end of a line produces better redisplay in
105 ;; try_window_id than inserting at the beginning of a line, and the textual
106 ;; result is the same. So, if we're at beginning of line, pretend to be at
107 ;; the end of the previous line.
108 (let ((flag (and (not (bobp))
109 (bolp)
110 ;; Make sure the newline before point isn't intangible.
111 (not (get-char-property (1- (point)) 'intangible))
112 ;; Make sure the newline before point isn't read-only.
113 (not (get-char-property (1- (point)) 'read-only))
114 ;; Make sure the newline before point isn't invisible.
115 (not (get-char-property (1- (point)) 'invisible))
116 ;; This should probably also test for the previous char
117 ;; being the *last* character too.
118 (not (get-char-property (1- (point)) 'end-open))
119 ;; Make sure the newline before point has the same
120 ;; properties as the char before it (if any).
121 (< (or (previous-extent-change (point)) -2)
122 (- (point) 2))))
123 (was-page-start (and (bolp)
124 (looking-at page-delimiter)))
125 (beforepos (point)))
126 (if flag (backward-char 1))
127 ;; Call self-insert so that auto-fill, abbrev expansion etc. happens.
128 ;; Set last-command-char to tell self-insert what to insert.
129 (let ((last-command-char ?\n)
130 ;; Don't auto-fill if we have a numeric argument.
131 ;; Also not if flag is true (it would fill wrong line);
132 ;; there is no need to since we're at BOL.
133 (auto-fill-function (if (or arg flag) nil auto-fill-function)))
134 (unwind-protect
135 (self-insert-command (prefix-numeric-value arg))
136 ;; If we get an error in self-insert-command, put point at right place.
137 (if flag (forward-char 1))))
138 ;; If we did *not* get an error, cancel that forward-char.
139 (if flag (backward-char 1))
140 ;; Mark the newline(s) `hard'.
141 (if use-hard-newlines
142 (let* ((from (- (point) (if arg (prefix-numeric-value arg) 1)))
143 (sticky (get-text-property from 'end-open))) ; XEmacs
144 (put-text-property from (point) 'hard 't)
145 ;; If end-open is not "t", add 'hard to end-open list
146 (if (and (listp sticky) (not (memq 'hard sticky)))
147 (put-text-property from (point) 'end-open ; XEmacs
148 (cons 'hard sticky)))))
149 ;; If the newline leaves the previous line blank,
150 ;; and we have a left margin, delete that from the blank line.
151 (or flag
152 (save-excursion
153 (goto-char beforepos)
154 (beginning-of-line)
155 (and (looking-at "[ \t]$")
156 (> (current-left-margin) 0)
157 (delete-region (point) (progn (end-of-line) (point))))))
158 (if flag (forward-char 1))
159 ;; Indent the line after the newline, except in one case:
160 ;; when we added the newline at the beginning of a line
161 ;; which starts a page.
162 (or was-page-start
163 (move-to-left-margin nil t)))
164 nil)
165
166 (defun open-line (arg)
167 "Insert a newline and leave point before it.
168 If there is a fill prefix and/or a left-margin, insert them on the new line
169 if the line would have been blank.
170 With arg N, insert N newlines."
171 (interactive "*p")
172 (let* ((do-fill-prefix (and fill-prefix (bolp)))
173 (do-left-margin (and (bolp) (> (current-left-margin) 0)))
174 (loc (point)))
175 (newline arg)
176 (goto-char loc)
177 (while (> arg 0)
178 (cond ((bolp)
179 (if do-left-margin (indent-to (current-left-margin)))
180 (if do-fill-prefix (insert fill-prefix))))
181 (forward-line 1)
182 (setq arg (1- arg)))
183 (goto-char loc)
184 (end-of-line)))
185
186 (defun split-line ()
187 "Split current line, moving portion beyond point vertically down."
188 (interactive "*")
189 (skip-chars-forward " \t")
190 (let ((col (current-column))
191 (pos (point)))
192 (newline 1)
193 (indent-to col 0)
194 (goto-char pos)))
195
196 (defun quoted-insert (arg)
197 "Read next input character and insert it.
198 This is useful for inserting control characters.
199 You may also type up to 3 octal digits, to insert a character with that code.
200
201 In overwrite mode, this function inserts the character anyway, and
202 does not handle octal digits specially. This means that if you use
203 overwrite as your normal editing mode, you can use this function to
204 insert characters when necessary.
205
206 In binary overwrite mode, this function does overwrite, and octal
207 digits are interpreted as a character code. This is supposed to make
208 this function useful in editing binary files."
209 (interactive "*p")
210 (let ((char (if (or (not overwrite-mode)
211 (eq overwrite-mode 'overwrite-mode-binary))
212 (read-quoted-char)
213 (read-char))))
214 (if (> arg 0)
215 (if (eq overwrite-mode 'overwrite-mode-binary)
216 (delete-char arg)))
217 (while (> arg 0)
218 (insert char)
219 (setq arg (1- arg)))))
220
221 (defun delete-indentation (&optional arg)
222 "Join this line to previous and fix up whitespace at join.
223 If there is a fill prefix, delete it from the beginning of this line.
224 With argument, join this line to following line."
225 (interactive "*P")
226 (beginning-of-line)
227 (if arg (forward-line 1))
228 (if (eq (char-before (point)) ?\n)
229 (progn
230 (delete-region (point) (1- (point)))
231 ;; If the second line started with the fill prefix,
232 ;; delete the prefix.
233 (if (and fill-prefix
234 (<= (+ (point) (length fill-prefix)) (point-max))
235 (string= fill-prefix
236 (buffer-substring (point)
237 (+ (point) (length fill-prefix)))))
238 (delete-region (point) (+ (point) (length fill-prefix))))
239 (fixup-whitespace))))
240
241 (defun fixup-whitespace ()
242 "Fixup white space between objects around point.
243 Leave one space or none, according to the context."
244 (interactive "*")
245 (save-excursion
246 (delete-horizontal-space)
247 (if (or (looking-at "^\\|\\s)")
248 (save-excursion (forward-char -1)
249 (looking-at "$\\|\\s(\\|\\s'")))
250 nil
251 (insert ?\ ))))
252
253 (defun delete-horizontal-space ()
254 "Delete all spaces and tabs around point."
255 (interactive "*")
256 (skip-chars-backward " \t")
257 (delete-region (point) (progn (skip-chars-forward " \t") (point))))
258
259 (defun just-one-space ()
260 "Delete all spaces and tabs around point, leaving one space."
261 (interactive "*")
262 (if abbrev-mode ; XEmacs
263 (expand-abbrev))
264 (skip-chars-backward " \t")
265 (if (eq (char-after (point)) ? ) ; XEmacs
266 (forward-char 1)
267 (insert ? ))
268 (delete-region (point) (progn (skip-chars-forward " \t") (point))))
269
270 (defun delete-blank-lines ()
271 "On blank line, delete all surrounding blank lines, leaving just one.
272 On isolated blank line, delete that one.
273 On nonblank line, delete any immediately following blank lines."
274 (interactive "*")
275 (let (thisblank singleblank)
276 (save-excursion
277 (beginning-of-line)
278 (setq thisblank (looking-at "[ \t]*$"))
279 ;; Set singleblank if there is just one blank line here.
280 (setq singleblank
281 (and thisblank
282 (not (looking-at "[ \t]*\n[ \t]*$"))
283 (or (bobp)
284 (progn (forward-line -1)
285 (not (looking-at "[ \t]*$")))))))
286 ;; Delete preceding blank lines, and this one too if it's the only one.
287 (if thisblank
288 (progn
289 (beginning-of-line)
290 (if singleblank (forward-line 1))
291 (delete-region (point)
292 (if (re-search-backward "[^ \t\n]" nil t)
293 (progn (forward-line 1) (point))
294 (point-min)))))
295 ;; Delete following blank lines, unless the current line is blank
296 ;; and there are no following blank lines.
297 (if (not (and thisblank singleblank))
298 (save-excursion
299 (end-of-line)
300 (forward-line 1)
301 (delete-region (point)
302 (if (re-search-forward "[^ \t\n]" nil t)
303 (progn (beginning-of-line) (point))
304 (point-max)))))
305 ;; Handle the special case where point is followed by newline and eob.
306 ;; Delete the line, leaving point at eob.
307 (if (looking-at "^[ \t]*\n\\'")
308 (delete-region (point) (point-max)))))
309
310 (defun back-to-indentation ()
311 "Move point to the first non-whitespace character on this line."
312 ;; XEmacs change
313 (interactive "_")
314 (beginning-of-line 1)
315 (skip-chars-forward " \t"))
316
317 (defun newline-and-indent ()
318 "Insert a newline, then indent according to major mode.
319 Indentation is done using the value of `indent-line-function'.
320 In programming language modes, this is the same as TAB.
321 In some text modes, where TAB inserts a tab, this command indents to the
322 column specified by the function `current-left-margin'."
323 (interactive "*")
324 (delete-region (point) (progn (skip-chars-backward " \t") (point)))
325 (newline)
326 (indent-according-to-mode))
327
328 (defun reindent-then-newline-and-indent ()
329 "Reindent current line, insert newline, then indent the new line.
330 Indentation of both lines is done according to the current major mode,
331 which means calling the current value of `indent-line-function'.
332 In programming language modes, this is the same as TAB.
333 In some text modes, where TAB inserts a tab, this indents to the
334 column specified by the function `current-left-margin'."
335 (interactive "*")
336 (save-excursion
337 (delete-region (point) (progn (skip-chars-backward " \t") (point)))
338 (indent-according-to-mode))
339 (newline)
340 (indent-according-to-mode))
341
342 ;; Internal subroutine of delete-char
343 (defun kill-forward-chars (arg)
344 (if (listp arg) (setq arg (car arg)))
345 (if (eq arg '-) (setq arg -1))
346 (kill-region (point) (+ (point) arg)))
347
348 ;; Internal subroutine of backward-delete-char
349 (defun kill-backward-chars (arg)
350 (if (listp arg) (setq arg (car arg)))
351 (if (eq arg '-) (setq arg -1))
352 (kill-region (point) (- (point) arg)))
353
354 (defun backward-delete-char-untabify (arg &optional killp)
355 "Delete characters backward, changing tabs into spaces.
356 Delete ARG chars, and kill (save in kill ring) if KILLP is non-nil.
357 Interactively, ARG is the prefix arg (default 1)
358 and KILLP is t if a prefix arg was specified."
359 (interactive "*p\nP")
360 (let ((count arg))
361 (save-excursion
362 (while (and (> count 0) (not (bobp)))
363 (if (eq (char-before (point)) ?\t) ; XEmacs
364 (let ((col (current-column)))
365 (forward-char -1)
366 (setq col (- col (current-column)))
367 (insert-char ?\ col)
368 (delete-char 1)))
369 (forward-char -1)
370 (setq count (1- count)))))
371 (delete-backward-char arg killp)
372 ;; XEmacs: In overwrite mode, back over columns while clearing them out,
373 ;; unless at end of line.
374 (and overwrite-mode (not (eolp))
375 (save-excursion (insert-char ?\ arg))))
376
377 (defcustom delete-key-deletes-forward nil
378 "*If non-nil, the DEL key will erase one character forwards.
379 If nil, the DEL key will erase one character backwards."
380 :type 'boolean
381 :group 'editing-basics)
382
383 (defun backward-or-forward-delete-char (arg)
384 "Delete either one character backwards or one character forwards.
385 Controlled by the state of `delete-key-deletes-forward' and whether the
386 BackSpace keysym even exists on your keyboard. If you don't have a
387 BackSpace keysym, the delete key should always delete one character
388 backwards."
389 (interactive "*p")
390 (if (and delete-key-deletes-forward
391 (or (eq 'tty (device-type))
392 (x-keysym-on-keyboard-p "BackSpace")))
393 (delete-char arg)
394 (delete-backward-char arg)))
395
396 (defun backward-or-forward-kill-word (arg)
397 "Delete either one word backwards or one word forwards.
398 Controlled by the state of `delete-key-deletes-forward' and whether the
399 BackSpace keysym even exists on your keyboard. If you don't have a
400 BackSpace keysym, the delete key should always delete one character
401 backwards."
402 (interactive "*p")
403 (if (and delete-key-deletes-forward
404 (or (eq 'tty (device-type))
405 (x-keysym-on-keyboard-p "BackSpace")))
406 (kill-word arg)
407 (backward-kill-word arg)))
408
409 (defun backward-or-forward-kill-sentence (arg)
410 "Delete either one sentence backwards or one sentence forwards.
411 Controlled by the state of `delete-key-deletes-forward' and whether the
412 BackSpace keysym even exists on your keyboard. If you don't have a
413 BackSpace keysym, the delete key should always delete one character
414 backwards."
415 (interactive "*P")
416 (if (and delete-key-deletes-forward
417 (or (eq 'tty (device-type))
418 (x-keysym-on-keyboard-p "BackSpace")))
419 (kill-sentence arg)
420 (backward-kill-sentence (prefix-numeric-value arg))))
421
422 (defun backward-or-forward-kill-sexp (arg)
423 "Delete either one sexpr backwards or one sexpr forwards.
424 Controlled by the state of `delete-key-deletes-forward' and whether the
425 BackSpace keysym even exists on your keyboard. If you don't have a
426 BackSpace keysym, the delete key should always delete one character
427 backwards."
428 (interactive "*p")
429 (if (and delete-key-deletes-forward
430 (or (eq 'tty (device-type))
431 (x-keysym-on-keyboard-p "BackSpace")))
432 (kill-sexp arg)
433 (backward-kill-sexp arg)))
434
435 (defun zap-to-char (arg char)
436 "Kill up to and including ARG'th occurrence of CHAR.
437 Goes backward if ARG is negative; error if CHAR not found."
438 (interactive "*p\ncZap to char: ")
439 (kill-region (point) (progn
440 (search-forward (char-to-string char) nil nil arg)
441 ; (goto-char (if (> arg 0) (1- (point)) (1+ (point))))
442 (point))))
443
444 (defun beginning-of-buffer (&optional arg)
445 "Move point to the beginning of the buffer; leave mark at previous position.
446 With arg N, put point N/10 of the way from the beginning.
447
448 If the buffer is narrowed, this command uses the beginning and size
449 of the accessible part of the buffer.
450
451 Don't use this command in Lisp programs!
452 \(goto-char (point-min)) is faster and avoids clobbering the mark."
453 ;; XEmacs change
454 (interactive "_P")
455 (push-mark)
456 (let ((size (- (point-max) (point-min))))
457 (goto-char (if arg
458 (+ (point-min)
459 (if (> size 10000)
460 ;; Avoid overflow for large buffer sizes!
461 (* (prefix-numeric-value arg)
462 (/ size 10))
463 (/ (+ 10 (* size (prefix-numeric-value arg))) 10)))
464 (point-min))))
465 (if arg (forward-line 1)))
466
467 (defun end-of-buffer (&optional arg)
468 "Move point to the end of the buffer; leave mark at previous position.
469 With arg N, put point N/10 of the way from the end.
470
471 If the buffer is narrowed, this command uses the beginning and size
472 of the accessible part of the buffer.
473
474 Don't use this command in Lisp programs!
475 \(goto-char (point-max)) is faster and avoids clobbering the mark."
476 ;; XEmacs change
477 (interactive "_P")
478 (push-mark)
479 ;; XEmacs changes here.
480 (let ((scroll-to-end (not (pos-visible-in-window-p (point-max))))
481 (size (- (point-max) (point-min))))
482 (goto-char (if arg
483 (- (point-max)
484 (if (> size 10000)
485 ;; Avoid overflow for large buffer sizes!
486 (* (prefix-numeric-value arg)
487 (/ size 10))
488 (/ (* size (prefix-numeric-value arg)) 10)))
489 (point-max)))
490 (cond (arg
491 ;; If we went to a place in the middle of the buffer,
492 ;; adjust it to the beginning of a line.
493 (forward-line 1))
494 ;; XEmacs change
495 (scroll-to-end
496 ;; If the end of the buffer is not already on the screen,
497 ;; then scroll specially to put it near, but not at, the bottom.
498 (recenter -3)))))
499
500 ;; XEmacs (not in FSF)
501 (defun mark-beginning-of-buffer (&optional arg)
502 "Push a mark at the beginning of the buffer; leave point where it is.
503 With arg N, push mark N/10 of the way from the true beginning."
504 (interactive "P")
505 (push-mark (if arg
506 (if (> (buffer-size) 10000)
507 ;; Avoid overflow for large buffer sizes!
508 (* (prefix-numeric-value arg)
509 (/ (buffer-size) 10))
510 (/ (+ 10 (* (buffer-size) (prefix-numeric-value arg))) 10))
511 (point-min))
512 nil
513 t))
514 (define-function 'mark-bob 'mark-beginning-of-buffer)
515
516 ;; XEmacs (not in FSF)
517 (defun mark-end-of-buffer (&optional arg)
518 "Push a mark at the end of the buffer; leave point where it is.
519 With arg N, push mark N/10 of the way from the true end."
520 (interactive "P")
521 (push-mark (if arg
522 (- (1+ (buffer-size))
523 (if (> (buffer-size) 10000)
524 ;; Avoid overflow for large buffer sizes!
525 (* (prefix-numeric-value arg)
526 (/ (buffer-size) 10))
527 (/ (* (buffer-size) (prefix-numeric-value arg)) 10)))
528 (point-max))
529 nil
530 t))
531 (define-function 'mark-eob 'mark-end-of-buffer)
532
533 (defun mark-whole-buffer ()
534 "Put point at beginning and mark at end of buffer.
535 You probably should not use this function in Lisp programs;
536 it is usually a mistake for a Lisp function to use any subroutine
537 that uses or sets the mark."
538 (interactive)
539 (push-mark (point))
540 (push-mark (point-max) nil t)
541 (goto-char (point-min)))
542
543 ;; XEmacs
544 (defun eval-current-buffer (&optional printflag)
545 "Evaluate the current buffer as Lisp code.
546 Programs can pass argument PRINTFLAG which controls printing of output:
547 nil means discard it; anything else is stream for print."
548 (interactive)
549 (eval-buffer (current-buffer) printflag))
550
551 ;; XEmacs
552 (defun count-words-buffer (b)
553 (interactive "b")
554 (save-excursion
555 (let ((buf (or b (current-buffer))))
556 (set-buffer buf)
557 (message "Buffer has %d words"
558 (count-words-region (point-min) (point-max))))))
559
560 ;; XEmacs
561 (defun count-words-region (start end)
562 (interactive "r")
563 (save-excursion
564 (let ((n 0))
565 (goto-char start)
566 (while (< (point) end)
567 (if (forward-word 1)
568 (setq n (1+ n))))
569 (message "Region has %d words" n)
570 n)))
571
572 (defun count-lines-region (start end)
573 "Print number of lines and characters in the region."
574 ;; XEmacs change
575 (interactive "_r")
576 (message "Region has %d lines, %d characters"
577 (count-lines start end) (- end start)))
578
579 ;; XEmacs
580 (defun count-lines-buffer (b)
581 "Print number of lines and characters in the specified buffer."
582 (interactive "_b")
583 (save-excursion
584 (let ((buf (or b (current-buffer)))
585 cnt)
586 (set-buffer buf)
587 (setq cnt (count-lines (point-min) (point-max)))
588 (message "Buffer has %d lines, %d characters"
589 cnt (- (point-max) (point-min)))
590 cnt)))
591
592 (defun what-line ()
593 "Print the current buffer line number and narrowed line number of point."
594 ;; XEmacs change
595 (interactive "_")
596 (let ((opoint (point)) start)
597 (save-excursion
598 (save-restriction
599 (goto-char (point-min))
600 (widen)
601 (beginning-of-line)
602 (setq start (point))
603 (goto-char opoint)
604 (beginning-of-line)
605 (if (/= start 1)
606 (message "line %d (narrowed line %d)"
607 (1+ (count-lines 1 (point)))
608 (1+ (count-lines start (point))))
609 (message "Line %d" (1+ (count-lines 1 (point)))))))))
610
611
612 (defun count-lines (start end)
613 "Return number of lines between START and END.
614 This is usually the number of newlines between them,
615 but can be one more if START is not equal to END
616 and the greater of them is not at the start of a line."
617 (save-excursion
618 (save-restriction
619 (narrow-to-region start end)
620 (goto-char (point-min))
621 (if (eq selective-display t)
622 (save-match-data
623 (let ((done 0))
624 (while (re-search-forward "[\n\C-m]" nil t 40)
625 (setq done (+ 40 done)))
626 (while (re-search-forward "[\n\C-m]" nil t 1)
627 (setq done (+ 1 done)))
628 (goto-char (point-max))
629 (if (and (/= start end)
630 (not (bolp)))
631 (1+ done)
632 done)))
633 (- (buffer-size) (forward-line (buffer-size)))))))
634
635 (defun what-cursor-position ()
636 "Print info on cursor position (on screen and within buffer)."
637 ;; XEmacs change
638 (interactive "_")
639 (let* ((char (char-after (point))) ; XEmacs
640 (beg (point-min))
641 (end (point-max))
642 (pos (point))
643 (total (buffer-size))
644 (percent (if (> total 50000)
645 ;; Avoid overflow from multiplying by 100!
646 (/ (+ (/ total 200) (1- pos)) (max (/ total 100) 1))
647 (/ (+ (/ total 2) (* 100 (1- pos))) (max total 1))))
648 (hscroll (if (= (window-hscroll) 0)
649 ""
650 (format " Hscroll=%d" (window-hscroll))))
651 (col (current-column)))
652 (if (= pos end)
653 (if (or (/= beg 1) (/= end (1+ total)))
654 (message "point=%d of %d(%d%%) <%d - %d> column %d %s"
655 pos total percent beg end col hscroll)
656 (message "point=%d of %d(%d%%) column %d %s"
657 pos total percent col hscroll))
658 ;; XEmacs: don't use single-key-description
659 (if (or (/= beg 1) (/= end (1+ total)))
660 (message "Char: %s (0%o, %d, 0x%x) point=%d of %d(%d%%) <%d - %d> column %d %s"
661 (text-char-description char) char char char pos total
662 percent beg end col hscroll)
663 (message "Char: %s (0%o, %d, 0x%x) point=%d of %d(%d%%) column %d %s"
664 (text-char-description char) char char char pos total
665 percent col hscroll)))))
666
667 (defun fundamental-mode ()
668 "Major mode not specialized for anything in particular.
669 Other major modes are defined by comparison with this one."
670 (interactive)
671 (kill-all-local-variables))
672
673 ;; XEmacs the following are declared elsewhere
674 ;(defvar read-expression-map (cons 'keymap minibuffer-local-map)
675 ; "Minibuffer keymap used for reading Lisp expressions.")
676 ;(define-key read-expression-map "\M-\t" 'lisp-complete-symbol)
677
678 ;(put 'eval-expression 'disabled t)
679
680 ;(defvar read-expression-history nil)
681
682 ;; We define this, rather than making `eval' interactive,
683 ;; for the sake of completion of names like eval-region, eval-current-buffer.
684 (defun eval-expression (expression)
685 "Evaluate EXPRESSION and print value in minibuffer.
686 Value is also consed on to front of the variable `values'."
687 ;(interactive "xEval: ")
688 (interactive
689 (list (read-from-minibuffer "Eval: "
690 nil read-expression-map t
691 'read-expression-history)))
692 (setq values (cons (eval expression) values))
693 (prin1 (car values) t))
694
695 ;; XEmacs -- extra parameter (variant, but equivalent logic)
696 (defun edit-and-eval-command (prompt command &optional history)
697 "Prompting with PROMPT, let user edit COMMAND and eval result.
698 COMMAND is a Lisp expression. Let user edit that expression in
699 the minibuffer, then read and evaluate the result."
700 (let ((command (read-expression prompt
701 ;; first try to format the thing readably;
702 ;; and if that fails, print it normally.
703 (condition-case ()
704 (let ((print-readably t))
705 (prin1-to-string command))
706 (error (prin1-to-string command)))
707 (or history '(command-history . 1)))))
708 (or history (setq history 'command-history))
709 (if (consp history)
710 (setq history (car history)))
711 (if (eq history t)
712 nil
713 ;; If command was added to the history as a string,
714 ;; get rid of that. We want only evallable expressions there.
715 (if (stringp (car (symbol-value history)))
716 (set history (cdr (symbol-value history))))
717
718 ;; If command to be redone does not match front of history,
719 ;; add it to the history.
720 (or (equal command (car (symbol-value history)))
721 (set history (cons command (symbol-value history)))))
722 (eval command)))
723
724 (defun repeat-complex-command (arg)
725 "Edit and re-evaluate last complex command, or ARGth from last.
726 A complex command is one which used the minibuffer.
727 The command is placed in the minibuffer as a Lisp form for editing.
728 The result is executed, repeating the command as changed.
729 If the command has been changed or is not the most recent previous command
730 it is added to the front of the command history.
731 You can use the minibuffer history commands \\<minibuffer-local-map>\\[next-history-element] and \\[previous-history-element]
732 to get different commands to edit and resubmit."
733 (interactive "p")
734 ;; XEmacs: It looks like our version is better -sb
735 (let ((print-level nil))
736 (edit-and-eval-command "Redo: "
737 (or (nth (1- arg) command-history)
738 (error ""))
739 (cons 'command-history arg))))
740
741 ;; XEmacs: Functions moved to minibuf.el
742 ;; previous-matching-history-element
743 ;; next-matching-history-element
744 ;; next-history-element
745 ;; previous-history-element
746 ;; next-complete-history-element
747 ;; previous-complete-history-element
748
749 (defun goto-line (arg)
750 "Goto line ARG, counting from line 1 at beginning of buffer."
751 (interactive "NGoto line: ")
752 (setq arg (prefix-numeric-value arg))
753 (save-restriction
754 (widen)
755 (goto-char 1)
756 (if (eq selective-display t)
757 (re-search-forward "[\n\C-m]" nil 'end (1- arg))
758 (forward-line (1- arg)))))
759
760 ;Put this on C-x u, so we can force that rather than C-_ into startup msg
761 (define-function 'advertised-undo 'undo)
762
763 (defun undo (&optional arg)
764 "Undo some previous changes.
765 Repeat this command to undo more changes.
766 A numeric argument serves as a repeat count."
767 (interactive "*p")
768 ;; If we don't get all the way through, make last-command indicate that
769 ;; for the following command.
770 (setq this-command t)
771 (let ((modified (buffer-modified-p))
772 (recent-save (recent-auto-save-p)))
773 (or (eq (selected-window) (minibuffer-window))
774 (display-message 'command "Undo!"))
775 (or (and (eq last-command 'undo)
776 (eq (current-buffer) last-undo-buffer)) ; XEmacs
777 (progn (undo-start)
778 (undo-more 1)))
779 (undo-more (or arg 1))
780 ;; Don't specify a position in the undo record for the undo command.
781 ;; Instead, undoing this should move point to where the change is.
782 (let ((tail buffer-undo-list)
783 done)
784 (while (and tail (not done) (not (null (car tail))))
785 (if (integerp (car tail))
786 (progn
787 (setq done t)
788 (setq buffer-undo-list (delq (car tail) buffer-undo-list))))
789 (setq tail (cdr tail))))
790 (and modified (not (buffer-modified-p))
791 (delete-auto-save-file-if-necessary recent-save)))
792 ;; If we do get all the way through, make this-command indicate that.
793 (setq this-command 'undo))
794
795 (defvar pending-undo-list nil
796 "Within a run of consecutive undo commands, list remaining to be undone.")
797
798 (defvar last-undo-buffer nil) ; XEmacs
799
800 (defun undo-start ()
801 "Set `pending-undo-list' to the front of the undo list.
802 The next call to `undo-more' will undo the most recently made change."
803 (if (eq buffer-undo-list t)
804 (error "No undo information in this buffer"))
805 (setq pending-undo-list buffer-undo-list))
806
807 (defun undo-more (count)
808 "Undo back N undo-boundaries beyond what was already undone recently.
809 Call `undo-start' to get ready to undo recent changes,
810 then call `undo-more' one or more times to undo them."
811 (or pending-undo-list
812 (error "No further undo information"))
813 (setq pending-undo-list (primitive-undo count pending-undo-list)
814 last-undo-buffer (current-buffer))) ; XEmacs
815
816 ;; XEmacs
817 (defun call-with-transparent-undo (fn &rest args)
818 "Apply FN to ARGS, and then undo all changes made by FN to the current
819 buffer. The undo records are processed even if FN returns non-locally.
820 There is no trace of the changes made by FN in the buffer's undo history.
821
822 You can use this in a write-file-hooks function with continue-save-buffer
823 to make the contents of a disk file differ from its in-memory buffer."
824 (let ((buffer-undo-list nil)
825 ;; Kludge to prevent undo list truncation:
826 (undo-high-threshold -1)
827 (undo-threshold -1)
828 (obuffer (current-buffer)))
829 (unwind-protect
830 (apply fn args)
831 ;; Go to the buffer we will restore and make it writable:
832 (set-buffer obuffer)
833 (save-excursion
834 (let ((buffer-read-only nil))
835 (save-restriction
836 (widen)
837 ;; Perform all undos, with further undo logging disabled:
838 (let ((tail buffer-undo-list))
839 (setq buffer-undo-list t)
840 (while tail
841 (setq tail (primitive-undo (length tail) tail))))))))))
842
843 ;; XEmacs: The following are in other files
844 ;; shell-command-history
845 ;; shell-command-switch
846 ;; shell-command
847 ;; shell-command-sentinel
848
849
850 (defconst universal-argument-map
851 (let ((map (make-sparse-keymap)))
852 (set-keymap-default-binding map 'universal-argument-other-key)
853 ;FSFmacs (define-key map [switch-frame] nil)
854 (define-key map [(t)] 'universal-argument-other-key)
855 (define-key map [(meta t)] 'universal-argument-other-key)
856 (define-key map [(control u)] 'universal-argument-more)
857 (define-key map [?-] 'universal-argument-minus)
858 (define-key map [?0] 'digit-argument)
859 (define-key map [?1] 'digit-argument)
860 (define-key map [?2] 'digit-argument)
861 (define-key map [?3] 'digit-argument)
862 (define-key map [?4] 'digit-argument)
863 (define-key map [?5] 'digit-argument)
864 (define-key map [?6] 'digit-argument)
865 (define-key map [?7] 'digit-argument)
866 (define-key map [?8] 'digit-argument)
867 (define-key map [?9] 'digit-argument)
868 map)
869 "Keymap used while processing \\[universal-argument].")
870
871 (defvar universal-argument-num-events nil
872 "Number of argument-specifying events read by `universal-argument'.
873 `universal-argument-other-key' uses this to discard those events
874 from (this-command-keys), and reread only the final command.")
875
876 (defun universal-argument ()
877 "Begin a numeric argument for the following command.
878 Digits or minus sign following \\[universal-argument] make up the numeric argument.
879 \\[universal-argument] following the digits or minus sign ends the argument.
880 \\[universal-argument] without digits or minus sign provides 4 as argument.
881 Repeating \\[universal-argument] without digits or minus sign
882 multiplies the argument by 4 each time."
883 (interactive)
884 (setq prefix-arg (list 4))
885 (setq zmacs-region-stays t) ; XEmacs
886 (setq universal-argument-num-events (length (this-command-keys)))
887 (setq overriding-terminal-local-map universal-argument-map))
888
889 ;; A subsequent C-u means to multiply the factor by 4 if we've typed
890 ;; nothing but C-u's; otherwise it means to terminate the prefix arg.
891 (defun universal-argument-more (arg)
892 (interactive "_P") ; XEmacs
893 (if (consp arg)
894 (setq prefix-arg (list (* 4 (car arg))))
895 (setq prefix-arg arg)
896 (setq overriding-terminal-local-map nil))
897 (setq universal-argument-num-events (length (this-command-keys))))
898
899 (defun negative-argument (arg)
900 "Begin a negative numeric argument for the next command.
901 \\[universal-argument] following digits or minus sign ends the argument."
902 (interactive "_P") ; XEmacs
903 (cond ((integerp arg)
904 (setq prefix-arg (- arg)))
905 ((eq arg '-)
906 (setq prefix-arg nil))
907 (t
908 (setq prefix-arg '-)))
909 (setq universal-argument-num-events (length (this-command-keys)))
910 (setq overriding-terminal-local-map universal-argument-map))
911
912 ;; XEmacs: This function not synched with FSF
913 (defun digit-argument (arg)
914 "Part of the numeric argument for the next command.
915 \\[universal-argument] following digits or minus sign ends the argument."
916 (interactive "_P") ; XEmacs
917 (let* ((event last-command-event)
918 (key (and (key-press-event-p event)
919 (event-key event)))
920 (digit (and key (characterp key) (>= key ?0) (<= key ?9)
921 (- key ?0))))
922 (if (null digit)
923 (universal-argument-other-key arg)
924 (cond ((integerp arg)
925 (setq prefix-arg (+ (* arg 10)
926 (if (< arg 0) (- digit) digit))))
927 ((eq arg '-)
928 ;; Treat -0 as just -, so that -01 will work.
929 (setq prefix-arg (if (zerop digit) '- (- digit))))
930 (t
931 (setq prefix-arg digit)))
932 (setq universal-argument-num-events (length (this-command-keys)))
933 (setq overriding-terminal-local-map universal-argument-map))))
934
935 ;; For backward compatibility, minus with no modifiers is an ordinary
936 ;; command if digits have already been entered.
937 (defun universal-argument-minus (arg)
938 (interactive "_P") ; XEmacs
939 (if (integerp arg)
940 (universal-argument-other-key arg)
941 (negative-argument arg)))
942
943 ;; Anything else terminates the argument and is left in the queue to be
944 ;; executed as a command.
945 (defun universal-argument-other-key (arg)
946 (interactive "_P") ; XEmacs
947 (setq prefix-arg arg)
948 (let* ((key (this-command-keys))
949 ;; FSF calls silly function `listify-key-sequence' here.
950 (keylist (append key nil)))
951 (setq unread-command-events
952 (append (nthcdr universal-argument-num-events keylist)
953 unread-command-events)))
954 (reset-this-command-lengths)
955 (setq overriding-terminal-local-map nil))
956
957
958 ;; XEmacs -- keep zmacs-region active.
959 (defun forward-to-indentation (arg)
960 "Move forward ARG lines and position at first nonblank character."
961 (interactive "_p")
962 (forward-line arg)
963 (skip-chars-forward " \t"))
964
965 (defun backward-to-indentation (arg)
966 "Move backward ARG lines and position at first nonblank character."
967 (interactive "_p")
968 (forward-line (- arg))
969 (skip-chars-forward " \t"))
970
971 (defcustom kill-whole-line nil
972 "*If non-nil, `kill-line' with no arg at beg of line kills the whole line."
973 :type 'boolean
974 :group 'killing)
975
976 (defun kill-line (&optional arg)
977 "Kill the rest of the current line; if no nonblanks there, kill thru newline.
978 With prefix argument, kill that many lines from point.
979 Negative arguments kill lines backward.
980
981 When calling from a program, nil means \"no arg\",
982 a number counts as a prefix arg.
983
984 If `kill-whole-line' is non-nil, then kill the whole line
985 when given no argument at the beginning of a line."
986 (interactive "*P")
987 (kill-region (point)
988 ;; Don't shift point before doing the delete; that way,
989 ;; undo will record the right position of point.
990 ;; FSF
991 ; ;; It is better to move point to the other end of the kill
992 ; ;; before killing. That way, in a read-only buffer, point
993 ; ;; moves across the text that is copied to the kill ring.
994 ; ;; The choice has no effect on undo now that undo records
995 ; ;; the value of point from before the command was run.
996 ; (progn
997 (save-excursion
998 (if arg
999 (forward-line (prefix-numeric-value arg))
1000 (if (eobp)
1001 (signal 'end-of-buffer nil))
1002 (if (or (looking-at "[ \t]*$") (and kill-whole-line (bolp)))
1003 (forward-line 1)
1004 (end-of-line)))
1005 (point))))
1006
1007 ;; XEmacs
1008 (defun backward-kill-line nil
1009 "Kill back to the beginning of the line."
1010 (interactive)
1011 (let ((point (point)))
1012 (beginning-of-line nil)
1013 (kill-region (point) point)))
1014
1015
1016 ;;;; Window system cut and paste hooks.
1017 ;;;
1018 ;;; I think that kill-hooks is a better name and more general mechanism
1019 ;;; than interprogram-cut-function (from FSFmacs). I don't like the behavior
1020 ;;; of interprogram-paste-function: ^Y should always come from the kill ring,
1021 ;;; not the X selection. But if that were provided, it should be called (and
1022 ;;; behave as) yank-hooks instead. -- jwz
1023
1024 ;; [... code snipped ...]
1025
1026 (defcustom kill-hooks nil
1027 "*Functions run when something is added to the XEmacs kill ring.
1028 These functions are called with one argument, the string most recently
1029 cut or copied. You can use this to, for example, make the most recent
1030 kill become the X Clipboard selection."
1031 :type 'hook
1032 :group 'killing)
1033
1034 ;;; `kill-hooks' seems not sufficient because
1035 ;;; `interprogram-cut-function' requires more variable about to rotate
1036 ;;; the cut buffers. I'm afraid to change interface of `kill-hooks',
1037 ;;; so I add it. (1997-11-03 by MORIOKA Tomohiko)
1038
1039 (defvar interprogram-cut-function nil
1040 "Function to call to make a killed region available to other programs.
1041
1042 Most window systems provide some sort of facility for cutting and
1043 pasting text between the windows of different programs.
1044 This variable holds a function that Emacs calls whenever text
1045 is put in the kill ring, to make the new kill available to other
1046 programs.
1047
1048 The function takes one or two arguments.
1049 The first argument, TEXT, is a string containing
1050 the text which should be made available.
1051 The second, PUSH, if non-nil means this is a \"new\" kill;
1052 nil means appending to an \"old\" kill.")
1053
1054 (defvar interprogram-paste-function nil
1055 "Function to call to get text cut from other programs.
1056
1057 Most window systems provide some sort of facility for cutting and
1058 pasting text between the windows of different programs.
1059 This variable holds a function that Emacs calls to obtain
1060 text that other programs have provided for pasting.
1061
1062 The function should be called with no arguments. If the function
1063 returns nil, then no other program has provided such text, and the top
1064 of the Emacs kill ring should be used. If the function returns a
1065 string, that string should be put in the kill ring as the latest kill.
1066
1067 Note that the function should return a string only if a program other
1068 than Emacs has provided a string for pasting; if Emacs provided the
1069 most recent string, the function should return nil. If it is
1070 difficult to tell whether Emacs or some other program provided the
1071 current string, it is probably good enough to return nil if the string
1072 is equal (according to `string=') to the last text Emacs provided.")
1073
1074
1075 ;;;; The kill ring data structure.
1076
1077 (defvar kill-ring nil
1078 "List of killed text sequences.
1079 Since the kill ring is supposed to interact nicely with cut-and-paste
1080 facilities offered by window systems, use of this variable should
1081 interact nicely with `interprogram-cut-function' and
1082 `interprogram-paste-function'. The functions `kill-new',
1083 `kill-append', and `current-kill' are supposed to implement this
1084 interaction; you may want to use them instead of manipulating the kill
1085 ring directly.")
1086
1087 (defcustom kill-ring-max 30
1088 "*Maximum length of kill ring before oldest elements are thrown away."
1089 :type 'integer
1090 :group 'killing)
1091
1092 (defvar kill-ring-yank-pointer nil
1093 "The tail of the kill ring whose car is the last thing yanked.")
1094
1095 (defun kill-new (string &optional replace)
1096 "Make STRING the latest kill in the kill ring.
1097 Set the kill-ring-yank pointer to point to it.
1098 Run `kill-hooks'.
1099 Optional second argument REPLACE non-nil means that STRING will replace
1100 the front of the kill ring, rather than being added to the list."
1101 ; (and (fboundp 'menu-bar-update-yank-menu)
1102 ; (menu-bar-update-yank-menu string (and replace (car kill-ring))))
1103 (if replace
1104 (setcar kill-ring string)
1105 (setq kill-ring (cons string kill-ring))
1106 (if (> (length kill-ring) kill-ring-max)
1107 (setcdr (nthcdr (1- kill-ring-max) kill-ring) nil)))
1108 (setq kill-ring-yank-pointer kill-ring)
1109 (if interprogram-cut-function
1110 (funcall interprogram-cut-function string (not replace)))
1111 (run-hook-with-args 'kill-hooks string))
1112
1113 (defun kill-append (string before-p)
1114 "Append STRING to the end of the latest kill in the kill ring.
1115 If BEFORE-P is non-nil, prepend STRING to the kill.
1116 Run `kill-hooks'."
1117 (kill-new (if before-p
1118 (concat string (car kill-ring))
1119 (concat (car kill-ring) string)) t))
1120
1121 (defun current-kill (n &optional do-not-move)
1122 "Rotate the yanking point by N places, and then return that kill.
1123 If N is zero, `interprogram-paste-function' is set, and calling it
1124 returns a string, then that string is added to the front of the
1125 kill ring and returned as the latest kill.
1126 If optional arg DO-NOT-MOVE is non-nil, then don't actually move the
1127 yanking point\; just return the Nth kill forward."
1128 (let ((interprogram-paste (and (= n 0)
1129 interprogram-paste-function
1130 (funcall interprogram-paste-function))))
1131 (if interprogram-paste
1132 (progn
1133 ;; Disable the interprogram cut function when we add the new
1134 ;; text to the kill ring, so Emacs doesn't try to own the
1135 ;; selection, with identical text.
1136 (let ((interprogram-cut-function nil))
1137 (kill-new interprogram-paste))
1138 interprogram-paste)
1139 (or kill-ring (error "Kill ring is empty"))
1140 (let* ((tem (nthcdr (mod (- n (length kill-ring-yank-pointer))
1141 (length kill-ring))
1142 kill-ring)))
1143 (or do-not-move
1144 (setq kill-ring-yank-pointer tem))
1145 (car tem)))))
1146
1147
1148
1149 ;;;; Commands for manipulating the kill ring.
1150
1151 ;; In FSF killing read-only text just pastes it into kill-ring. Which
1152 ;; is a very bad idea -- see Jamie's comment below.
1153
1154 ;(defvar kill-read-only-ok nil
1155 ; "*Non-nil means don't signal an error for killing read-only text.")
1156
1157 (defun kill-region (beg end &optional verbose) ; verbose is XEmacs addition
1158 "Kill between point and mark.
1159 The text is deleted but saved in the kill ring.
1160 The command \\[yank] can retrieve it from there.
1161 \(If you want to kill and then yank immediately, use \\[copy-region-as-kill].)
1162
1163 This is the primitive for programs to kill text (as opposed to deleting it).
1164 Supply two arguments, character numbers indicating the stretch of text
1165 to be killed.
1166 Any command that calls this function is a \"kill command\".
1167 If the previous command was also a kill command,
1168 the text killed this time appends to the text killed last time
1169 to make one entry in the kill ring."
1170 (interactive "*r\np")
1171 ; (interactive
1172 ; (let ((region-hack (and zmacs-regions (eq last-command 'yank))))
1173 ; ;; This lets "^Y^W" work. I think this is dumb, but zwei did it.
1174 ; (if region-hack (zmacs-activate-region))
1175 ; (prog1
1176 ; (list (point) (mark) current-prefix-arg)
1177 ; (if region-hack (zmacs-deactivate-region)))))
1178 ;; beg and end can be markers but the rest of this function is
1179 ;; written as if they are only integers
1180 (if (markerp beg) (setq beg (marker-position beg)))
1181 (if (markerp end) (setq end (marker-position end)))
1182 (or (and beg end) (if zmacs-regions ;; rewritten for I18N3 snarfing
1183 (error "The region is not active now")
1184 (error "The mark is not set now")))
1185 (if verbose (if buffer-read-only
1186 (display-message
1187 'command
1188 (format "Copying %d characters"
1189 (- (max beg end) (min beg end))))
1190 (display-message
1191 'command
1192 (format "Killing %d characters"
1193 (- (max beg end) (min beg end))))))
1194 (cond
1195
1196 ;; I don't like this large change in behavior -- jwz
1197 ;; Read-Only text means it shouldn't be deleted, so I'm restoring
1198 ;; this code, but only for text-properties and not full extents. -sb
1199 ;; If the buffer is read-only, we should beep, in case the person
1200 ;; just isn't aware of this. However, there's no harm in putting
1201 ;; the region's text in the kill ring, anyway.
1202 ((or (and buffer-read-only (not inhibit-read-only))
1203 (text-property-not-all (min beg end) (max beg end) 'read-only nil))
1204 ;; This is redundant.
1205 ;; (if verbose (message "Copying %d characters"
1206 ;; (- (max beg end) (min beg end))))
1207 (copy-region-as-kill beg end)
1208 ;; ;; This should always barf, and give us the correct error.
1209 ;; (if kill-read-only-ok
1210 ;; (message "Read only text copied to kill ring")
1211 (setq this-command 'kill-region)
1212 (barf-if-buffer-read-only)
1213 (signal 'buffer-read-only (list (current-buffer))))
1214
1215 ;; In certain cases, we can arrange for the undo list and the kill
1216 ;; ring to share the same string object. This code does that.
1217 ((not (or (eq buffer-undo-list t)
1218 (eq last-command 'kill-region)
1219 ;; Use = since positions may be numbers or markers.
1220 (= beg end)))
1221 ;; Don't let the undo list be truncated before we can even access it.
1222 ;; FSF calls this `undo-strong-limit'
1223 (let ((undo-high-threshold (+ (- end beg) 100))
1224 ;(old-list buffer-undo-list)
1225 tail)
1226 (delete-region beg end)
1227 ;; Search back in buffer-undo-list for this string,
1228 ;; in case a change hook made property changes.
1229 (setq tail buffer-undo-list)
1230 (while (and tail
1231 (not (stringp (car-safe (car-safe tail))))) ; XEmacs
1232 (pop tail))
1233 ;; Take the same string recorded for undo
1234 ;; and put it in the kill-ring.
1235 (and tail
1236 (kill-new (car (car tail))))))
1237
1238 (t
1239 ;; if undo is not kept, grab the string then delete it (which won't
1240 ;; add another string to the undo list).
1241 (copy-region-as-kill beg end)
1242 (delete-region beg end)))
1243 (setq this-command 'kill-region))
1244
1245 ;; copy-region-as-kill no longer sets this-command, because it's confusing
1246 ;; to get two copies of the text when the user accidentally types M-w and
1247 ;; then corrects it with the intended C-w.
1248 (defun copy-region-as-kill (beg end)
1249 "Save the region as if killed, but don't kill it.
1250 Run `kill-hooks'."
1251 (interactive "r")
1252 (if (eq last-command 'kill-region)
1253 (kill-append (buffer-substring beg end) (< end beg))
1254 (kill-new (buffer-substring beg end)))
1255 nil)
1256
1257 (defun kill-ring-save (beg end)
1258 "Save the region as if killed, but don't kill it.
1259 This command is similar to `copy-region-as-kill', except that it gives
1260 visual feedback indicating the extent of the region being copied."
1261 (interactive "r")
1262 (copy-region-as-kill beg end)
1263 ;; copy before delay, for xclipboard's benefit
1264 (if (interactive-p)
1265 (let ((other-end (if (= (point) beg) end beg))
1266 (opoint (point))
1267 ;; Inhibit quitting so we can make a quit here
1268 ;; look like a C-g typed as a command.
1269 (inhibit-quit t))
1270 (if (pos-visible-in-window-p other-end (selected-window))
1271 (progn
1272 ;; FSF (I'm not sure what this does -sb)
1273 ; ;; Swap point and mark.
1274 ; (set-marker (mark-marker) (point) (current-buffer))
1275 (goto-char other-end)
1276 (sit-for 1)
1277 ; ;; Swap back.
1278 ; (set-marker (mark-marker) other-end (current-buffer))
1279 (goto-char opoint)
1280 ;; If user quit, deactivate the mark
1281 ;; as C-g would as a command.
1282 (and quit-flag (mark)
1283 (zmacs-deactivate-region)))
1284 ;; too noisy. -- jwz
1285 ; (let* ((killed-text (current-kill 0))
1286 ; (message-len (min (length killed-text) 40)))
1287 ; (if (= (point) beg)
1288 ; ;; Don't say "killed"; that is misleading.
1289 ; (message "Saved text until \"%s\""
1290 ; (substring killed-text (- message-len)))
1291 ; (message "Saved text from \"%s\""
1292 ; (substring killed-text 0 message-len))))
1293 ))))
1294
1295 (defun append-next-kill ()
1296 "Cause following command, if it kills, to append to previous kill."
1297 ;; XEmacs
1298 (interactive "_")
1299 (if (interactive-p)
1300 (progn
1301 (setq this-command 'kill-region)
1302 (display-message 'command
1303 "If the next command is a kill, it will append"))
1304 (setq last-command 'kill-region)))
1305
1306 (defun yank-pop (arg)
1307 "Replace just-yanked stretch of killed text with a different stretch.
1308 This command is allowed only immediately after a `yank' or a `yank-pop'.
1309 At such a time, the region contains a stretch of reinserted
1310 previously-killed text. `yank-pop' deletes that text and inserts in its
1311 place a different stretch of killed text.
1312
1313 With no argument, the previous kill is inserted.
1314 With argument N, insert the Nth previous kill.
1315 If N is negative, this is a more recent kill.
1316
1317 The sequence of kills wraps around, so that after the oldest one
1318 comes the newest one."
1319 (interactive "*p")
1320 (if (not (eq last-command 'yank))
1321 (error "Previous command was not a yank"))
1322 (setq this-command 'yank)
1323 (let ((inhibit-read-only t)
1324 (before (< (point) (mark t))))
1325 (delete-region (point) (mark t))
1326 ;;(set-marker (mark-marker) (point) (current-buffer))
1327 (set-mark (point))
1328 (insert (current-kill arg))
1329 (if before
1330 ;; This is like exchange-point-and-mark, but doesn't activate the mark.
1331 ;; It is cleaner to avoid activation, even though the command
1332 ;; loop would deactivate the mark because we inserted text.
1333 (goto-char (prog1 (mark t)
1334 (set-marker (mark-marker t) (point) (current-buffer))))))
1335 nil)
1336
1337
1338 (defun yank (&optional arg)
1339 "Reinsert the last stretch of killed text.
1340 More precisely, reinsert the stretch of killed text most recently
1341 killed OR yanked. Put point at end, and set mark at beginning.
1342 With just C-u as argument, same but put point at beginning (and mark at end).
1343 With argument N, reinsert the Nth most recently killed stretch of killed
1344 text.
1345 See also the command \\[yank-pop]."
1346 (interactive "*P")
1347 ;; If we don't get all the way through, make last-command indicate that
1348 ;; for the following command.
1349 (setq this-command t)
1350 (push-mark (point))
1351 (insert (current-kill (cond
1352 ((listp arg) 0)
1353 ((eq arg '-) -1)
1354 (t (1- arg)))))
1355 (if (consp arg)
1356 ;; This is like exchange-point-and-mark, but doesn't activate the mark.
1357 ;; It is cleaner to avoid activation, even though the command
1358 ;; loop would deactivate the mark because we inserted text.
1359 ;; (But it's an unnecessary kludge in XEmacs.)
1360 ;(goto-char (prog1 (mark t)
1361 ;(set-marker (mark-marker) (point) (current-buffer)))))
1362 (exchange-point-and-mark t))
1363 ;; If we do get all the way thru, make this-command indicate that.
1364 (setq this-command 'yank)
1365 nil)
1366
1367 (defun rotate-yank-pointer (arg)
1368 "Rotate the yanking point in the kill ring.
1369 With argument, rotate that many kills forward (or backward, if negative)."
1370 (interactive "p")
1371 (current-kill arg))
1372
1373
1374 (defun insert-buffer (buffer)
1375 "Insert after point the contents of BUFFER.
1376 Puts mark after the inserted text.
1377 BUFFER may be a buffer or a buffer name."
1378 (interactive
1379 (list
1380 (progn
1381 (barf-if-buffer-read-only)
1382 (read-buffer "Insert buffer: "
1383 ;; XEmacs: we have different args
1384 (other-buffer (current-buffer) nil t)
1385 t))))
1386 (or (bufferp buffer)
1387 (setq buffer (get-buffer buffer)))
1388 (let (start end newmark)
1389 (save-excursion
1390 (save-excursion
1391 (set-buffer buffer)
1392 (setq start (point-min) end (point-max)))
1393 (insert-buffer-substring buffer start end)
1394 (setq newmark (point)))
1395 (push-mark newmark))
1396 nil)
1397
1398 (defun append-to-buffer (buffer start end)
1399 "Append to specified buffer the text of the region.
1400 It is inserted into that buffer before its point.
1401
1402 When calling from a program, give three arguments:
1403 BUFFER (or buffer name), START and END.
1404 START and END specify the portion of the current buffer to be copied."
1405 (interactive
1406 ;; XEmacs: we have different args to other-buffer
1407 (list (read-buffer "Append to buffer: " (other-buffer (current-buffer)
1408 nil t))
1409 (region-beginning) (region-end)))
1410 (let ((oldbuf (current-buffer)))
1411 (save-excursion
1412 (set-buffer (get-buffer-create buffer))
1413 (insert-buffer-substring oldbuf start end))))
1414
1415 (defun prepend-to-buffer (buffer start end)
1416 "Prepend to specified buffer the text of the region.
1417 It is inserted into that buffer after its point.
1418
1419 When calling from a program, give three arguments:
1420 BUFFER (or buffer name), START and END.
1421 START and END specify the portion of the current buffer to be copied."
1422 (interactive "BPrepend to buffer: \nr")
1423 (let ((oldbuf (current-buffer)))
1424 (save-excursion
1425 (set-buffer (get-buffer-create buffer))
1426 (save-excursion
1427 (insert-buffer-substring oldbuf start end)))))
1428
1429 (defun copy-to-buffer (buffer start end)
1430 "Copy to specified buffer the text of the region.
1431 It is inserted into that buffer, replacing existing text there.
1432
1433 When calling from a program, give three arguments:
1434 BUFFER (or buffer name), START and END.
1435 START and END specify the portion of the current buffer to be copied."
1436 (interactive "BCopy to buffer: \nr")
1437 (let ((oldbuf (current-buffer)))
1438 (save-excursion
1439 (set-buffer (get-buffer-create buffer))
1440 (erase-buffer)
1441 (save-excursion
1442 (insert-buffer-substring oldbuf start end)))))
1443
1444 ;FSFmacs
1445 ;(put 'mark-inactive 'error-conditions '(mark-inactive error))
1446 ;(put 'mark-inactive 'error-message "The mark is not active now")
1447
1448 (defun mark (&optional force buffer)
1449 "Return this buffer's mark value as integer, or nil if no mark.
1450
1451 If `zmacs-regions' is true, then this returns nil unless the region is
1452 currently in the active (highlighted) state. With an argument of t, this
1453 returns the mark (if there is one) regardless of the active-region state.
1454 You should *generally* not use the mark unless the region is active, if
1455 the user has expressed a preference for the active-region model.
1456
1457 If you are using this in an editing command, you are most likely making
1458 a mistake; see the documentation of `set-mark'."
1459 (setq buffer (decode-buffer buffer))
1460 ;FSFmacs version:
1461 ; (if (or force (not transient-mark-mode) mark-active mark-even-if-inactive)
1462 ; (marker-position (mark-marker))
1463 ; (signal 'mark-inactive nil)))
1464 (let ((m (mark-marker force buffer)))
1465 (and m (marker-position m))))
1466
1467 ;;;#### FSFmacs
1468 ;;; Many places set mark-active directly, and several of them failed to also
1469 ;;; run deactivate-mark-hook. This shorthand should simplify.
1470 ;(defsubst deactivate-mark ()
1471 ; "Deactivate the mark by setting `mark-active' to nil.
1472 ;\(That makes a difference only in Transient Mark mode.)
1473 ;Also runs the hook `deactivate-mark-hook'."
1474 ; (if transient-mark-mode
1475 ; (progn
1476 ; (setq mark-active nil)
1477 ; (run-hooks 'deactivate-mark-hook))))
1478
1479 (defun set-mark (pos &optional buffer)
1480 "Set this buffer's mark to POS. Don't use this function!
1481 That is to say, don't use this function unless you want
1482 the user to see that the mark has moved, and you want the previous
1483 mark position to be lost.
1484
1485 Normally, when a new mark is set, the old one should go on the stack.
1486 This is why most applications should use push-mark, not set-mark.
1487
1488 Novice Emacs Lisp programmers often try to use the mark for the wrong
1489 purposes. The mark saves a location for the user's convenience.
1490 Most editing commands should not alter the mark.
1491 To remember a location for internal use in the Lisp program,
1492 store it in a Lisp variable. Example:
1493
1494 (let ((beg (point))) (forward-line 1) (delete-region beg (point)))."
1495
1496 (setq buffer (decode-buffer buffer))
1497 (set-marker (mark-marker t buffer) pos buffer))
1498 ;; FSF
1499 ; (if pos
1500 ; (progn
1501 ; (setq mark-active t)
1502 ; (run-hooks 'activate-mark-hook)
1503 ; (set-marker (mark-marker) pos (current-buffer)))
1504 ; ;; Normally we never clear mark-active except in Transient Mark mode.
1505 ; ;; But when we actually clear out the mark value too,
1506 ; ;; we must clear mark-active in any mode.
1507 ; (setq mark-active nil)
1508 ; (run-hooks 'deactivate-mark-hook)
1509 ; (set-marker (mark-marker) nil)))
1510
1511 (defvar mark-ring nil
1512 "The list of former marks of the current buffer, most recent first.")
1513 (make-variable-buffer-local 'mark-ring)
1514 (put 'mark-ring 'permanent-local t)
1515
1516 (defcustom mark-ring-max 16
1517 "*Maximum size of mark ring. Start discarding off end if gets this big."
1518 :type 'integer
1519 :group 'killing)
1520
1521 (defvar global-mark-ring nil
1522 "The list of saved global marks, most recent first.")
1523
1524 (defcustom global-mark-ring-max 16
1525 "*Maximum size of global mark ring. \
1526 Start discarding off end if gets this big."
1527 :type 'integer
1528 :group 'killing)
1529
1530 (defun set-mark-command (arg)
1531 "Set mark at where point is, or jump to mark.
1532 With no prefix argument, set mark, push old mark position on local mark
1533 ring, and push mark on global mark ring.
1534 With argument, jump to mark, and pop a new position for mark off the ring
1535 \(does not affect global mark ring\).
1536
1537 Novice Emacs Lisp programmers often try to use the mark for the wrong
1538 purposes. See the documentation of `set-mark' for more information."
1539 (interactive "P")
1540 (if (null arg)
1541 (push-mark nil nil t)
1542 (if (null (mark t))
1543 (error "No mark set in this buffer")
1544 (goto-char (mark t))
1545 (pop-mark))))
1546
1547 ;; XEmacs: Extra parameter
1548 (defun push-mark (&optional location nomsg activate-region buffer)
1549 "Set mark at LOCATION (point, by default) and push old mark on mark ring.
1550 If the last global mark pushed was not in the current buffer,
1551 also push LOCATION on the global mark ring.
1552 Display `Mark set' unless the optional second arg NOMSG is non-nil.
1553 Activate mark if optional third arg ACTIVATE-REGION non-nil.
1554
1555 Novice Emacs Lisp programmers often try to use the mark for the wrong
1556 purposes. See the documentation of `set-mark' for more information."
1557 (setq buffer (decode-buffer buffer)) ; XEmacs
1558 (if (null (mark t buffer)) ; XEmacs
1559 nil
1560 ;; The save-excursion / set-buffer is necessary because mark-ring
1561 ;; is a buffer local variable
1562 (save-excursion
1563 (set-buffer buffer)
1564 (setq mark-ring (cons (copy-marker (mark-marker t buffer)) mark-ring))
1565 (if (> (length mark-ring) mark-ring-max)
1566 (progn
1567 (move-marker (car (nthcdr mark-ring-max mark-ring)) nil buffer)
1568 (setcdr (nthcdr (1- mark-ring-max) mark-ring) nil)))))
1569 (set-mark (or location (point buffer)) buffer)
1570 ; (set-marker (mark-marker) (or location (point)) (current-buffer)) ; FSF
1571 ;; Now push the mark on the global mark ring.
1572 (if (or (null global-mark-ring)
1573 (not (eq (marker-buffer (car global-mark-ring)) buffer)))
1574 ;; The last global mark pushed wasn't in this same buffer.
1575 (progn
1576 (setq global-mark-ring (cons (copy-marker (mark-marker t buffer))
1577 global-mark-ring))
1578 (if (> (length global-mark-ring) global-mark-ring-max)
1579 (progn
1580 (move-marker (car (nthcdr global-mark-ring-max global-mark-ring))
1581 nil buffer)
1582 (setcdr (nthcdr (1- global-mark-ring-max) global-mark-ring) nil)))))
1583 (or nomsg executing-kbd-macro (> (minibuffer-depth) 0)
1584 (display-message 'command "Mark set"))
1585 (if activate-region
1586 (progn
1587 (setq zmacs-region-stays t)
1588 (zmacs-activate-region)))
1589 ; (if (or activate (not transient-mark-mode)) ; FSF
1590 ; (set-mark (mark t))) ; FSF
1591 nil)
1592
1593 (defun pop-mark ()
1594 "Pop off mark ring into the buffer's actual mark.
1595 Does not set point. Does nothing if mark ring is empty."
1596 (if mark-ring
1597 (progn
1598 (setq mark-ring (nconc mark-ring (list (copy-marker (mark-marker t)))))
1599 (set-mark (car mark-ring))
1600 (move-marker (car mark-ring) nil)
1601 (if (null (mark t)) (ding))
1602 (setq mark-ring (cdr mark-ring)))))
1603
1604 (define-function 'exchange-dot-and-mark 'exchange-point-and-mark)
1605 (defun exchange-point-and-mark (&optional dont-activate-region)
1606 "Put the mark where point is now, and point where the mark is now.
1607 The mark is activated unless DONT-ACTIVATE-REGION is non-nil."
1608 (interactive nil)
1609 (let ((omark (mark t)))
1610 (if (null omark)
1611 (error "No mark set in this buffer"))
1612 (set-mark (point))
1613 (goto-char omark)
1614 (or dont-activate-region (zmacs-activate-region)) ; XEmacs
1615 nil))
1616
1617 ;; XEmacs
1618 (defun mark-something (mark-fn movement-fn arg)
1619 "internal function used by mark-sexp, mark-word, etc."
1620 (let (newmark (pushp t))
1621 (save-excursion
1622 (if (and (eq last-command mark-fn) (mark))
1623 ;; Extend the previous state in the same direction:
1624 (progn
1625 (if (< (mark) (point)) (setq arg (- arg)))
1626 (goto-char (mark))
1627 (setq pushp nil)))
1628 (funcall movement-fn arg)
1629 (setq newmark (point)))
1630 (if pushp
1631 (push-mark newmark nil t)
1632 ;; Do not mess with the mark stack, but merely adjust the previous state:
1633 (set-mark newmark)
1634 (activate-region))))
1635
1636 ;(defun transient-mark-mode (arg)
1637 ; "Toggle Transient Mark mode.
1638 ;With arg, turn Transient Mark mode on if arg is positive, off otherwise.
1639 ;
1640 ;In Transient Mark mode, when the mark is active, the region is highlighted.
1641 ;Changing the buffer \"deactivates\" the mark.
1642 ;So do certain other operations that set the mark
1643 ;but whose main purpose is something else--for example,
1644 ;incremental search, \\[beginning-of-buffer], and \\[end-of-buffer]."
1645 ; (interactive "P")
1646 ; (setq transient-mark-mode
1647 ; (if (null arg)
1648 ; (not transient-mark-mode)
1649 ; (> (prefix-numeric-value arg) 0))))
1650
1651 (defun pop-global-mark ()
1652 "Pop off global mark ring and jump to the top location."
1653 (interactive)
1654 ;; Pop entries which refer to non-existent buffers.
1655 (while (and global-mark-ring (not (marker-buffer (car global-mark-ring))))
1656 (setq global-mark-ring (cdr global-mark-ring)))
1657 (or global-mark-ring
1658 (error "No global mark set"))
1659 (let* ((marker (car global-mark-ring))
1660 (buffer (marker-buffer marker))
1661 (position (marker-position marker)))
1662 (setq global-mark-ring (nconc (cdr global-mark-ring)
1663 (list (car global-mark-ring))))
1664 (set-buffer buffer)
1665 (or (and (>= position (point-min))
1666 (<= position (point-max)))
1667 (widen))
1668 (goto-char position)
1669 (switch-to-buffer buffer)))
1670
1671
1672 ;;; After 8 years of waiting ... -sb
1673 (defcustom next-line-add-newlines nil ; XEmacs
1674 "*If non-nil, `next-line' inserts newline when the point is at end of buffer.
1675 This behavior used to be the default, and is still default in FSF Emacs.
1676 We think it is an unnecessary and unwanted side-effect."
1677 :type 'boolean
1678 :group 'editing-basics)
1679
1680 (defun next-line (arg)
1681 "Move cursor vertically down ARG lines.
1682 If there is no character in the target line exactly under the current column,
1683 the cursor is positioned after the character in that line which spans this
1684 column, or at the end of the line if it is not long enough.
1685
1686 If there is no line in the buffer after this one, behavior depends on the
1687 value of `next-line-add-newlines'. If non-nil, it inserts a newline character
1688 to create a line, and moves the cursor to that line. Otherwise it moves the
1689 cursor to the end of the buffer.
1690
1691 The command \\[set-goal-column] can be used to create
1692 a semipermanent goal column to which this command always moves.
1693 Then it does not try to move vertically. This goal column is stored
1694 in `goal-column', which is nil when there is none.
1695
1696 If you are thinking of using this in a Lisp program, consider
1697 using `forward-line' instead. It is usually easier to use
1698 and more reliable (no dependence on goal column, etc.)."
1699 (interactive "_p") ; XEmacs
1700 (if (and next-line-add-newlines (= arg 1))
1701 (let ((opoint (point)))
1702 (end-of-line)
1703 (if (eobp)
1704 (newline 1)
1705 (goto-char opoint)
1706 (line-move arg)))
1707 (if (interactive-p)
1708 ;; XEmacs: Not sure what to do about this. It's inconsistent. -sb
1709 (condition-case nil
1710 (line-move arg)
1711 ((beginning-of-buffer end-of-buffer)
1712 (when signal-error-on-buffer-boundary
1713 (ding nil 'buffer-bound))))
1714 (line-move arg)))
1715 nil)
1716
1717 (defun previous-line (arg)
1718 "Move cursor vertically up ARG lines.
1719 If there is no character in the target line exactly over the current column,
1720 the cursor is positioned after the character in that line which spans this
1721 column, or at the end of the line if it is not long enough.
1722
1723 The command \\[set-goal-column] can be used to create
1724 a semipermanent goal column to which this command always moves.
1725 Then it does not try to move vertically.
1726
1727 If you are thinking of using this in a Lisp program, consider using
1728 `forward-line' with a negative argument instead. It is usually easier
1729 to use and more reliable (no dependence on goal column, etc.)."
1730 (interactive "_p") ; XEmacs
1731 (if (interactive-p)
1732 (condition-case nil
1733 (line-move (- arg))
1734 ((beginning-of-buffer end-of-buffer)
1735 (when signal-error-on-buffer-boundary ; XEmacs
1736 (ding nil 'buffer-bound))))
1737 (line-move (- arg)))
1738 nil)
1739
1740 (defcustom track-eol nil
1741 "*Non-nil means vertical motion starting at end of line keeps to ends of lines.
1742 This means moving to the end of each line moved onto.
1743 The beginning of a blank line does not count as the end of a line."
1744 :type 'boolean
1745 :group 'editing-basics)
1746
1747 (defcustom goal-column nil
1748 "*Semipermanent goal column for vertical motion, as set by \\[set-goal-column], or nil."
1749 :type '(choice integer (const :tag "None" nil))
1750 :group 'editing-basics)
1751 (make-variable-buffer-local 'goal-column)
1752
1753 (defvar temporary-goal-column 0
1754 "Current goal column for vertical motion.
1755 It is the column where point was
1756 at the start of current run of vertical motion commands.
1757 When the `track-eol' feature is doing its job, the value is 9999.")
1758
1759 ;XEmacs: not yet ported, so avoid compiler warnings
1760 (eval-when-compile
1761 (defvar inhibit-point-motion-hooks))
1762
1763 (defcustom line-move-ignore-invisible nil
1764 "*Non-nil means \\[next-line] and \\[previous-line] ignore invisible lines.
1765 Use with care, as it slows down movement significantly. Outline mode sets this."
1766 :type 'boolean
1767 :group 'editing-basics)
1768
1769 ;; This is the guts of next-line and previous-line.
1770 ;; Arg says how many lines to move.
1771 (defun line-move (arg)
1772 ;; Don't run any point-motion hooks, and disregard intangibility,
1773 ;; for intermediate positions.
1774 (let ((inhibit-point-motion-hooks t)
1775 (opoint (point))
1776 new)
1777 (unwind-protect
1778 (progn
1779 (if (not (or (eq last-command 'next-line)
1780 (eq last-command 'previous-line)))
1781 (setq temporary-goal-column
1782 (if (and track-eol (eolp)
1783 ;; Don't count beg of empty line as end of line
1784 ;; unless we just did explicit end-of-line.
1785 (or (not (bolp)) (eq last-command 'end-of-line)))
1786 9999
1787 (current-column))))
1788 (if (and (not (integerp selective-display))
1789 (not line-move-ignore-invisible))
1790 ;; Use just newline characters.
1791 (or (if (> arg 0)
1792 (progn (if (> arg 1) (forward-line (1- arg)))
1793 ;; This way of moving forward ARG lines
1794 ;; verifies that we have a newline after the last one.
1795 ;; It doesn't get confused by intangible text.
1796 (end-of-line)
1797 (zerop (forward-line 1)))
1798 (and (zerop (forward-line arg))
1799 (bolp)))
1800 (signal (if (< arg 0)
1801 'beginning-of-buffer
1802 'end-of-buffer)
1803 nil))
1804 ;; Move by arg lines, but ignore invisible ones.
1805 (while (> arg 0)
1806 (end-of-line)
1807 (and (zerop (vertical-motion 1))
1808 (signal 'end-of-buffer nil))
1809 ;; If the following character is currently invisible,
1810 ;; skip all characters with that same `invisible' property value.
1811 (while (and (not (eobp))
1812 (let ((prop
1813 (get-char-property (point) 'invisible)))
1814 (if (eq buffer-invisibility-spec t)
1815 prop
1816 (or (memq prop buffer-invisibility-spec)
1817 (assq prop buffer-invisibility-spec)))))
1818 (if (get-text-property (point) 'invisible)
1819 (goto-char (next-single-property-change (point) 'invisible))
1820 (goto-char (next-extent-change (point))))) ; XEmacs
1821 (setq arg (1- arg)))
1822 (while (< arg 0)
1823 (beginning-of-line)
1824 (and (zerop (vertical-motion -1))
1825 (signal 'beginning-of-buffer nil))
1826 (while (and (not (bobp))
1827 (let ((prop
1828 (get-char-property (1- (point)) 'invisible)))
1829 (if (eq buffer-invisibility-spec t)
1830 prop
1831 (or (memq prop buffer-invisibility-spec)
1832 (assq prop buffer-invisibility-spec)))))
1833 (if (get-text-property (1- (point)) 'invisible)
1834 (goto-char (previous-single-property-change (point) 'invisible))
1835 (goto-char (previous-extent-change (point))))) ; XEmacs
1836 (setq arg (1+ arg))))
1837 (move-to-column (or goal-column temporary-goal-column)))
1838 ;; Remember where we moved to, go back home,
1839 ;; then do the motion over again
1840 ;; in just one step, with intangibility and point-motion hooks
1841 ;; enabled this time.
1842 (setq new (point))
1843 (goto-char opoint)
1844 (setq inhibit-point-motion-hooks nil)
1845 (goto-char new)))
1846 nil)
1847
1848 ;;; Many people have said they rarely use this feature, and often type
1849 ;;; it by accident. Maybe it shouldn't even be on a key.
1850 ;; It's not on a key, as of 20.2. So no need for this.
1851 ;(put 'set-goal-column 'disabled t)
1852
1853 (defun set-goal-column (arg)
1854 "Set the current horizontal position as a goal for \\[next-line] and \\[previous-line].
1855 Those commands will move to this position in the line moved to
1856 rather than trying to keep the same horizontal position.
1857 With a non-nil argument, clears out the goal column
1858 so that \\[next-line] and \\[previous-line] resume vertical motion.
1859 The goal column is stored in the variable `goal-column'."
1860 (interactive "_P") ; XEmacs
1861 (if arg
1862 (progn
1863 (setq goal-column nil)
1864 (display-message 'command "No goal column"))
1865 (setq goal-column (current-column))
1866 (message (substitute-command-keys
1867 "Goal column %d (use \\[set-goal-column] with an arg to unset it)")
1868 goal-column))
1869 nil)
1870
1871 ;; deleted FSFmacs terminal randomness hscroll-point-visible stuff.
1872 ;; hscroll-step
1873 ;; hscroll-point-visible
1874 ;; hscroll-window-column
1875 ;; right-arrow
1876 ;; left-arrow
1877
1878 (defun scroll-other-window-down (lines)
1879 "Scroll the \"other window\" down.
1880 For more details, see the documentation for `scroll-other-window'."
1881 (interactive "P")
1882 (scroll-other-window
1883 ;; Just invert the argument's meaning.
1884 ;; We can do that without knowing which window it will be.
1885 (if (eq lines '-) nil
1886 (if (null lines) '-
1887 (- (prefix-numeric-value lines))))))
1888 ;(define-key esc-map [?\C-\S-v] 'scroll-other-window-down)
1889
1890 (defun beginning-of-buffer-other-window (arg)
1891 "Move point to the beginning of the buffer in the other window.
1892 Leave mark at previous position.
1893 With arg N, put point N/10 of the way from the true beginning."
1894 (interactive "P")
1895 (let ((orig-window (selected-window))
1896 (window (other-window-for-scrolling)))
1897 ;; We use unwind-protect rather than save-window-excursion
1898 ;; because the latter would preserve the things we want to change.
1899 (unwind-protect
1900 (progn
1901 (select-window window)
1902 ;; Set point and mark in that window's buffer.
1903 (beginning-of-buffer arg)
1904 ;; Set point accordingly.
1905 (recenter '(t)))
1906 (select-window orig-window))))
1907
1908 (defun end-of-buffer-other-window (arg)
1909 "Move point to the end of the buffer in the other window.
1910 Leave mark at previous position.
1911 With arg N, put point N/10 of the way from the true end."
1912 (interactive "P")
1913 ;; See beginning-of-buffer-other-window for comments.
1914 (let ((orig-window (selected-window))
1915 (window (other-window-for-scrolling)))
1916 (unwind-protect
1917 (progn
1918 (select-window window)
1919 (end-of-buffer arg)
1920 (recenter '(t)))
1921 (select-window orig-window))))
1922
1923 (defun transpose-chars (arg)
1924 "Interchange characters around point, moving forward one character.
1925 With prefix arg ARG, effect is to take character before point
1926 and drag it forward past ARG other characters (backward if ARG negative).
1927 If no argument and at end of line, the previous two chars are exchanged."
1928 (interactive "*P")
1929 (and (null arg) (eolp) (forward-char -1))
1930 (transpose-subr 'forward-char (prefix-numeric-value arg)))
1931
1932 ;;; A very old implementation of transpose-chars from the old days ...
1933 (defun transpose-preceding-chars (arg)
1934 "Interchange characters before point.
1935 With prefix arg ARG, effect is to take character before point
1936 and drag it forward past ARG other characters (backward if ARG negative).
1937 If no argument and not at start of line, the previous two chars are exchanged."
1938 (interactive "*P")
1939 (and (null arg) (not (bolp)) (forward-char -1))
1940 (transpose-subr 'forward-char (prefix-numeric-value arg)))
1941
1942
1943 (defun transpose-words (arg)
1944 "Interchange words around point, leaving point at end of them.
1945 With prefix arg ARG, effect is to take word before or around point
1946 and drag it forward past ARG other words (backward if ARG negative).
1947 If ARG is zero, the words around or after point and around or after mark
1948 are interchanged."
1949 (interactive "*p")
1950 (transpose-subr 'forward-word arg))
1951
1952 (defun transpose-sexps (arg)
1953 "Like \\[transpose-words] but applies to sexps.
1954 Does not work on a sexp that point is in the middle of
1955 if it is a list or string."
1956 (interactive "*p")
1957 (transpose-subr 'forward-sexp arg))
1958
1959 (defun transpose-lines (arg)
1960 "Exchange current line and previous line, leaving point after both.
1961 With argument ARG, takes previous line and moves it past ARG lines.
1962 With argument 0, interchanges line point is in with line mark is in."
1963 (interactive "*p")
1964 (transpose-subr #'(lambda (arg)
1965 (if (= arg 1)
1966 (progn
1967 ;; Move forward over a line,
1968 ;; but create a newline if none exists yet.
1969 (end-of-line)
1970 (if (eobp)
1971 (newline)
1972 (forward-char 1)))
1973 (forward-line arg)))
1974 arg))
1975
1976 (eval-when-compile
1977 ;; avoid byte-compiler warnings...
1978 (defvar start1)
1979 (defvar start2)
1980 (defvar end1)
1981 (defvar end2))
1982
1983 ; start[12] and end[12] used in transpose-subr-1 below
1984 (defun transpose-subr (mover arg)
1985 (let (start1 end1 start2 end2)
1986 (if (= arg 0)
1987 (progn
1988 (save-excursion
1989 (funcall mover 1)
1990 (setq end2 (point))
1991 (funcall mover -1)
1992 (setq start2 (point))
1993 (goto-char (mark t)) ; XEmacs
1994 (funcall mover 1)
1995 (setq end1 (point))
1996 (funcall mover -1)
1997 (setq start1 (point))
1998 (transpose-subr-1))
1999 (exchange-point-and-mark t))) ; XEmacs
2000 (while (> arg 0)
2001 (funcall mover -1)
2002 (setq start1 (point))
2003 (funcall mover 1)
2004 (setq end1 (point))
2005 (funcall mover 1)
2006 (setq end2 (point))
2007 (funcall mover -1)
2008 (setq start2 (point))
2009 (transpose-subr-1)
2010 (goto-char end2)
2011 (setq arg (1- arg)))
2012 (while (< arg 0)
2013 (funcall mover -1)
2014 (setq start2 (point))
2015 (funcall mover -1)
2016 (setq start1 (point))
2017 (funcall mover 1)
2018 (setq end1 (point))
2019 (funcall mover 1)
2020 (setq end2 (point))
2021 (transpose-subr-1)
2022 (setq arg (1+ arg)))))
2023
2024 ; start[12] and end[12] used free
2025 (defun transpose-subr-1 ()
2026 (if (> (min end1 end2) (max start1 start2))
2027 (error "Don't have two things to transpose"))
2028 (let ((word1 (buffer-substring start1 end1))
2029 (word2 (buffer-substring start2 end2)))
2030 (delete-region start2 end2)
2031 (goto-char start2)
2032 (insert word1)
2033 (goto-char (if (< start1 start2) start1
2034 (+ start1 (- (length word1) (length word2)))))
2035 (delete-char (length word1))
2036 (insert word2)))
2037
2038 (defcustom comment-column 32
2039 "*Column to indent right-margin comments to.
2040 Setting this variable automatically makes it local to the current buffer.
2041 Each mode establishes a different default value for this variable; you
2042 can set the value for a particular mode using that mode's hook."
2043 :type 'integer
2044 :group 'fill-comments)
2045 (make-variable-buffer-local 'comment-column)
2046
2047 (defcustom comment-start nil
2048 "*String to insert to start a new comment, or nil if no comment syntax."
2049 :type '(choice (const :tag "None" nil)
2050 string)
2051 :group 'fill-comments)
2052
2053 (defcustom comment-start-skip nil
2054 "*Regexp to match the start of a comment plus everything up to its body.
2055 If there are any \\(...\\) pairs, the comment delimiter text is held to begin
2056 at the place matched by the close of the first pair."
2057 :type '(choice (const :tag "None" nil)
2058 regexp)
2059 :group 'fill-comments)
2060
2061 (defcustom comment-end ""
2062 "*String to insert to end a new comment.
2063 Should be an empty string if comments are terminated by end-of-line."
2064 :type 'string
2065 :group 'fill-comments)
2066
2067 (defconst comment-indent-hook nil
2068 "Obsolete variable for function to compute desired indentation for a comment.
2069 Use `comment-indent-function' instead.
2070 This function is called with no args with point at the beginning of
2071 the comment's starting delimiter.")
2072
2073 (defconst comment-indent-function
2074 ;; XEmacs - add at least one space after the end of the text on the
2075 ;; current line...
2076 (lambda ()
2077 (save-excursion
2078 (beginning-of-line)
2079 (let ((eol (save-excursion (end-of-line) (point))))
2080 (and comment-start-skip
2081 (re-search-forward comment-start-skip eol t)
2082 (setq eol (match-beginning 0)))
2083 (goto-char eol)
2084 (skip-chars-backward " \t")
2085 (max comment-column (1+ (current-column))))))
2086 "Function to compute desired indentation for a comment.
2087 This function is called with no args with point at the beginning of
2088 the comment's starting delimiter.")
2089
2090 (defcustom block-comment-start nil
2091 "*String to insert to start a new comment on a line by itself.
2092 If nil, use `comment-start' instead.
2093 Note that the regular expression `comment-start-skip' should skip this string
2094 as well as the `comment-start' string."
2095 :type '(choice (const :tag "Use `comment-start'" nil)
2096 string)
2097 :group 'fill-comments)
2098
2099 (defcustom block-comment-end nil
2100 "*String to insert to end a new comment on a line by itself.
2101 Should be an empty string if comments are terminated by end-of-line.
2102 If nil, use `comment-end' instead."
2103 :type '(choice (const :tag "Use `comment-end'" nil)
2104 string)
2105 :group 'fill-comments)
2106
2107 (defun indent-for-comment ()
2108 "Indent this line's comment to comment column, or insert an empty comment."
2109 (interactive "*")
2110 (let* ((empty (save-excursion (beginning-of-line)
2111 (looking-at "[ \t]*$")))
2112 (starter (or (and empty block-comment-start) comment-start))
2113 (ender (or (and empty block-comment-end) comment-end)))
2114 (if (null starter)
2115 (error "No comment syntax defined")
2116 (let* ((eolpos (save-excursion (end-of-line) (point)))
2117 cpos indent begpos)
2118 (beginning-of-line)
2119 (if (re-search-forward comment-start-skip eolpos 'move)
2120 (progn (setq cpos (point-marker))
2121 ;; Find the start of the comment delimiter.
2122 ;; If there were paren-pairs in comment-start-skip,
2123 ;; position at the end of the first pair.
2124 (if (match-end 1)
2125 (goto-char (match-end 1))
2126 ;; If comment-start-skip matched a string with
2127 ;; internal whitespace (not final whitespace) then
2128 ;; the delimiter start at the end of that
2129 ;; whitespace. Otherwise, it starts at the
2130 ;; beginning of what was matched.
2131 (skip-syntax-backward " " (match-beginning 0))
2132 (skip-syntax-backward "^ " (match-beginning 0)))))
2133 (setq begpos (point))
2134 ;; Compute desired indent.
2135 (if (= (current-column)
2136 (setq indent (funcall comment-indent-function)))
2137 (goto-char begpos)
2138 ;; If that's different from current, change it.
2139 (skip-chars-backward " \t")
2140 (delete-region (point) begpos)
2141 (indent-to indent))
2142 ;; An existing comment?
2143 (if cpos
2144 (progn (goto-char cpos)
2145 (set-marker cpos nil))
2146 ;; No, insert one.
2147 (insert starter)
2148 (save-excursion
2149 (insert ender)))))))
2150
2151 (defun set-comment-column (arg)
2152 "Set the comment column based on point.
2153 With no arg, set the comment column to the current column.
2154 With just minus as arg, kill any comment on this line.
2155 With any other arg, set comment column to indentation of the previous comment
2156 and then align or create a comment on this line at that column."
2157 (interactive "P")
2158 (if (eq arg '-)
2159 (kill-comment nil)
2160 (if arg
2161 (progn
2162 (save-excursion
2163 (beginning-of-line)
2164 (re-search-backward comment-start-skip)
2165 (beginning-of-line)
2166 (re-search-forward comment-start-skip)
2167 (goto-char (match-beginning 0))
2168 (setq comment-column (current-column))
2169 (display-message
2170 'command
2171 (format "Comment column set to %d" comment-column)))
2172 (indent-for-comment))
2173 (setq comment-column (current-column))
2174 (display-message
2175 'command
2176 (format "Comment column set to %d" comment-column)))))
2177
2178 (defun kill-comment (arg)
2179 "Kill the comment on this line, if any.
2180 With argument, kill comments on that many lines starting with this one."
2181 ;; this function loses in a lot of situations. it incorrectly recognises
2182 ;; comment delimiters sometimes (ergo, inside a string), doesn't work
2183 ;; with multi-line comments, can kill extra whitespace if comment wasn't
2184 ;; through end-of-line, et cetera.
2185 (interactive "*P")
2186 (or comment-start-skip (error "No comment syntax defined"))
2187 (let ((count (prefix-numeric-value arg)) endc)
2188 (while (> count 0)
2189 (save-excursion
2190 (end-of-line)
2191 (setq endc (point))
2192 (beginning-of-line)
2193 (and (string< "" comment-end)
2194 (setq endc
2195 (progn
2196 (re-search-forward (regexp-quote comment-end) endc 'move)
2197 (skip-chars-forward " \t")
2198 (point))))
2199 (beginning-of-line)
2200 (if (re-search-forward comment-start-skip endc t)
2201 (progn
2202 (goto-char (match-beginning 0))
2203 (skip-chars-backward " \t")
2204 (kill-region (point) endc)
2205 ;; to catch comments a line beginnings
2206 (indent-according-to-mode))))
2207 (if arg (forward-line 1))
2208 (setq count (1- count)))))
2209
2210 (defun comment-region (beg end &optional arg)
2211 "Comment or uncomment each line in the region.
2212 With just C-u prefix arg, uncomment each line in region.
2213 Numeric prefix arg ARG means use ARG comment characters.
2214 If ARG is negative, delete that many comment characters instead.
2215 Comments are terminated on each line, even for syntax in which newline does
2216 not end the comment. Blank lines do not get comments."
2217 ;; if someone wants it to only put a comment-start at the beginning and
2218 ;; comment-end at the end then typing it, C-x C-x, closing it, C-x C-x
2219 ;; is easy enough. No option is made here for other than commenting
2220 ;; every line.
2221 (interactive "r\nP")
2222 (or comment-start (error "No comment syntax is defined"))
2223 (if (> beg end) (let (mid) (setq mid beg beg end end mid)))
2224 (save-excursion
2225 (save-restriction
2226 (let ((cs comment-start) (ce comment-end)
2227 numarg)
2228 (if (consp arg) (setq numarg t)
2229 (setq numarg (prefix-numeric-value arg))
2230 ;; For positive arg > 1, replicate the comment delims now,
2231 ;; then insert the replicated strings just once.
2232 (while (> numarg 1)
2233 (setq cs (concat cs comment-start)
2234 ce (concat ce comment-end))
2235 (setq numarg (1- numarg))))
2236 ;; Loop over all lines from BEG to END.
2237 (narrow-to-region beg end)
2238 (goto-char beg)
2239 (while (not (eobp))
2240 (if (or (eq numarg t) (< numarg 0))
2241 (progn
2242 ;; Delete comment start from beginning of line.
2243 (if (eq numarg t)
2244 (while (looking-at (regexp-quote cs))
2245 (delete-char (length cs)))
2246 (let ((count numarg))
2247 (while (and (> 1 (setq count (1+ count)))
2248 (looking-at (regexp-quote cs)))
2249 (delete-char (length cs)))))
2250 ;; Delete comment end from end of line.
2251 (if (string= "" ce)
2252 nil
2253 (if (eq numarg t)
2254 (progn
2255 (end-of-line)
2256 ;; This is questionable if comment-end ends in
2257 ;; whitespace. That is pretty brain-damaged,
2258 ;; though.
2259 (skip-chars-backward " \t")
2260 (if (and (>= (- (point) (point-min)) (length ce))
2261 (save-excursion
2262 (backward-char (length ce))
2263 (looking-at (regexp-quote ce))))
2264 (delete-char (- (length ce)))))
2265 (let ((count numarg))
2266 (while (> 1 (setq count (1+ count)))
2267 (end-of-line)
2268 ;; This is questionable if comment-end ends in
2269 ;; whitespace. That is pretty brain-damaged though
2270 (skip-chars-backward " \t")
2271 (save-excursion
2272 (backward-char (length ce))
2273 (if (looking-at (regexp-quote ce))
2274 (delete-char (length ce))))))))
2275 (forward-line 1))
2276 ;; Insert at beginning and at end.
2277 (if (looking-at "[ \t]*$") ()
2278 (insert cs)
2279 (if (string= "" ce) ()
2280 (end-of-line)
2281 (insert ce)))
2282 (search-forward "\n" nil 'move)))))))
2283
2284 ;; XEmacs
2285 (defun prefix-region (prefix)
2286 "Add a prefix string to each line between mark and point."
2287 (interactive "sPrefix string: ")
2288 (if prefix
2289 (let ((count (count-lines (mark) (point))))
2290 (goto-char (min (mark) (point)))
2291 (while (> count 0)
2292 (setq count (1- count))
2293 (beginning-of-line 1)
2294 (insert prefix)
2295 (end-of-line 1)
2296 (forward-char 1)))))
2297
2298
2299 ;; XEmacs - extra parameter
2300 (defun backward-word (arg &optional buffer)
2301 "Move backward until encountering the end of a word.
2302 With argument, do this that many times.
2303 In programs, it is faster to call `forward-word' with negative arg."
2304 (interactive "_p") ; XEmacs
2305 (forward-word (- arg) buffer))
2306
2307 (defun mark-word (arg)
2308 "Set mark arg words away from point."
2309 (interactive "p")
2310 (mark-something 'mark-word 'forward-word arg))
2311
2312 ;; XEmacs modified
2313 (defun kill-word (arg)
2314 "Kill characters forward until encountering the end of a word.
2315 With argument, do this that many times."
2316 (interactive "*p")
2317 (kill-region (point) (save-excursion (forward-word arg) (point))))
2318
2319 (defun backward-kill-word (arg)
2320 "Kill characters backward until encountering the end of a word.
2321 With argument, do this that many times."
2322 (interactive "*p") ; XEmacs
2323 (kill-word (- arg)))
2324
2325 (defun current-word (&optional strict)
2326 "Return the word point is on (or a nearby word) as a string.
2327 If optional arg STRICT is non-nil, return nil unless point is within
2328 or adjacent to a word.
2329 If point is not between two word-constituent characters, but immediately
2330 follows one, move back first.
2331 Otherwise, if point precedes a word constituent, move forward first.
2332 Otherwise, move backwards until a word constituent is found and get that word;
2333 if you a newlines is reached first, move forward instead."
2334 (save-excursion
2335 (let ((oldpoint (point)) (start (point)) (end (point)))
2336 (skip-syntax-backward "w_") (setq start (point))
2337 (goto-char oldpoint)
2338 (skip-syntax-forward "w_") (setq end (point))
2339 (if (and (eq start oldpoint) (eq end oldpoint))
2340 ;; Point is neither within nor adjacent to a word.
2341 (and (not strict)
2342 (progn
2343 ;; Look for preceding word in same line.
2344 (skip-syntax-backward "^w_"
2345 (save-excursion
2346 (beginning-of-line) (point)))
2347 (if (bolp)
2348 ;; No preceding word in same line.
2349 ;; Look for following word in same line.
2350 (progn
2351 (skip-syntax-forward "^w_"
2352 (save-excursion
2353 (end-of-line) (point)))
2354 (setq start (point))
2355 (skip-syntax-forward "w_")
2356 (setq end (point)))
2357 (setq end (point))
2358 (skip-syntax-backward "w_")
2359 (setq start (point)))
2360 (buffer-substring start end)))
2361 (buffer-substring start end)))))
2362
2363 (defcustom fill-prefix nil
2364 "*String for filling to insert at front of new line, or nil for none.
2365 Setting this variable automatically makes it local to the current buffer."
2366 :type '(choice (const :tag "None" nil)
2367 string)
2368 :group 'fill)
2369 (make-variable-buffer-local 'fill-prefix)
2370
2371 (defcustom auto-fill-inhibit-regexp nil
2372 "*Regexp to match lines which should not be auto-filled."
2373 :type '(choice (const :tag "None" nil)
2374 regexp)
2375 :group 'fill)
2376
2377 (defvar comment-line-break-function 'indent-new-comment-line
2378 "*Mode-specific function which line breaks and continues a comment.
2379
2380 This function is only called during auto-filling of a comment section.
2381 The function should take a single optional argument which is a flag
2382 indicating whether soft newlines should be inserted.")
2383
2384 ;; This function is the auto-fill-function of a buffer
2385 ;; when Auto-Fill mode is enabled.
2386 ;; It returns t if it really did any work.
2387 ;; XEmacs: This function is totally different.
2388 (defun do-auto-fill ()
2389 (let (give-up)
2390 (or (and auto-fill-inhibit-regexp
2391 (save-excursion (beginning-of-line)
2392 (looking-at auto-fill-inhibit-regexp)))
2393 (while (and (not give-up) (> (current-column) fill-column))
2394 ;; Determine where to split the line.
2395 (let ((fill-prefix fill-prefix)
2396 (fill-point
2397 (let ((opoint (point))
2398 bounce
2399 ;; 97/3/14 jhod: Kinsoku
2400 (re-break-point (if (featurep 'mule)
2401 (concat "[ \t\n]\\|" word-across-newline)
2402 "[ \t\n]"))
2403 ;; end patch
2404 (first t))
2405 (save-excursion
2406 (move-to-column (1+ fill-column))
2407 ;; Move back to a word boundary.
2408 (while (or first
2409 ;; If this is after period and a single space,
2410 ;; move back once more--we don't want to break
2411 ;; the line there and make it look like a
2412 ;; sentence end.
2413 (and (not (bobp))
2414 (not bounce)
2415 sentence-end-double-space
2416 (save-excursion (forward-char -1)
2417 (and (looking-at "\\. ")
2418 (not (looking-at "\\. "))))))
2419 (setq first nil)
2420 ;; 97/3/14 jhod: Kinsoku
2421 ; (skip-chars-backward "^ \t\n"))
2422 (fill-move-backward-to-break-point re-break-point)
2423 ;; end patch
2424 ;; If we find nowhere on the line to break it,
2425 ;; break after one word. Set bounce to t
2426 ;; so we will not keep going in this while loop.
2427 (if (bolp)
2428 (progn
2429 ;; 97/3/14 jhod: Kinsoku
2430 ; (re-search-forward "[ \t]" opoint t)
2431 (fill-move-forward-to-break-point re-break-point
2432 opoint)
2433 ;; end patch
2434 (setq bounce t)))
2435 (skip-chars-backward " \t"))
2436 (if (and (featurep 'mule)
2437 (or bounce (bolp))) (kinsoku-process)) ;; 97/3/14 jhod: Kinsoku
2438 ;; Let fill-point be set to the place where we end up.
2439 (point)))))
2440
2441 ;; I'm not sure why Stig made this change but it breaks
2442 ;; auto filling in at least C mode so I'm taking it back
2443 ;; out. --cet
2444 ;; XEmacs - adaptive fill.
2445 ;;(maybe-adapt-fill-prefix
2446 ;; (or from (setq from (save-excursion (beginning-of-line)
2447 ;; (point))))
2448 ;; (or to (setq to (save-excursion (beginning-of-line 2)
2449 ;; (point))))
2450 ;; t)
2451
2452 ;; If that place is not the beginning of the line,
2453 ;; break the line there.
2454 (if (save-excursion
2455 (goto-char fill-point)
2456 (not (or (bolp) (eolp)))) ; 97/3/14 jhod: during kinsoku processing it is possible to move beyond
2457 (let ((prev-column (current-column)))
2458 ;; If point is at the fill-point, do not `save-excursion'.
2459 ;; Otherwise, if a comment prefix or fill-prefix is inserted,
2460 ;; point will end up before it rather than after it.
2461 (if (save-excursion
2462 (skip-chars-backward " \t")
2463 (= (point) fill-point))
2464 ;; 97/3/14 jhod: Kinsoku processing
2465 ;(indent-new-comment-line)
2466 (let ((spacep (memq (char-before (point)) '(?\ ?\t))))
2467 (funcall comment-line-break-function)
2468 ;; if user type space explicitly, leave SPC
2469 ;; even if there is no WAN.
2470 (if spacep
2471 (save-excursion
2472 (goto-char fill-point)
2473 ;; put SPC except that there is SPC
2474 ;; already or there is sentence end.
2475 (or (memq (char-after (point)) '(?\ ?\t))
2476 (fill-end-of-sentence-p)
2477 (insert ?\ )))))
2478 (save-excursion
2479 (goto-char fill-point)
2480 (funcall comment-line-break-function)))
2481 ;; If making the new line didn't reduce the hpos of
2482 ;; the end of the line, then give up now;
2483 ;; trying again will not help.
2484 (if (>= (current-column) prev-column)
2485 (setq give-up t)))
2486 ;; No place to break => stop trying.
2487 (setq give-up t)))))))
2488
2489 ;; Put FSF one in until I can one or the other working properly, then the
2490 ;; other one is history.
2491 (defun fsf:do-auto-fill ()
2492 (let (fc justify
2493 ;; bol
2494 give-up
2495 (fill-prefix fill-prefix))
2496 (if (or (not (setq justify (current-justification)))
2497 (null (setq fc (current-fill-column)))
2498 (and (eq justify 'left)
2499 (<= (current-column) fc))
2500 (save-excursion (beginning-of-line)
2501 ;; (setq bol (point))
2502 (and auto-fill-inhibit-regexp
2503 (looking-at auto-fill-inhibit-regexp))))
2504 nil ;; Auto-filling not required
2505 (if (memq justify '(full center right))
2506 (save-excursion (unjustify-current-line)))
2507
2508 ;; Choose a fill-prefix automatically.
2509 (if (and adaptive-fill-mode
2510 (or (null fill-prefix) (string= fill-prefix "")))
2511 (let ((prefix
2512 (fill-context-prefix
2513 (save-excursion (backward-paragraph 1) (point))
2514 (save-excursion (forward-paragraph 1) (point))
2515 ;; Don't accept a non-whitespace fill prefix
2516 ;; from the first line of a paragraph.
2517 "^[ \t]*$")))
2518 (and prefix (not (equal prefix ""))
2519 (setq fill-prefix prefix))))
2520
2521 (while (and (not give-up) (> (current-column) fc))
2522 ;; Determine where to split the line.
2523 (let ((fill-point
2524 (let ((opoint (point))
2525 bounce
2526 (first t))
2527 (save-excursion
2528 (move-to-column (1+ fc))
2529 ;; Move back to a word boundary.
2530 (while (or first
2531 ;; If this is after period and a single space,
2532 ;; move back once more--we don't want to break
2533 ;; the line there and make it look like a
2534 ;; sentence end.
2535 (and (not (bobp))
2536 (not bounce)
2537 sentence-end-double-space
2538 (save-excursion (forward-char -1)
2539 (and (looking-at "\\. ")
2540 (not (looking-at "\\. "))))))
2541 (setq first nil)
2542 (skip-chars-backward "^ \t\n")
2543 ;; If we find nowhere on the line to break it,
2544 ;; break after one word. Set bounce to t
2545 ;; so we will not keep going in this while loop.
2546 (if (bolp)
2547 (progn
2548 (re-search-forward "[ \t]" opoint t)
2549 (setq bounce t)))
2550 (skip-chars-backward " \t"))
2551 ;; Let fill-point be set to the place where we end up.
2552 (point)))))
2553 ;; If that place is not the beginning of the line,
2554 ;; break the line there.
2555 (if (save-excursion
2556 (goto-char fill-point)
2557 (not (bolp)))
2558 (let ((prev-column (current-column)))
2559 ;; If point is at the fill-point, do not `save-excursion'.
2560 ;; Otherwise, if a comment prefix or fill-prefix is inserted,
2561 ;; point will end up before it rather than after it.
2562 (if (save-excursion
2563 (skip-chars-backward " \t")
2564 (= (point) fill-point))
2565 (funcall comment-line-break-function t)
2566 (save-excursion
2567 (goto-char fill-point)
2568 (funcall comment-line-break-function t)))
2569 ;; Now do justification, if required
2570 (if (not (eq justify 'left))
2571 (save-excursion
2572 (end-of-line 0)
2573 (justify-current-line justify nil t)))
2574 ;; If making the new line didn't reduce the hpos of
2575 ;; the end of the line, then give up now;
2576 ;; trying again will not help.
2577 (if (>= (current-column) prev-column)
2578 (setq give-up t)))
2579 ;; No place to break => stop trying.
2580 (setq give-up t))))
2581 ;; Justify last line.
2582 (justify-current-line justify t t)
2583 t)))
2584
2585 (defvar normal-auto-fill-function 'do-auto-fill
2586 "The function to use for `auto-fill-function' if Auto Fill mode is turned on.
2587 Some major modes set this.")
2588
2589 (defun auto-fill-mode (&optional arg)
2590 "Toggle auto-fill mode.
2591 With arg, turn auto-fill mode on if and only if arg is positive.
2592 In Auto-Fill mode, inserting a space at a column beyond `current-fill-column'
2593 automatically breaks the line at a previous space.
2594
2595 The value of `normal-auto-fill-function' specifies the function to use
2596 for `auto-fill-function' when turning Auto Fill mode on."
2597 (interactive "P")
2598 (prog1 (setq auto-fill-function
2599 (if (if (null arg)
2600 (not auto-fill-function)
2601 (> (prefix-numeric-value arg) 0))
2602 normal-auto-fill-function
2603 nil))
2604 (redraw-modeline)))
2605
2606 ;; This holds a document string used to document auto-fill-mode.
2607 (defun auto-fill-function ()
2608 "Automatically break line at a previous space, in insertion of text."
2609 nil)
2610
2611 (defun turn-on-auto-fill ()
2612 "Unconditionally turn on Auto Fill mode."
2613 (auto-fill-mode 1))
2614
2615 (defun set-fill-column (arg)
2616 "Set `fill-column' to specified argument.
2617 Just \\[universal-argument] as argument means to use the current column
2618 The variable `fill-column' has a separate value for each buffer."
2619 (interactive "_P") ; XEmacs
2620 (cond ((integerp arg)
2621 (setq fill-column arg))
2622 ((consp arg)
2623 (setq fill-column (current-column)))
2624 ;; Disallow missing argument; it's probably a typo for C-x C-f.
2625 (t
2626 (error "set-fill-column requires an explicit argument")))
2627 (display-message 'command (format "fill-column set to %d" fill-column)))
2628
2629 (defcustom comment-multi-line t ; XEmacs - this works well with adaptive fill
2630 "*Non-nil means \\[indent-new-comment-line] should continue same comment
2631 on new line, with no new terminator or starter.
2632 This is obsolete because you might as well use \\[newline-and-indent]."
2633 :type 'boolean
2634 :group 'fill-comments)
2635
2636 (defun indent-new-comment-line (&optional soft)
2637 "Break line at point and indent, continuing comment if within one.
2638 This indents the body of the continued comment
2639 under the previous comment line.
2640
2641 This command is intended for styles where you write a comment per line,
2642 starting a new comment (and terminating it if necessary) on each line.
2643 If you want to continue one comment across several lines, use \\[newline-and-indent].
2644
2645 If a fill column is specified, it overrides the use of the comment column
2646 or comment indentation.
2647
2648 The inserted newline is marked hard if `use-hard-newlines' is true,
2649 unless optional argument SOFT is non-nil."
2650 (interactive)
2651 (let (comcol comstart)
2652 (skip-chars-backward " \t")
2653 ;; 97/3/14 jhod: Kinsoku processing
2654 (if (featurep 'mule)
2655 (kinsoku-process))
2656 (delete-region (point)
2657 (progn (skip-chars-forward " \t")
2658 (point)))
2659 (if soft (insert ?\n) (newline 1))
2660 (if fill-prefix
2661 (progn
2662 (indent-to-left-margin)
2663 (insert fill-prefix))
2664 ;; #### - Eric Eide reverts to v18 semantics for this function in
2665 ;; fa-extras, which I'm not gonna do. His changes are to (1) execute
2666 ;; the save-excursion below unconditionally, and (2) uncomment the check
2667 ;; for (not comment-multi-line) further below. --Stig
2668 ;;### jhod: probably need to fix this for kinsoku processing
2669 (if (not comment-multi-line)
2670 (save-excursion
2671 (if (and comment-start-skip
2672 (let ((opoint (point)))
2673 (forward-line -1)
2674 (re-search-forward comment-start-skip opoint t)))
2675 ;; The old line is a comment.
2676 ;; Set WIN to the pos of the comment-start.
2677 ;; But if the comment is empty, look at preceding lines
2678 ;; to find one that has a nonempty comment.
2679
2680 ;; If comment-start-skip contains a \(...\) pair,
2681 ;; the real comment delimiter starts at the end of that pair.
2682 (let ((win (or (match-end 1) (match-beginning 0))))
2683 (while (and (eolp) (not (bobp))
2684 (let (opoint)
2685 (beginning-of-line)
2686 (setq opoint (point))
2687 (forward-line -1)
2688 (re-search-forward comment-start-skip opoint t)))
2689 (setq win (or (match-end 1) (match-beginning 0))))
2690 ;; Indent this line like what we found.
2691 (goto-char win)
2692 (setq comcol (current-column))
2693 (setq comstart
2694 (buffer-substring (point) (match-end 0)))))))
2695 (if (and comcol (not fill-prefix)) ; XEmacs - (ENE) from fa-extras.
2696 (let ((comment-column comcol)
2697 (comment-start comstart)
2698 (comment-end comment-end))
2699 (and comment-end (not (equal comment-end ""))
2700 ; (if (not comment-multi-line)
2701 (progn
2702 (forward-char -1)
2703 (insert comment-end)
2704 (forward-char 1))
2705 ; (setq comment-column (+ comment-column (length comment-start))
2706 ; comment-start "")
2707 ; )
2708 )
2709 (if (not (eolp))
2710 (setq comment-end ""))
2711 (insert ?\n)
2712 (forward-char -1)
2713 (indent-for-comment)
2714 (save-excursion
2715 ;; Make sure we delete the newline inserted above.
2716 (end-of-line)
2717 (delete-char 1)))
2718 (indent-according-to-mode)))))
2719
2720
2721 (defun set-selective-display (arg)
2722 "Set `selective-display' to ARG; clear it if no arg.
2723 When the value of `selective-display' is a number > 0,
2724 lines whose indentation is >= that value are not displayed.
2725 The variable `selective-display' has a separate value for each buffer."
2726 (interactive "P")
2727 (if (eq selective-display t)
2728 (error "selective-display already in use for marked lines"))
2729 (let ((current-vpos
2730 (save-restriction
2731 (narrow-to-region (point-min) (point))
2732 (goto-char (window-start))
2733 (vertical-motion (window-height)))))
2734 (setq selective-display
2735 (and arg (prefix-numeric-value arg)))
2736 (recenter current-vpos))
2737 (set-window-start (selected-window) (window-start (selected-window)))
2738 ;; #### doesn't localize properly:
2739 (princ "selective-display set to " t)
2740 (prin1 selective-display t)
2741 (princ "." t))
2742
2743 ;; XEmacs
2744 (defun nuke-selective-display ()
2745 "Ensure that the buffer is not in selective-display mode.
2746 If `selective-display' is t, then restore the buffer text to it's original
2747 state before disabling selective display."
2748 ;; by Stig@hackvan.com
2749 (interactive)
2750 (and (eq t selective-display)
2751 (save-excursion
2752 (save-restriction
2753 (widen)
2754 (goto-char (point-min))
2755 (let ((mod-p (buffer-modified-p))
2756 (buffer-read-only nil))
2757 (while (search-forward "\r" nil t)
2758 (delete-char -1)
2759 (insert "\n"))
2760 (set-buffer-modified-p mod-p)
2761 ))))
2762 (setq selective-display nil))
2763
2764 (add-hook 'change-major-mode-hook 'nuke-selective-display)
2765
2766 (defconst overwrite-mode-textual (purecopy " Ovwrt")
2767 "The string displayed in the mode line when in overwrite mode.")
2768 (defconst overwrite-mode-binary (purecopy " Bin Ovwrt")
2769 "The string displayed in the mode line when in binary overwrite mode.")
2770
2771 (defun overwrite-mode (arg)
2772 "Toggle overwrite mode.
2773 With arg, turn overwrite mode on iff arg is positive.
2774 In overwrite mode, printing characters typed in replace existing text
2775 on a one-for-one basis, rather than pushing it to the right. At the
2776 end of a line, such characters extend the line. Before a tab,
2777 such characters insert until the tab is filled in.
2778 \\[quoted-insert] still inserts characters in overwrite mode; this
2779 is supposed to make it easier to insert characters when necessary."
2780 (interactive "P")
2781 (setq overwrite-mode
2782 (if (if (null arg) (not overwrite-mode)
2783 (> (prefix-numeric-value arg) 0))
2784 'overwrite-mode-textual))
2785 (redraw-modeline))
2786
2787 (defun binary-overwrite-mode (arg)
2788 "Toggle binary overwrite mode.
2789 With arg, turn binary overwrite mode on iff arg is positive.
2790 In binary overwrite mode, printing characters typed in replace
2791 existing text. Newlines are not treated specially, so typing at the
2792 end of a line joins the line to the next, with the typed character
2793 between them. Typing before a tab character simply replaces the tab
2794 with the character typed.
2795 \\[quoted-insert] replaces the text at the cursor, just as ordinary
2796 typing characters do.
2797
2798 Note that binary overwrite mode is not its own minor mode; it is a
2799 specialization of overwrite-mode, entered by setting the
2800 `overwrite-mode' variable to `overwrite-mode-binary'."
2801 (interactive "P")
2802 (setq overwrite-mode
2803 (if (if (null arg)
2804 (not (eq overwrite-mode 'overwrite-mode-binary))
2805 (> (prefix-numeric-value arg) 0))
2806 'overwrite-mode-binary))
2807 (redraw-modeline))
2808
2809 (defcustom line-number-mode nil
2810 "*Non-nil means display line number in modeline."
2811 :type 'boolean
2812 :group 'editing-basics)
2813
2814 (defun line-number-mode (arg)
2815 "Toggle Line Number mode.
2816 With arg, turn Line Number mode on iff arg is positive.
2817 When Line Number mode is enabled, the line number appears
2818 in the mode line."
2819 (interactive "P")
2820 (setq line-number-mode
2821 (if (null arg) (not line-number-mode)
2822 (> (prefix-numeric-value arg) 0)))
2823 (redraw-modeline))
2824
2825 (defcustom column-number-mode nil
2826 "*Non-nil means display column number in mode line."
2827 :type 'boolean
2828 :group 'editing-basics)
2829
2830 (defun column-number-mode (arg)
2831 "Toggle Column Number mode.
2832 With arg, turn Column Number mode on iff arg is positive.
2833 When Column Number mode is enabled, the column number appears
2834 in the mode line."
2835 (interactive "P")
2836 (setq column-number-mode
2837 (if (null arg) (not column-number-mode)
2838 (> (prefix-numeric-value arg) 0)))
2839 (redraw-modeline))
2840
2841
2842 (defcustom blink-matching-paren t
2843 "*Non-nil means show matching open-paren when close-paren is inserted."
2844 :type 'boolean
2845 :group 'paren-blinking)
2846
2847 (defcustom blink-matching-paren-on-screen t
2848 "*Non-nil means show matching open-paren when it is on screen.
2849 nil means don't show it (but the open-paren can still be shown
2850 when it is off screen."
2851 :type 'boolean
2852 :group 'paren-blinking)
2853
2854 (defcustom blink-matching-paren-distance 12000
2855 "*If non-nil, is maximum distance to search for matching open-paren."
2856 :type '(choice integer (const nil))
2857 :group 'paren-blinking)
2858
2859 (defcustom blink-matching-delay 1
2860 "*The number of seconds that `blink-matching-open' will delay at a match."
2861 :type 'number
2862 :group 'paren-blinking)
2863
2864 (defcustom blink-matching-paren-dont-ignore-comments nil
2865 "*Non-nil means `blink-matching-paren' should not ignore comments."
2866 :type 'boolean
2867 :group 'paren-blinking)
2868
2869 (defun blink-matching-open ()
2870 "Move cursor momentarily to the beginning of the sexp before point."
2871 (interactive "_") ; XEmacs
2872 (and (> (point) (1+ (point-min)))
2873 blink-matching-paren
2874 ;; Verify an even number of quoting characters precede the close.
2875 (= 1 (logand 1 (- (point)
2876 (save-excursion
2877 (forward-char -1)
2878 (skip-syntax-backward "/\\")
2879 (point)))))
2880 (let* ((oldpos (point))
2881 (parse-sexp-ignore-comments t) ; to avoid C++ lossage
2882 (blinkpos)
2883 (mismatch))
2884 (save-excursion
2885 (save-restriction
2886 (if blink-matching-paren-distance
2887 (narrow-to-region (max (point-min)
2888 (- (point) blink-matching-paren-distance))
2889 oldpos))
2890 (condition-case ()
2891 (let ((parse-sexp-ignore-comments
2892 (and parse-sexp-ignore-comments
2893 (not blink-matching-paren-dont-ignore-comments))))
2894 (setq blinkpos (scan-sexps oldpos -1)))
2895 (error nil)))
2896 (and blinkpos
2897 (/= (char-syntax (char-after blinkpos))
2898 ?\$)
2899 (setq mismatch
2900 (or (null (matching-paren (char-after blinkpos)))
2901 (/= (char-after (1- oldpos))
2902 (matching-paren (char-after blinkpos))))))
2903 (if mismatch (setq blinkpos nil))
2904 (if blinkpos
2905 (progn
2906 (goto-char blinkpos)
2907 (if (pos-visible-in-window-p)
2908 (and blink-matching-paren-on-screen
2909 (progn
2910 (auto-show-make-point-visible)
2911 (sit-for blink-matching-delay)))
2912 (goto-char blinkpos)
2913 (display-message
2914 'command
2915 (format
2916 "Matches %s"
2917 ;; Show what precedes the open in its line, if anything.
2918 (if (save-excursion
2919 (skip-chars-backward " \t")
2920 (not (bolp)))
2921 (buffer-substring (progn (beginning-of-line) (point))
2922 (1+ blinkpos))
2923 ;; Show what follows the open in its line, if anything.
2924 (if (save-excursion
2925 (forward-char 1)
2926 (skip-chars-forward " \t")
2927 (not (eolp)))
2928 (buffer-substring blinkpos
2929 (progn (end-of-line) (point)))
2930 ;; Otherwise show the previous nonblank line,
2931 ;; if there is one.
2932 (if (save-excursion
2933 (skip-chars-backward "\n \t")
2934 (not (bobp)))
2935 (concat
2936 (buffer-substring (progn
2937 (skip-chars-backward "\n \t")
2938 (beginning-of-line)
2939 (point))
2940 (progn (end-of-line)
2941 (skip-chars-backward " \t")
2942 (point)))
2943 ;; Replace the newline and other whitespace with `...'.
2944 "..."
2945 (buffer-substring blinkpos (1+ blinkpos)))
2946 ;; There is nothing to show except the char itself.
2947 (buffer-substring blinkpos (1+ blinkpos)))))))))
2948 (cond (mismatch
2949 (display-message 'no-log "Mismatched parentheses"))
2950 ((not blink-matching-paren-distance)
2951 (display-message 'no-log "Unmatched parenthesis"))))))))
2952
2953 ;Turned off because it makes dbx bomb out.
2954 (setq blink-paren-function 'blink-matching-open)
2955
2956 (eval-when-compile (defvar myhelp)) ; suppress compiler warning
2957
2958 ;; XEmacs: Some functions moved to cmdloop.el:
2959 ;; keyboard-quit
2960 ;; buffer-quit-function
2961 ;; keyboard-escape-quit
2962
2963 (defun assoc-ignore-case (key alist)
2964 "Like `assoc', but assumes KEY is a string and ignores case when comparing."
2965 (setq key (downcase key))
2966 (let (element)
2967 (while (and alist (not element))
2968 (if (equal key (downcase (car (car alist))))
2969 (setq element (car alist)))
2970 (setq alist (cdr alist)))
2971 element))
2972
2973
2974 (defcustom mail-user-agent 'sendmail-user-agent
2975 "*Your preference for a mail composition package.
2976 Various Emacs Lisp packages (e.g. reporter) require you to compose an
2977 outgoing email message. This variable lets you specify which
2978 mail-sending package you prefer.
2979
2980 Valid values include:
2981
2982 sendmail-user-agent -- use the default Emacs Mail package
2983 mh-e-user-agent -- use the Emacs interface to the MH mail system
2984 message-user-agent -- use the GNUS mail sending package
2985
2986 Additional valid symbols may be available; check with the author of
2987 your package for details."
2988 :type '(radio (function-item :tag "Default Emacs mail"
2989 :format "%t\n"
2990 sendmail-user-agent)
2991 (function-item :tag "Gnus mail sending package"
2992 :format "%t\n"
2993 message-user-agent)
2994 (function :tag "Other"))
2995 :group 'mail)
2996
2997 (defun define-mail-user-agent (symbol composefunc sendfunc
2998 &optional abortfunc hookvar)
2999 "Define a symbol to identify a mail-sending package for `mail-user-agent'.
3000
3001 SYMBOL can be any Lisp symbol. Its function definition and/or
3002 value as a variable do not matter for this usage; we use only certain
3003 properties on its property list, to encode the rest of the arguments.
3004
3005 COMPOSEFUNC is program callable function that composes an outgoing
3006 mail message buffer. This function should set up the basics of the
3007 buffer without requiring user interaction. It should populate the
3008 standard mail headers, leaving the `to:' and `subject:' headers blank
3009 by default.
3010
3011 COMPOSEFUNC should accept several optional arguments--the same
3012 arguments that `compose-mail' takes. See that function's documentation.
3013
3014 SENDFUNC is the command a user would run to send the message.
3015
3016 Optional ABORTFUNC is the command a user would run to abort the
3017 message. For mail packages that don't have a separate abort function,
3018 this can be `kill-buffer' (the equivalent of omitting this argument).
3019
3020 Optional HOOKVAR is a hook variable that gets run before the message
3021 is actually sent. Callers that use the `mail-user-agent' may
3022 install a hook function temporarily on this hook variable.
3023 If HOOKVAR is nil, `mail-send-hook' is used.
3024
3025 The properties used on SYMBOL are `composefunc', `sendfunc',
3026 `abortfunc', and `hookvar'."
3027 (put symbol 'composefunc composefunc)
3028 (put symbol 'sendfunc sendfunc)
3029 (put symbol 'abortfunc (or abortfunc 'kill-buffer))
3030 (put symbol 'hookvar (or hookvar 'mail-send-hook)))
3031
3032 (define-mail-user-agent 'sendmail-user-agent
3033 'sendmail-user-agent-compose 'mail-send-and-exit)
3034
3035 (define-mail-user-agent 'message-user-agent
3036 'message-mail 'message-send-and-exit
3037 'message-kill-buffer 'message-send-hook)
3038
3039 (defun sendmail-user-agent-compose (&optional to subject other-headers continue
3040 switch-function yank-action
3041 send-actions)
3042 (if switch-function
3043 (let ((special-display-buffer-names nil)
3044 (special-display-regexps nil)
3045 (same-window-buffer-names nil)
3046 (same-window-regexps nil))
3047 (funcall switch-function "*mail*")))
3048 (let ((cc (cdr (assoc-ignore-case "cc" other-headers)))
3049 (in-reply-to (cdr (assoc-ignore-case "in-reply-to" other-headers))))
3050 (or (mail continue to subject in-reply-to cc yank-action send-actions)
3051 continue
3052 (error "Message aborted"))
3053 (save-excursion
3054 (goto-char (point-min))
3055 (search-forward mail-header-separator)
3056 (beginning-of-line)
3057 (while other-headers
3058 (if (not (member (car (car other-headers)) '("in-reply-to" "cc")))
3059 (insert (car (car other-headers)) ": "
3060 (cdr (car other-headers)) "\n"))
3061 (setq other-headers (cdr other-headers)))
3062 t)))
3063
3064 (define-mail-user-agent 'mh-e-user-agent
3065 'mh-smail-batch 'mh-send-letter 'mh-fully-kill-draft
3066 'mh-before-send-letter-hook)
3067
3068 (defun compose-mail (&optional to subject other-headers continue
3069 switch-function yank-action send-actions)
3070 "Start composing a mail message to send.
3071 This uses the user's chosen mail composition package
3072 as selected with the variable `mail-user-agent'.
3073 The optional arguments TO and SUBJECT specify recipients
3074 and the initial Subject field, respectively.
3075
3076 OTHER-HEADERS is an alist specifying additional
3077 header fields. Elements look like (HEADER . VALUE) where both
3078 HEADER and VALUE are strings.
3079
3080 CONTINUE, if non-nil, says to continue editing a message already
3081 being composed.
3082
3083 SWITCH-FUNCTION, if non-nil, is a function to use to
3084 switch to and display the buffer used for mail composition.
3085
3086 YANK-ACTION, if non-nil, is an action to perform, if and when necessary,
3087 to insert the raw text of the message being replied to.
3088 It has the form (FUNCTION . ARGS). The user agent will apply
3089 FUNCTION to ARGS, to insert the raw text of the original message.
3090 \(The user agent will also run `mail-citation-hook', *after* the
3091 original text has been inserted in this way.)
3092
3093 SEND-ACTIONS is a list of actions to call when the message is sent.
3094 Each action has the form (FUNCTION . ARGS)."
3095 (interactive
3096 (list nil nil nil current-prefix-arg))
3097 (let ((function (get mail-user-agent 'composefunc)))
3098 (funcall function to subject other-headers continue
3099 switch-function yank-action send-actions)))
3100
3101 (defun compose-mail-other-window (&optional to subject other-headers continue
3102 yank-action send-actions)
3103 "Like \\[compose-mail], but edit the outgoing message in another window."
3104 (interactive
3105 (list nil nil nil current-prefix-arg))
3106 (compose-mail to subject other-headers continue
3107 'switch-to-buffer-other-window yank-action send-actions))
3108
3109
3110 (defun compose-mail-other-frame (&optional to subject other-headers continue
3111 yank-action send-actions)
3112 "Like \\[compose-mail], but edit the outgoing message in another frame."
3113 (interactive
3114 (list nil nil nil current-prefix-arg))
3115 (compose-mail to subject other-headers continue
3116 'switch-to-buffer-other-frame yank-action send-actions))
3117
3118
3119 (defun set-variable (var val)
3120 "Set VARIABLE to VALUE. VALUE is a Lisp object.
3121 When using this interactively, supply a Lisp expression for VALUE.
3122 If you want VALUE to be a string, you must surround it with doublequotes.
3123
3124 If VARIABLE has a `variable-interactive' property, that is used as if
3125 it were the arg to `interactive' (which see) to interactively read the value."
3126 (interactive
3127 (let* ((var (read-variable "Set variable: "))
3128 ;; #### - yucky code replication here. This should use something
3129 ;; from help.el or hyper-apropos.el
3130 (minibuffer-help-form
3131 '(funcall myhelp))
3132 (myhelp
3133 #'(lambda ()
3134 (with-output-to-temp-buffer "*Help*"
3135 (prin1 var)
3136 (princ "\nDocumentation:\n")
3137 (princ (substring (documentation-property var 'variable-documentation)
3138 1))
3139 (if (boundp var)
3140 (let ((print-length 20))
3141 (princ "\n\nCurrent value: ")
3142 (prin1 (symbol-value var))))
3143 (save-excursion
3144 (set-buffer standard-output)
3145 (help-mode))
3146 nil))))
3147 (list var
3148 (let ((prop (get var 'variable-interactive)))
3149 (if prop
3150 ;; Use VAR's `variable-interactive' property
3151 ;; as an interactive spec for prompting.
3152 (call-interactively (list 'lambda '(arg)
3153 (list 'interactive prop)
3154 'arg))
3155 (eval-minibuffer (format "Set %s to value: " var)))))))
3156 (set var val))
3157
3158 ;; XEmacs
3159 (defun activate-region ()
3160 "Activate the region, if `zmacs-regions' is true.
3161 Setting `zmacs-regions' to true causes LISPM-style active regions to be used.
3162 This function has no effect if `zmacs-regions' is false."
3163 (interactive)
3164 (and zmacs-regions (zmacs-activate-region)))
3165
3166 ;; XEmacs
3167 (defsubst region-exists-p ()
3168 "Non-nil iff the region exists.
3169 If active regions are in use (i.e. `zmacs-regions' is true), this means that
3170 the region is active. Otherwise, this means that the user has pushed
3171 a mark in this buffer at some point in the past.
3172 The functions `region-beginning' and `region-end' can be used to find the
3173 limits of the region."
3174 (not (null (mark))))
3175
3176 ;; XEmacs
3177 (defun region-active-p ()
3178 "Non-nil iff the region is active.
3179 If `zmacs-regions' is true, this is equivalent to `region-exists-p'.
3180 Otherwise, this function always returns false."
3181 (and zmacs-regions zmacs-region-extent))
3182
3183 ;; A bunch of stuff was moved elsewhere:
3184 ;; completion-list-mode-map
3185 ;; completion-reference-buffer
3186 ;; completion-base-size
3187 ;; delete-completion-window
3188 ;; previous-completion
3189 ;; next-completion
3190 ;; choose-completion
3191 ;; choose-completion-delete-max-match
3192 ;; choose-completion-string
3193 ;; completion-list-mode
3194 ;; completion-fixup-function
3195 ;; completion-setup-function
3196 ;; switch-to-completions
3197 ;; event stuffs
3198 ;; keypad stuffs
3199
3200 ;; The rest of this file is not in Lisp in FSF
3201 (defun capitalize-region-or-word (arg)
3202 "Capitalize the selected region or the following word (or ARG words)."
3203 (interactive "p")
3204 (if (region-active-p)
3205 (capitalize-region (region-beginning) (region-end))
3206 (capitalize-word arg)))
3207
3208 (defun upcase-region-or-word (arg)
3209 "Upcase the selected region or the following word (or ARG words)."
3210 (interactive "p")
3211 (if (region-active-p)
3212 (upcase-region (region-beginning) (region-end))
3213 (upcase-word arg)))
3214
3215 (defun downcase-region-or-word (arg)
3216 "Downcase the selected region or the following word (or ARG words)."
3217 (interactive "p")
3218 (if (region-active-p)
3219 (downcase-region (region-beginning) (region-end))
3220 (downcase-word arg)))
3221
3222 ;;;
3223 ;;; Most of the zmacs code is now in elisp. The only thing left in C
3224 ;;; are the variables zmacs-regions, zmacs-region-active-p and
3225 ;;; zmacs-region-stays plus the function zmacs_update_region which
3226 ;;; calls the lisp level zmacs-update-region. It must remain since it
3227 ;;; must be called by core C code.
3228 ;;;
3229 ;;; Huh? Why couldn't "core C code" just use
3230 ;;; call0(Qzmacs_update_region)??? -hniksic
3231
3232 (defvar zmacs-activate-region-hook nil
3233 "Function or functions called when the region becomes active;
3234 see the variable `zmacs-regions'.")
3235
3236 (defvar zmacs-deactivate-region-hook nil
3237 "Function or functions called when the region becomes inactive;
3238 see the variable `zmacs-regions'.")
3239
3240 (defvar zmacs-update-region-hook nil
3241 "Function or functions called when the active region changes.
3242 This is called after each command that sets `zmacs-region-stays' to t.
3243 See the variable `zmacs-regions'.")
3244
3245 (defvar zmacs-region-extent nil
3246 "The extent of the zmacs region; don't use this.")
3247
3248 (defvar zmacs-region-rectangular-p nil
3249 "Whether the zmacs region is a rectangle; don't use this.")
3250
3251 (defun zmacs-make-extent-for-region (region)
3252 ;; Given a region, this makes an extent in the buffer which holds that
3253 ;; region, for highlighting purposes. If the region isn't associated
3254 ;; with a buffer, this does nothing.
3255 (let ((buffer nil)
3256 (valid (and (extentp zmacs-region-extent)
3257 (extent-object zmacs-region-extent)
3258 (buffer-live-p (extent-object zmacs-region-extent))))
3259 start end)
3260 (cond ((consp region)
3261 (setq start (min (car region) (cdr region))
3262 end (max (car region) (cdr region))
3263 valid (and valid
3264 (eq (marker-buffer (car region))
3265 (extent-object zmacs-region-extent)))
3266 buffer (marker-buffer (car region))))
3267 (t
3268 (signal 'error (list "Invalid region" region))))
3269
3270 (if valid
3271 nil
3272 ;; The condition case is in case any of the extents are dead or
3273 ;; otherwise incapacitated.
3274 (condition-case ()
3275 (if (listp zmacs-region-extent)
3276 (mapc 'delete-extent zmacs-region-extent)
3277 (delete-extent zmacs-region-extent))
3278 (error nil)))
3279
3280 (if valid
3281 (set-extent-endpoints zmacs-region-extent start end)
3282 (setq zmacs-region-extent (make-extent start end buffer))
3283
3284 ;; Make the extent be closed on the right, which means that if
3285 ;; characters are inserted exactly at the end of the extent, the
3286 ;; extent will grow to cover them. This is important for shell
3287 ;; buffers - suppose one makes a region, and one end is at point-max.
3288 ;; If the shell produces output, that marker will remain at point-max
3289 ;; (its position will increase). So it's important that the extent
3290 ;; exhibit the same behavior, lest the region covered by the extent
3291 ;; (the visual indication), and the region between point and mark
3292 ;; (the actual region value) become different!
3293 (set-extent-property zmacs-region-extent 'end-open nil)
3294
3295 ;; use same priority as mouse-highlighting so that conflicts between
3296 ;; the region extent and a mouse-highlighted extent are resolved by
3297 ;; the usual size-and-endpoint-comparison method.
3298 (set-extent-priority zmacs-region-extent mouse-highlight-priority)
3299 (set-extent-face zmacs-region-extent 'zmacs-region)
3300
3301 ;; #### It might be better to actually break
3302 ;; default-mouse-track-next-move-rect out of mouse.el so that we
3303 ;; can use its logic here.
3304 (cond
3305 (zmacs-region-rectangular-p
3306 (setq zmacs-region-extent (list zmacs-region-extent))
3307 (default-mouse-track-next-move-rect start end zmacs-region-extent)
3308 ))
3309
3310 zmacs-region-extent)))
3311
3312 (defun zmacs-region-buffer ()
3313 "Return the buffer containing the zmacs region, or nil."
3314 ;; #### this is horrible and kludgy! This stuff needs to be rethought.
3315 (and zmacs-regions zmacs-region-active-p
3316 (or (marker-buffer (mark-marker t))
3317 (and (extent-live-p zmacs-region-extent)
3318 (buffer-live-p (extent-object zmacs-region-extent))
3319 (extent-object zmacs-region-extent)))))
3320
3321 (defun zmacs-activate-region ()
3322 "Make the region between `point' and `mark' be active (highlighted),
3323 if `zmacs-regions' is true. Only a very small number of commands
3324 should ever do this. Calling this function will call the hook
3325 `zmacs-activate-region-hook', if the region was previously inactive.
3326 Calling this function ensures that the region stays active after the
3327 current command terminates, even if `zmacs-region-stays' is not set.
3328 Returns t if the region was activated (i.e. if `zmacs-regions' if t)."
3329 (if (not zmacs-regions)
3330 nil
3331 (setq zmacs-region-active-p t
3332 zmacs-region-stays t
3333 zmacs-region-rectangular-p (and (boundp 'mouse-track-rectangle-p)
3334 mouse-track-rectangle-p))
3335 (if (marker-buffer (mark-marker t))
3336 (zmacs-make-extent-for-region (cons (point-marker t) (mark-marker t))))
3337 (run-hooks 'zmacs-activate-region-hook)
3338 t))
3339
3340 (defun zmacs-deactivate-region ()
3341 "Make the region between `point' and `mark' no longer be active,
3342 if `zmacs-regions' is true. You shouldn't need to call this; the
3343 command loop calls it when appropriate. Calling this function will
3344 call the hook `zmacs-deactivate-region-hook', if the region was
3345 previously active. Returns t if the region had been active, nil
3346 otherwise."
3347 (if (not zmacs-region-active-p)
3348 nil
3349 (setq zmacs-region-active-p nil
3350 zmacs-region-stays nil
3351 zmacs-region-rectangular-p nil)
3352 (if zmacs-region-extent
3353 (let ((inhibit-quit t))
3354 (if (listp zmacs-region-extent)
3355 (mapc 'delete-extent zmacs-region-extent)
3356 (delete-extent zmacs-region-extent))
3357 (setq zmacs-region-extent nil)))
3358 (run-hooks 'zmacs-deactivate-region-hook)
3359 t))
3360
3361 (defun zmacs-update-region ()
3362 "Update the highlighted region between `point' and `mark'.
3363 You shouldn't need to call this; the command loop calls it
3364 when appropriate. Calling this function will call the hook
3365 `zmacs-update-region-hook', if the region is active."
3366 (when zmacs-region-active-p
3367 (when (marker-buffer (mark-marker t))
3368 (zmacs-make-extent-for-region (cons (point-marker t)
3369 (mark-marker t))))
3370 (run-hooks 'zmacs-update-region-hook)))
3371
3372 ;;;;;;
3373 ;;;;;; echo area stuff
3374 ;;;;;;
3375
3376 ;;; #### Should this be moved to a separate file, for clarity?
3377 ;;; -hniksic
3378
3379 ;;; The `message-stack' is an alist of labels with messages; the first
3380 ;;; message in this list is always in the echo area. A call to
3381 ;;; `display-message' inserts a label/message pair at the head of the
3382 ;;; list, and removes any other pairs with that label. Calling
3383 ;;; `clear-message' causes any pair with matching label to be removed,
3384 ;;; and this may cause the displayed message to change or vanish. If
3385 ;;; the label arg is nil, the entire message stack is cleared.
3386 ;;;
3387 ;;; Message/error filtering will be a little tricker to implement than
3388 ;;; logging, since messages can be built up incrementally
3389 ;;; using clear-message followed by repeated calls to append-message
3390 ;;; (this happens with error messages). For messages which aren't
3391 ;;; created this way, filtering could be implemented at display-message
3392 ;;; very easily.
3393 ;;;
3394 ;;; Bits of the logging code are borrowed from log-messages.el by
3395 ;;; Robert Potter (rpotter@grip.cis.upenn.edu).
3396
3397 ;; need this to terminate the currently-displayed message
3398 ;; ("Loading simple ...")
3399 (when (and
3400 (not (fboundp 'display-message))
3401 (not (featurep 'debug)))
3402 (send-string-to-terminal "\n"))
3403
3404 (defvar message-stack nil
3405 "An alist of label/string pairs representing active echo-area messages.
3406 The first element in the list is currently displayed in the echo area.
3407 Do not modify this directly--use the `message' or
3408 `display-message'/`clear-message' functions.")
3409
3410 (defvar remove-message-hook 'log-message
3411 "A function or list of functions to be called when a message is removed
3412 from the echo area at the bottom of the frame. The label of the removed
3413 message is passed as the first argument, and the text of the message
3414 as the second argument.")
3415
3416 (defcustom log-message-max-size 50000
3417 "Maximum size of the \" *Message-Log*\" buffer. See `log-message'."
3418 :type 'integer
3419 :group 'log-message)
3420 (make-compatible-variable 'message-log-max 'log-message-max-size)
3421
3422 ;; We used to reject quite a lot of stuff here, but it was a bad idea,
3423 ;; for two reasons:
3424 ;;
3425 ;; a) In most circumstances, you *want* to see the message in the log.
3426 ;; The explicitly non-loggable messages should be marked as such by
3427 ;; the issuer. Gratuitous non-displaying of random regexps made
3428 ;; debugging harder, too (because various reasonable debugging
3429 ;; messages would get eaten).
3430 ;;
3431 ;; b) It slowed things down. Yes, visibly.
3432 ;;
3433 ;; So, I left only a few of the really useless ones on this kill-list.
3434 ;;
3435 ;; --hniksic
3436 (defcustom log-message-ignore-regexps
3437 '(;; Note: adding entries to this list slows down messaging
3438 ;; significantly. Wherever possible, use message lables.
3439
3440 ;; Often-seen messages
3441 "\\`\\'" ; empty message
3442 "\\`\\(Beginning\\|End\\) of buffer\\'"
3443 ;;"^Quit$"
3444 ;; completions
3445 ;; Many packages print this -- impossible to categorize
3446 ;;"^Making completion list"
3447 ;; Gnus
3448 ;; "^No news is no news$"
3449 ;; "^No more\\( unread\\)? newsgroups$"
3450 ;; "^Opening [^ ]+ server\\.\\.\\."
3451 ;; "^[^:]+: Reading incoming mail"
3452 ;; "^Getting mail from "
3453 ;; "^\\(Generating Summary\\|Sorting threads\\|Making sparse threads\\|Scoring\\|Checking new news\\|Expiring articles\\|Sending\\)\\.\\.\\."
3454 ;; "^\\(Fetching headers for\\|Retrieving newsgroup\\|Reading active file\\)"
3455 ;; "^No more\\( unread\\)? articles"
3456 ;; "^Deleting article "
3457 ;; W3
3458 ;; "^Parsed [0-9]+ of [0-9]+ ([0-9]+%)"
3459 )
3460 "List of regular expressions matching messages which shouldn't be logged.
3461 See `log-message'.
3462
3463 Ideally, packages which generate messages which might need to be ignored
3464 should label them with 'progress, 'prompt, or 'no-log, so they can be
3465 filtered by the log-message-ignore-labels."
3466 :type '(repeat regexp)
3467 :group 'log-message)
3468
3469 (defcustom log-message-ignore-labels
3470 '(help-echo command progress prompt no-log garbage-collecting auto-saving)
3471 "List of symbols indicating labels of messages which shouldn't be logged.
3472 See `display-message' for some common labels. See also `log-message'."
3473 :type '(repeat (symbol :tag "Label"))
3474 :group 'log-message)
3475
3476 ;;Subsumed by view-lossage
3477 ;; Not really, I'm adding it back by popular demand. -slb
3478 (defun show-message-log ()
3479 "Show the \" *Message-Log*\" buffer, which contains old messages and errors."
3480 (interactive)
3481 (pop-to-buffer " *Message-Log*"))
3482
3483 (defvar log-message-filter-function 'log-message-filter
3484 "Value must be a function of two arguments: a symbol (label) and
3485 a string (message). It should return non-nil to indicate a message
3486 should be logged. Possible values include 'log-message-filter and
3487 'log-message-filter-errors-only.")
3488
3489 (defun log-message-filter (label message)
3490 "Default value of log-message-filter-function.
3491 Mesages whose text matches one of the log-message-ignore-regexps
3492 or whose label appears in log-message-ignore-labels are not saved."
3493 (let ((r log-message-ignore-regexps)
3494 (ok (not (memq label log-message-ignore-labels))))
3495 (while (and r ok)
3496 (if (save-match-data (string-match (car r) message))
3497 (setq ok nil))
3498 (setq r (cdr r)))
3499 ok))
3500
3501 (defun log-message-filter-errors-only (label message)
3502 "For use as the log-message-filter-function. Only logs error messages."
3503 (eq label 'error))
3504
3505 (defun log-message (label message)
3506 "Stuff a copy of the message into the \" *Message-Log*\" buffer,
3507 if it satisfies the log-message-filter-function.
3508
3509 For use on remove-message-hook."
3510 (if (and (not noninteractive)
3511 (funcall log-message-filter-function label message))
3512 (save-excursion
3513 (set-buffer (get-buffer-create " *Message-Log*"))
3514 (goto-char (point-max))
3515 ;; (insert (concat (upcase (symbol-name label)) ": " message "\n"))
3516 (insert message "\n")
3517 (if (> (point-max) (max log-message-max-size (point-min)))
3518 (progn
3519 ;; trim log to ~90% of max size
3520 (goto-char (max (- (point-max)
3521 (truncate (* 0.9 log-message-max-size)))
3522 (point-min)))
3523 (forward-line 1)
3524 (delete-region (point-min) (point)))))))
3525
3526 (defun message-displayed-p (&optional return-string frame)
3527 "Return a non-nil value if a message is presently displayed in the\n\
3528 minibuffer's echo area. If optional argument RETURN-STRING is non-nil,\n\
3529 return a string containing the message, otherwise just return t."
3530 ;; by definition, a message is displayed if the echo area buffer is
3531 ;; non-empty (see also echo_area_active()). It had better also
3532 ;; be the case that message-stack is nil exactly when the echo area
3533 ;; is non-empty.
3534 (let ((buffer (get-buffer " *Echo Area*")))
3535 (and (< (point-min buffer) (point-max buffer))
3536 (if return-string
3537 (buffer-substring nil nil buffer)
3538 t))))
3539
3540 ;;; Returns the string which remains in the echo area, or nil if none.
3541 ;;; If label is nil, the whole message stack is cleared.
3542 (defun clear-message (&optional label frame stdout-p no-restore)
3543 "Remove any message with the given LABEL from the message-stack,
3544 erasing it from the echo area if it's currently displayed there.
3545 If a message remains at the head of the message-stack and NO-RESTORE
3546 is nil, it will be displayed. The string which remains in the echo
3547 area will be returned, or nil if the message-stack is now empty.
3548 If LABEL is nil, the entire message-stack is cleared.
3549
3550 Unless you need the return value or you need to specify a label,
3551 you should just use (message nil)."
3552 (or frame (setq frame (selected-frame)))
3553 (let ((clear-stream (and message-stack (eq 'stream (frame-type frame)))))
3554 (remove-message label frame)
3555 (let ((buffer (get-buffer " *Echo Area*"))
3556 (inhibit-read-only t)
3557 (zmacs-region-stays zmacs-region-stays)) ; preserve from change
3558 (erase-buffer buffer))
3559 (if clear-stream
3560 (send-string-to-terminal ?\n stdout-p))
3561 (if no-restore
3562 nil ; just preparing to put another msg up
3563 (if message-stack
3564 (let ((oldmsg (cdr (car message-stack))))
3565 (raw-append-message oldmsg frame stdout-p)
3566 oldmsg)
3567 ;; ### should we (redisplay-echo-area) here? messes some things up.
3568 nil))))
3569
3570 (defun remove-message (&optional label frame)
3571 ;; If label is nil, we want to remove all matching messages.
3572 ;; Must reverse the stack first to log them in the right order.
3573 (let ((log nil))
3574 (while (and message-stack
3575 (or (null label) ; null label means clear whole stack
3576 (eq label (car (car message-stack)))))
3577 (setq log (cons (car message-stack) log))
3578 (setq message-stack (cdr message-stack)))
3579 (let ((s message-stack))
3580 (while (cdr s)
3581 (let ((msg (car (cdr s))))
3582 (if (eq label (car msg))
3583 (progn
3584 (setq log (cons msg log))
3585 (setcdr s (cdr (cdr s))))
3586 (setq s (cdr s))))))
3587 ;; (possibly) log each removed message
3588 (while log
3589 (condition-case e
3590 (run-hook-with-args 'remove-message-hook
3591 (car (car log)) (cdr (car log)))
3592 (error (setq remove-message-hook nil)
3593 (message "remove-message-hook error: %s" e)
3594 (sit-for 2)
3595 (let ((inhibit-read-only t))
3596 (erase-buffer (get-buffer " *Echo Area*")))
3597 (signal (car e) (cdr e))))
3598 (setq log (cdr log)))))
3599
3600 (defun append-message (label message &optional frame stdout-p)
3601 (or frame (setq frame (selected-frame)))
3602 ;; add a new entry to the message-stack, or modify an existing one
3603 (let ((top (car message-stack)))
3604 (if (eq label (car top))
3605 (setcdr top (concat (cdr top) message))
3606 (setq message-stack (cons (cons label message) message-stack))))
3607 (raw-append-message message frame stdout-p))
3608
3609 ;; really append the message to the echo area. no fiddling with message-stack.
3610 (defun raw-append-message (message &optional frame stdout-p)
3611 (if (eq message "") nil
3612 (let ((buffer (get-buffer " *Echo Area*"))
3613 (zmacs-region-stays zmacs-region-stays)) ; preserve from change
3614 (save-excursion
3615 (set-buffer buffer)
3616 (let ((inhibit-read-only t))
3617 (insert message)))
3618 ;; Conditionalizing on the device type in this way is not that clean,
3619 ;; but neither is having a device method, as I originally implemented
3620 ;; it: all non-stream devices behave in the same way. Perhaps
3621 ;; the cleanest way is to make the concept of a "redisplayable"
3622 ;; device, which stream devices are not. Look into this more if
3623 ;; we ever create another non-redisplayable device type (e.g.
3624 ;; processes? printers?).
3625
3626 ;; Don't redisplay the echo area if we are executing a macro.
3627 (if (not executing-kbd-macro)
3628 (if (eq 'stream (frame-type frame))
3629 (send-string-to-terminal message stdout-p)
3630 (redisplay-echo-area))))))
3631
3632 (defun display-message (label message &optional frame stdout-p)
3633 "Print a one-line message at the bottom of the frame. First argument
3634 LABEL is an identifier for this message. MESSAGE is the string to display.
3635 Use `clear-message' to remove a labelled message.
3636
3637 Here are some standard labels (those marked with `*' are not logged
3638 by default--see the `log-message-ignore-labels' variable):
3639 message default label used by the `message' function
3640 error default label used for reporting errors
3641 * progress progress indicators like \"Converting... 45%\"
3642 * prompt prompt-like messages like \"I-search: foo\"
3643 * no-log messages that should never be logged"
3644 (clear-message label frame stdout-p t)
3645 (append-message label message frame stdout-p))
3646
3647 (defun current-message (&optional frame)
3648 "Returns the current message in the echo area, or nil.
3649 The FRAME argument is currently unused."
3650 (cdr (car message-stack)))
3651
3652 ;;; may eventually be frame-dependent
3653 (defun current-message-label (&optional frame)
3654 (car (car message-stack)))
3655
3656 (defun message (fmt &rest args)
3657 "Print a one-line message at the bottom of the frame.
3658 The arguments are the same as to `format'.
3659
3660 If the only argument is nil, clear any existing message; let the
3661 minibuffer contents show."
3662 ;; questionable junk in the C code
3663 ;; (if (framep default-minibuffer-frame)
3664 ;; (make-frame-visible default-minibuffer-frame))
3665 (if (and (null fmt) (null args))
3666 (progn
3667 (clear-message nil)
3668 nil)
3669 (let ((str (apply 'format fmt args)))
3670 (display-message 'message str)
3671 str)))
3672
3673 ;;;;;;
3674 ;;;;;; warning stuff
3675 ;;;;;;
3676
3677 (defcustom log-warning-minimum-level 'info
3678 "Minimum level of warnings that should be logged.
3679 The warnings in levels below this are completely ignored, as if they never
3680 happened.
3681
3682 The recognized warning levels, in decreasing order of priority, are
3683 'emergency, 'alert, 'critical, 'error, 'warning, 'notice, 'info, and
3684 'debug.
3685
3686 See also `display-warning-minimum-level'.
3687
3688 You can also control which warnings are displayed on a class-by-class
3689 basis. See `display-warning-suppressed-classes' and
3690 `log-warning-suppressed-classes'."
3691 :type '(choice (const emergency) (const alert) (const critical)
3692 (const error) (const warning) (const notice)
3693 (const info) (const debug))
3694 :group 'warnings)
3695
3696 (defcustom display-warning-minimum-level 'info
3697 "Minimum level of warnings that should be displayed.
3698 The warnings in levels below this are completely ignored, as if they never
3699 happened.
3700
3701 The recognized warning levels, in decreasing order of priority, are
3702 'emergency, 'alert, 'critical, 'error, 'warning, 'notice, 'info, and
3703 'debug.
3704
3705 See also `log-warning-minimum-level'.
3706
3707 You can also control which warnings are displayed on a class-by-class
3708 basis. See `display-warning-suppressed-classes' and
3709 `log-warning-suppressed-classes'."
3710 :type '(choice (const emergency) (const alert) (const critical)
3711 (const error) (const warning) (const notice)
3712 (const info) (const debug))
3713 :group 'warnings)
3714
3715 (defvar log-warning-suppressed-classes nil
3716 "List of classes of warnings that shouldn't be logged or displayed.
3717 If any of the CLASS symbols associated with a warning is the same as
3718 any of the symbols listed here, the warning will be completely ignored,
3719 as it they never happened.
3720
3721 NOTE: In most circumstances, you should *not* set this variable.
3722 Set `display-warning-suppressed-classes' instead. That way the suppressed
3723 warnings are not displayed but are still unobtrusively logged.
3724
3725 See also `log-warning-minimum-level' and `display-warning-minimum-level'.")
3726
3727 (defcustom display-warning-suppressed-classes nil
3728 "List of classes of warnings that shouldn't be displayed.
3729 If any of the CLASS symbols associated with a warning is the same as
3730 any of the symbols listed here, the warning will not be displayed.
3731 The warning will still logged in the *Warnings* buffer (unless also
3732 contained in `log-warning-suppressed-classes'), but the buffer will
3733 not be automatically popped up.
3734
3735 See also `log-warning-minimum-level' and `display-warning-minimum-level'."
3736 :type '(repeat symbol)
3737 :group 'warnings)
3738
3739 (defvar warning-count 0
3740 "Count of the number of warning messages displayed so far.")
3741
3742 (defconst warning-level-alist '((emergency . 8)
3743 (alert . 7)
3744 (critical . 6)
3745 (error . 5)
3746 (warning . 4)
3747 (notice . 3)
3748 (info . 2)
3749 (debug . 1)))
3750
3751 (defun warning-level-p (level)
3752 "Non-nil if LEVEL specifies a warning level."
3753 (and (symbolp level) (assq level warning-level-alist)))
3754
3755 ;; If you're interested in rewriting this function, be aware that it
3756 ;; could be called at arbitrary points in a Lisp program (when a
3757 ;; built-in function wants to issue a warning, it will call out to
3758 ;; this function the next time some Lisp code is evaluated). Therefore,
3759 ;; this function *must* not permanently modify any global variables
3760 ;; (e.g. the current buffer) except those that specifically apply
3761 ;; to the warning system.
3762
3763 (defvar before-init-deferred-warnings nil)
3764
3765 (defun after-init-display-warnings ()
3766 "Display warnings deferred till after the init file is run.
3767 Warnings that occur before then are deferred so that warning
3768 suppression in the .emacs file will be honored."
3769 (while before-init-deferred-warnings
3770 (apply 'display-warning (car before-init-deferred-warnings))
3771 (setq before-init-deferred-warnings
3772 (cdr before-init-deferred-warnings))))
3773
3774 #-infodock (add-hook 'after-init-hook 'after-init-display-warnings)
3775
3776 (defun display-warning (class message &optional level)
3777 "Display a warning message.
3778 CLASS should be a symbol describing what sort of warning this is, such
3779 as `resource' or `key-mapping'. A list of such symbols is also
3780 accepted. (Individual classes can be suppressed; see
3781 `display-warning-suppressed-classes'.) Optional argument LEVEL can
3782 be used to specify a priority for the warning, other than default priority
3783 `warning'. (See `display-warning-minimum-level'). The message is
3784 inserted into the *Warnings* buffer, which is made visible at appropriate
3785 times."
3786 (or level (setq level 'warning))
3787 (or (listp class) (setq class (list class)))
3788 (check-argument-type 'warning-level-p level)
3789 (if (and (not (featurep 'infodock))
3790 (not init-file-loaded))
3791 (setq before-init-deferred-warnings
3792 (cons (list class message level) before-init-deferred-warnings))
3793 (catch 'ignored
3794 (let ((display-p t)
3795 (level-num (cdr (assq level warning-level-alist))))
3796 (if (< level-num (cdr (assq log-warning-minimum-level
3797 warning-level-alist)))
3798 (throw 'ignored nil))
3799 (if (intersection class log-warning-suppressed-classes)
3800 (throw 'ignored nil))
3801
3802 (if (< level-num (cdr (assq display-warning-minimum-level
3803 warning-level-alist)))
3804 (setq display-p nil))
3805 (if (and display-p
3806 (intersection class display-warning-suppressed-classes))
3807 (setq display-p nil))
3808 (save-excursion
3809 (let ((buffer (get-buffer-create "*Warnings*")))
3810 (when display-p
3811 ;; The C code looks at display-warning-tick to determine
3812 ;; when it should call `display-warning-buffer'. Change it
3813 ;; to get the C code's attention.
3814 (incf display-warning-tick))
3815 (set-buffer buffer)
3816 (goto-char (point-max))
3817 (setq warning-count (1+ warning-count))
3818 (princ (format "(%d) (%s/%s) "
3819 warning-count
3820 (mapconcat 'symbol-name class ",")
3821 level) buffer)
3822 (princ message buffer)
3823 (terpri buffer)
3824 (terpri buffer)))))))
3825
3826 (defun warn (&rest args)
3827 "Display a warning message.
3828 The message is constructed by passing all args to `format'. The message
3829 is placed in the *Warnings* buffer, which will be popped up at the next
3830 redisplay. The class of the warning is `warning'. See also
3831 `display-warning'."
3832 (display-warning 'warning (apply 'format args)))
3833
3834 (defvar warning-marker nil)
3835
3836 ;; When this function is called by the C code, all non-local exits are
3837 ;; trapped and C-g is inhibited; therefore, it would be a very, very
3838 ;; bad idea for this function to get into an infinite loop.
3839
3840 (defun display-warning-buffer ()
3841 "Make the buffer that contains the warnings be visible.
3842 The C code calls this periodically, right before redisplay."
3843 (let ((buffer (get-buffer-create "*Warnings*")))
3844 (when (or (not warning-marker)
3845 (not (eq (marker-buffer warning-marker) buffer)))
3846 (setq warning-marker (make-marker))
3847 (set-marker warning-marker 1 buffer))
3848 (set-window-start (display-buffer buffer) warning-marker)
3849 (set-marker warning-marker (point-max buffer) buffer)))
3850
3851 (defun emacs-name ()
3852 "Return the printable name of this instance of Emacs."
3853 (cond ((featurep 'infodock) "InfoDock")
3854 ((featurep 'xemacs) "XEmacs")
3855 (t "Emacs")))
3856
3857 ;;; simple.el ends here