comparison lisp/simple.el @ 1333:1b0339b048ce

[xemacs-hg @ 2003-03-02 09:38:37 by ben] To: xemacs-patches@xemacs.org PROBLEMS: Include nt/PROBLEMS and update. Add note about incremental linking badness. cmdloop.el, custom.el, dumped-lisp.el, files.el, keydefs.el, keymap.el, lisp-mode.el, make-docfile.el, replace.el, simple.el, subr.el, view-less.el, wid-edit.el: Lots of syncing with FSF 21.2. Use if-fboundp in wid-edit.el. New file newcomment.el from FSF. internals/internals.texi: Fix typo. (Build-Time Dependencies): New node. PROBLEMS: Delete. config.inc.samp, xemacs.mak: Eliminate HAVE_VC6, use SUPPORT_EDIT_AND_CONTINUE in its place. No incremental linking unless SUPPORT_EDIT_AND_CONTINUE, since it can cause nasty crashes in pdump. Put warnings about this in config.inc.samp. Report the full compile flags used for src and lib-src in the Installation output. alloc.c, lisp.h, ralloc.c, regex.c: Use ALLOCA() in regex.c to avoid excessive stack allocation. Also fix subtle problem with REL_ALLOC() -- any call to malloc() (direct or indirect) may relocate rel-alloced data, causing buffer text to shift. After any such call, regex must update all its pointers to such data. Add a system, when ERROR_CHECK_MALLOC, whereby regex.c indicates all the places it is prepared to handle malloc()/realloc()/free(), and any calls anywhere in XEmacs outside of this will trigger an abort. alloc.c, dialog-msw.c, eval.c, event-stream.c, general-slots.h, insdel.c, lisp.h, menubar-msw.c, menubar-x.c: Change *run_hook*_trapping_problems to take a warning class, not a string. Factor out code to issue warnings, add flag to call_trapping_problems() to postpone warning issue, and make *run_hook*_trapping_problems issue their own warnings tailored to the hook, postponed in the case of safe_run_hook_trapping_problems() so that the appropriate message can be issued about resetting to nil only when not `quit'. Make record_unwind_protect_restoring_int() non-static. dumper.c: Issue notes about incremental linking problems under Windows. fileio.c: Mule-ize encrypt/decrypt-string code. text.h: Spacing changes.
author ben
date Sun, 02 Mar 2003 09:38:54 +0000
parents 465bd3c7d932
children 01c57eb70ae9
comparison
equal deleted inserted replaced
1332:6aa23bb3da6b 1333:1b0339b048ce
23 ;; along with XEmacs; see the file COPYING. If not, write to the Free 23 ;; along with XEmacs; see the file COPYING. If not, write to the Free
24 ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 24 ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 ;; 02111-1307, USA. 25 ;; 02111-1307, USA.
26 26
27 ;;; Synched up with: FSF 19.34 [But not very closely]. 27 ;;; Synched up with: FSF 19.34 [But not very closely].
28 ;;; Occasional synching to FSF 21.2, as marked. Comment stuff also
29 ;;; synched, and in newcomment.el.
28 30
29 ;;; Commentary: 31 ;;; Commentary:
30 32
31 ;; This file is dumped with XEmacs. 33 ;; This file is dumped with XEmacs.
32 34
2679 (setq end2 (point)) 2681 (setq end2 (point))
2680 (transpose-subr-1) 2682 (transpose-subr-1)
2681 (setq arg (1+ arg))))))) 2683 (setq arg (1+ arg)))))))
2682 2684
2683 2685
2684 (defcustom comment-column 32
2685 "*Column to indent right-margin comments to.
2686 Setting this variable automatically makes it local to the current buffer.
2687 Each mode establishes a different default value for this variable; you
2688 can set the value for a particular mode using that mode's hook."
2689 :type 'integer
2690 :group 'fill-comments)
2691 (make-variable-buffer-local 'comment-column)
2692
2693 (defcustom comment-start nil
2694 "*String to insert to start a new comment, or nil if no comment syntax."
2695 :type '(choice (const :tag "None" nil)
2696 string)
2697 :group 'fill-comments)
2698
2699 (defcustom comment-start-skip nil
2700 "*Regexp to match the start of a comment plus everything up to its body.
2701 If there are any \\(...\\) pairs, the comment delimiter text is held to begin
2702 at the place matched by the close of the first pair."
2703 :type '(choice (const :tag "None" nil)
2704 regexp)
2705 :group 'fill-comments)
2706
2707 (defcustom comment-end ""
2708 "*String to insert to end a new comment.
2709 Should be an empty string if comments are terminated by end-of-line."
2710 :type 'string
2711 :group 'fill-comments)
2712
2713 (defconst comment-indent-hook nil
2714 "Obsolete variable for function to compute desired indentation for a comment.
2715 Use `comment-indent-function' instead.
2716 This function is called with no args with point at the beginning of
2717 the comment's starting delimiter.")
2718
2719 (defconst comment-indent-function
2720 ;; XEmacs - add at least one space after the end of the text on the
2721 ;; current line...
2722 (lambda ()
2723 (save-excursion
2724 (beginning-of-line)
2725 (let ((eol (save-excursion (end-of-line) (point))))
2726 (and comment-start-skip
2727 (re-search-forward comment-start-skip eol t)
2728 (setq eol (match-beginning 0)))
2729 (goto-char eol)
2730 (skip-chars-backward " \t")
2731 (max comment-column (1+ (current-column))))))
2732 "Function to compute desired indentation for a comment.
2733 This function is called with no args with point at the beginning of
2734 the comment's starting delimiter.")
2735
2736 (defcustom block-comment-start nil
2737 "*String to insert to start a new comment on a line by itself.
2738 If nil, use `comment-start' instead.
2739 Note that the regular expression `comment-start-skip' should skip this string
2740 as well as the `comment-start' string."
2741 :type '(choice (const :tag "Use `comment-start'" nil)
2742 string)
2743 :group 'fill-comments)
2744
2745 (defcustom block-comment-end nil
2746 "*String to insert to end a new comment on a line by itself.
2747 Should be an empty string if comments are terminated by end-of-line.
2748 If nil, use `comment-end' instead."
2749 :type '(choice (const :tag "Use `comment-end'" nil)
2750 string)
2751 :group 'fill-comments)
2752
2753 (defun indent-for-comment ()
2754 "Indent this line's comment to comment column, or insert an empty
2755 comment. Comments starting in column 0 are not moved."
2756 (interactive "*")
2757 (let* ((empty (save-excursion (beginning-of-line)
2758 (looking-at "[ \t]*$")))
2759 (starter (or (and empty block-comment-start) comment-start))
2760 (ender (or (and empty block-comment-end) comment-end)))
2761 (if (null starter)
2762 (error "No comment syntax defined")
2763 (let* ((eolpos (save-excursion (end-of-line) (point)))
2764 cpos indent begpos)
2765 (beginning-of-line)
2766 (if (re-search-forward comment-start-skip eolpos 'move)
2767 (progn (setq cpos (point-marker))
2768 ;; Find the start of the comment delimiter.
2769 ;; If there were paren-pairs in comment-start-skip,
2770 ;; position at the end of the first pair.
2771 (if (match-end 1)
2772 (goto-char (match-end 1))
2773 ;; If comment-start-skip matched a string with
2774 ;; internal whitespace (not final whitespace) then
2775 ;; the delimiter start at the end of that
2776 ;; whitespace. Otherwise, it starts at the
2777 ;; beginning of what was matched.
2778 (skip-syntax-backward " " (match-beginning 0))
2779 (skip-syntax-backward "^ " (match-beginning 0)))))
2780 (setq begpos (point))
2781 ;; Compute desired indent.
2782 ;; XEmacs change: Preserve indentation of comments starting in
2783 ;; column 0, as documented.
2784 (cond
2785 ((= (current-column) 0)
2786 (goto-char begpos))
2787 ((= (current-column)
2788 (setq indent (funcall comment-indent-function)))
2789 (goto-char begpos))
2790 (t
2791 ;; If that's different from current, change it.
2792 (skip-chars-backward " \t")
2793 (delete-region (point) begpos)
2794 (indent-to indent)))
2795 ;; An existing comment?
2796 (if cpos
2797 (progn (goto-char cpos)
2798 (set-marker cpos nil))
2799 ;; No, insert one.
2800 (insert starter)
2801 (save-excursion
2802 (insert ender)))))))
2803
2804 (defun set-comment-column (arg)
2805 "Set the comment column based on point.
2806 With no arg, set the comment column to the current column.
2807 With just minus as arg, kill any comment on this line.
2808 With any other arg, set comment column to indentation of the previous comment
2809 and then align or create a comment on this line at that column."
2810 (interactive "P")
2811 (if (eq arg '-)
2812 (kill-comment nil)
2813 (if arg
2814 (progn
2815 (save-excursion
2816 (beginning-of-line)
2817 (re-search-backward comment-start-skip)
2818 (beginning-of-line)
2819 (re-search-forward comment-start-skip)
2820 (goto-char (match-beginning 0))
2821 (setq comment-column (current-column))
2822 (lmessage 'command "Comment column set to %d" comment-column))
2823 (indent-for-comment))
2824 (setq comment-column (current-column))
2825 (lmessage 'command "Comment column set to %d" comment-column))))
2826
2827 (defun kill-comment (arg)
2828 "Kill the comment on this line, if any.
2829 With argument, kill comments on that many lines starting with this one."
2830 ;; this function loses in a lot of situations. it incorrectly recognizes
2831 ;; comment delimiters sometimes (ergo, inside a string), doesn't work
2832 ;; with multi-line comments, can kill extra whitespace if comment wasn't
2833 ;; through end-of-line, et cetera.
2834 (interactive "*P")
2835 (or comment-start-skip (error "No comment syntax defined"))
2836 (let ((count (prefix-numeric-value arg)) endc)
2837 (while (> count 0)
2838 (save-excursion
2839 (end-of-line)
2840 (setq endc (point))
2841 (beginning-of-line)
2842 (and (string< "" comment-end)
2843 (setq endc
2844 (progn
2845 (re-search-forward (regexp-quote comment-end) endc 'move)
2846 (skip-chars-forward " \t")
2847 (point))))
2848 (beginning-of-line)
2849 (if (re-search-forward comment-start-skip endc t)
2850 (progn
2851 (goto-char (match-beginning 0))
2852 (skip-chars-backward " \t")
2853 (kill-region (point) endc)
2854 ;; to catch comments a line beginnings
2855 (indent-according-to-mode))))
2856 (if arg (forward-line 1))
2857 (setq count (1- count)))))
2858
2859 ;; This variable: Synched up with 20.7.
2860 (defvar comment-padding 1
2861 "Number of spaces `comment-region' puts between comment chars and text.
2862
2863 Extra spacing between the comment characters and the comment text
2864 makes the comment easier to read. Default is 1. Nil means 0 and is
2865 more efficient.")
2866
2867 ;; This function: Synched up with 20.7.
2868 (defun comment-region (start end &optional arg)
2869 "Comment or uncomment each line in the region.
2870 With just C-u prefix arg, uncomment each line in region.
2871 Numeric prefix arg ARG means use ARG comment characters.
2872 If ARG is negative, delete that many comment characters instead.
2873 Comments are terminated on each line, even for syntax in which newline does
2874 not end the comment. Blank lines do not get comments."
2875 ;; if someone wants it to only put a comment-start at the beginning and
2876 ;; comment-end at the end then typing it, C-x C-x, closing it, C-x C-x
2877 ;; is easy enough. No option is made here for other than commenting
2878 ;; every line.
2879 (interactive "r\nP")
2880 (or comment-start (error "No comment syntax is defined"))
2881 (if (> start end) (let (mid) (setq mid start start end end mid)))
2882 (save-excursion
2883 (save-restriction
2884 (let ((cs comment-start) (ce comment-end)
2885 (cp (when comment-padding
2886 (make-string comment-padding ? )))
2887 numarg)
2888 (if (consp arg) (setq numarg t)
2889 (setq numarg (prefix-numeric-value arg))
2890 ;; For positive arg > 1, replicate the comment delims now,
2891 ;; then insert the replicated strings just once.
2892 (while (> numarg 1)
2893 (setq cs (concat cs comment-start)
2894 ce (concat ce comment-end))
2895 (setq numarg (1- numarg))))
2896 ;; Loop over all lines from START to END.
2897 (narrow-to-region start end)
2898 (goto-char start)
2899 ;; if user didn't specify how many comments to remove, be smart
2900 ;; and remove the minimal number that all lines have. that way,
2901 ;; comments in a region of Elisp code that gets commented out will
2902 ;; get put back correctly.
2903 (if (eq numarg t)
2904 (let ((min-comments 999999))
2905 (while (not (eobp))
2906 (let ((this-comments 0))
2907 (while (looking-at (regexp-quote cs))
2908 (incf this-comments)
2909 (forward-char (length cs)))
2910 (if (and (> this-comments 0) (< this-comments min-comments))
2911 (setq min-comments this-comments))
2912 (forward-line 1)))
2913 (if (< min-comments 999999)
2914 (setq numarg (- min-comments)))
2915 (goto-char start)))
2916 (if (or (eq numarg t) (< numarg 0))
2917 (while (not (eobp))
2918 (let (found-comment)
2919 ;; Delete comment start from beginning of line.
2920 (if (eq numarg t)
2921 (while (looking-at (regexp-quote cs))
2922 (setq found-comment t)
2923 (delete-char (length cs)))
2924 (let ((count numarg))
2925 (while (and (> 1 (setq count (1+ count)))
2926 (looking-at (regexp-quote cs)))
2927 (setq found-comment t)
2928 (delete-char (length cs)))))
2929 ;; Delete comment padding from beginning of line
2930 (when (and found-comment comment-padding
2931 (looking-at (regexp-quote cp)))
2932 (delete-char comment-padding))
2933 ;; Delete comment end from end of line.
2934 (if (string= "" ce)
2935 nil
2936 (if (eq numarg t)
2937 (progn
2938 (end-of-line)
2939 ;; This is questionable if comment-end ends in
2940 ;; whitespace. That is pretty brain-damaged,
2941 ;; though.
2942 (while (progn (skip-chars-backward " \t")
2943 (and (>= (- (point) (point-min))
2944 (length ce))
2945 (save-excursion
2946 (backward-char (length ce))
2947 (looking-at (regexp-quote ce)))))
2948 (delete-char (- (length ce)))))
2949 (let ((count numarg))
2950 (while (> 1 (setq count (1+ count)))
2951 (end-of-line)
2952 ;; This is questionable if comment-end ends in
2953 ;; whitespace. That is pretty brain-damaged though
2954 (skip-chars-backward " \t")
2955 (if (>= (- (point) (point-min)) (length ce))
2956 (save-excursion
2957 (backward-char (length ce))
2958 (if (looking-at (regexp-quote ce))
2959 (delete-char (length ce)))))))))
2960 (forward-line 1)))
2961
2962 (when comment-padding
2963 (setq cs (concat cs cp)))
2964 (while (not (eobp))
2965 ;; Insert at beginning and at end.
2966 (if (looking-at "[ \t]*$") ()
2967 (insert cs)
2968 (if (string= "" ce) ()
2969 (end-of-line)
2970 (insert ce)))
2971 (search-forward "\n" nil 'move)))))))
2972
2973 ;; XEmacs 2686 ;; XEmacs
2974 (defun prefix-region (prefix) 2687 (defun prefix-region (prefix)
2975 "Add a prefix string to each line between mark and point." 2688 "Add a prefix string to each line between mark and point."
2976 (interactive "sPrefix string: ") 2689 (interactive "sPrefix string: ")
2977 (if prefix 2690 (if prefix
3332 ;; Disallow missing argument; it's probably a typo for C-x C-f. 3045 ;; Disallow missing argument; it's probably a typo for C-x C-f.
3333 (t 3046 (t
3334 (error "set-fill-column requires an explicit argument"))) 3047 (error "set-fill-column requires an explicit argument")))
3335 (lmessage 'command "fill-column set to %d" fill-column)) 3048 (lmessage 'command "fill-column set to %d" fill-column))
3336 3049
3337 (defcustom comment-multi-line t ; XEmacs - this works well with adaptive fill 3050
3338 "*Non-nil means \\[indent-new-comment-line] should continue same comment 3051 ;; BEGIN SYNCHED WITH FSF 21.2.
3339 on new line, with no new terminator or starter. 3052
3340 This is obsolete because you might as well use \\[newline-and-indent]."
3341 :type 'boolean
3342 :group 'fill-comments)
3343
3344 (defun indent-new-comment-line (&optional soft)
3345 "Break line at point and indent, continuing comment if within one.
3346 This indents the body of the continued comment
3347 under the previous comment line.
3348
3349 This command is intended for styles where you write a comment per line,
3350 starting a new comment (and terminating it if necessary) on each line.
3351 If you want to continue one comment across several lines, use \\[newline-and-indent].
3352
3353 If a fill column is specified, it overrides the use of the comment column
3354 or comment indentation.
3355
3356 The inserted newline is marked hard if `use-hard-newlines' is true,
3357 unless optional argument SOFT is non-nil."
3358 (interactive)
3359 (let (comcol comstart)
3360 (skip-chars-backward " \t")
3361 (if (featurep 'mule)
3362 (declare-fboundp (kinsoku-process)))
3363 (delete-region (point)
3364 (progn (skip-chars-forward " \t")
3365 (point)))
3366 (if soft (insert ?\n) (newline 1))
3367 (if fill-prefix
3368 (progn
3369 (indent-to-left-margin)
3370 (insert fill-prefix))
3371 ;; #### - Eric Eide reverts to v18 semantics for this function in
3372 ;; fa-extras, which I'm not gonna do. His changes are to (1) execute
3373 ;; the save-excursion below unconditionally, and (2) uncomment the check
3374 ;; for (not comment-multi-line) further below. --Stig
3375 ;;#### jhod: probably need to fix this for kinsoku processing
3376 (if (not comment-multi-line)
3377 (save-excursion
3378 (if (and comment-start-skip
3379 (let ((opoint (point)))
3380 (forward-line -1)
3381 (re-search-forward comment-start-skip opoint t)))
3382 ;; The old line is a comment.
3383 ;; Set WIN to the pos of the comment-start.
3384 ;; But if the comment is empty, look at preceding lines
3385 ;; to find one that has a nonempty comment.
3386
3387 ;; If comment-start-skip contains a \(...\) pair,
3388 ;; the real comment delimiter starts at the end of that pair.
3389 (let ((win (or (match-end 1) (match-beginning 0))))
3390 (while (and (eolp) (not (bobp))
3391 (let (opoint)
3392 (beginning-of-line)
3393 (setq opoint (point))
3394 (forward-line -1)
3395 (re-search-forward comment-start-skip opoint t)))
3396 (setq win (or (match-end 1) (match-beginning 0))))
3397 ;; Indent this line like what we found.
3398 (goto-char win)
3399 (setq comcol (current-column))
3400 (setq comstart
3401 (buffer-substring (point) (match-end 0)))))))
3402 (if (and comcol (not fill-prefix)) ; XEmacs - (ENE) from fa-extras.
3403 (let ((comment-column comcol)
3404 (comment-start comstart)
3405 (block-comment-start comstart)
3406 (comment-end comment-end))
3407 (and comment-end (not (equal comment-end ""))
3408 ; (if (not comment-multi-line)
3409 (progn
3410 (backward-char 1)
3411 (insert comment-end)
3412 (forward-char 1))
3413 ; (setq comment-column (+ comment-column (length comment-start))
3414 ; comment-start "")
3415 ; )
3416 )
3417 (if (not (eolp))
3418 (setq comment-end ""))
3419 (insert ?\n)
3420 (backward-char 1)
3421 (indent-for-comment)
3422 (save-excursion
3423 ;; Make sure we delete the newline inserted above.
3424 (end-of-line)
3425 (delete-char 1)))
3426 (indent-according-to-mode)))))
3427
3428
3429 (defun set-selective-display (arg) 3053 (defun set-selective-display (arg)
3430 "Set `selective-display' to ARG; clear it if no arg. 3054 "Set `selective-display' to ARG; clear it if no arg.
3431 When the value of `selective-display' is a number > 0, 3055 When the value of `selective-display' is a number > 0,
3432 lines whose indentation is >= that value are not displayed. 3056 lines whose indentation is >= that value are not displayed.
3433 The variable `selective-display' has a separate value for each buffer." 3057 The variable `selective-display' has a separate value for each buffer."
3469 )))) 3093 ))))
3470 (setq selective-display nil)) 3094 (setq selective-display nil))
3471 3095
3472 (add-hook 'change-major-mode-hook 'nuke-selective-display) 3096 (add-hook 'change-major-mode-hook 'nuke-selective-display)
3473 3097
3474 (defconst overwrite-mode-textual " Ovwrt" 3098 (defvar overwrite-mode-textual " Ovwrt"
3475 "The string displayed in the mode line when in overwrite mode.") 3099 "The string displayed in the mode line when in overwrite mode.")
3476 (defconst overwrite-mode-binary " Bin Ovwrt" 3100 (defvar overwrite-mode-binary " Bin Ovwrt"
3477 "The string displayed in the mode line when in binary overwrite mode.") 3101 "The string displayed in the mode line when in binary overwrite mode.")
3478 3102
3479 (defun overwrite-mode (arg) 3103 (defun overwrite-mode (arg)
3480 "Toggle overwrite mode. 3104 "Toggle overwrite mode.
3481 With arg, enable overwrite mode if arg is positive, else disable. 3105 With arg, turn overwrite mode on iff arg is positive.
3482 In overwrite mode, printing characters typed in replace existing text 3106 In overwrite mode, printing characters typed in replace existing text
3483 on a one-for-one basis, rather than pushing it to the right. At the 3107 on a one-for-one basis, rather than pushing it to the right. At the
3484 end of a line, such characters extend the line. Before a tab, 3108 end of a line, such characters extend the line. Before a tab,
3485 such characters insert until the tab is filled in. 3109 such characters insert until the tab is filled in.
3486 \\[quoted-insert] still inserts characters in overwrite mode; this 3110 \\[quoted-insert] still inserts characters in overwrite mode; this
3492 'overwrite-mode-textual)) 3116 'overwrite-mode-textual))
3493 (redraw-modeline)) 3117 (redraw-modeline))
3494 3118
3495 (defun binary-overwrite-mode (arg) 3119 (defun binary-overwrite-mode (arg)
3496 "Toggle binary overwrite mode. 3120 "Toggle binary overwrite mode.
3497 With arg, enable binary overwrite mode if arg is positive, else disable. 3121 With arg, turn binary overwrite mode on iff arg is positive.
3498 In binary overwrite mode, printing characters typed in replace 3122 In binary overwrite mode, printing characters typed in replace
3499 existing text. Newlines are not treated specially, so typing at the 3123 existing text. Newlines are not treated specially, so typing at the
3500 end of a line joins the line to the next, with the typed character 3124 end of a line joins the line to the next, with the typed character
3501 between them. Typing before a tab character simply replaces the tab 3125 between them. Typing before a tab character simply replaces the tab
3502 with the character typed. 3126 with the character typed.
3511 (if (if (null arg) 3135 (if (if (null arg)
3512 (not (eq overwrite-mode 'overwrite-mode-binary)) 3136 (not (eq overwrite-mode 'overwrite-mode-binary))
3513 (> (prefix-numeric-value arg) 0)) 3137 (> (prefix-numeric-value arg) 0))
3514 'overwrite-mode-binary)) 3138 'overwrite-mode-binary))
3515 (redraw-modeline)) 3139 (redraw-modeline))
3140
3141 ;; END SYNCHED WITH FSF 21.2.
3142
3516 3143
3517 (defcustom line-number-mode t 3144 (defcustom line-number-mode t
3518 "*Non-nil means display line number in modeline." 3145 "*Non-nil means display line number in modeline."
3519 :type 'boolean 3146 :type 'boolean
3520 :group 'editing-basics) 3147 :group 'editing-basics)
3670 3297
3671 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 3298 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3672 ;; mail composition code ;; 3299 ;; mail composition code ;;
3673 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 3300 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3674 3301
3302 ;; BEGIN SYNCHED WITH FSF 21.2.
3303
3675 (defcustom mail-user-agent 'sendmail-user-agent 3304 (defcustom mail-user-agent 'sendmail-user-agent
3676 "*Your preference for a mail composition package. 3305 "*Your preference for a mail composition package.
3677 Various Emacs Lisp packages (e.g. reporter) require you to compose an 3306 Various Emacs Lisp packages (e.g. Reporter) require you to compose an
3678 outgoing email message. This variable lets you specify which 3307 outgoing email message. This variable lets you specify which
3679 mail-sending package you prefer. 3308 mail-sending package you prefer.
3680 3309
3681 Valid values include: 3310 Valid values include:
3682 3311
3683 sendmail-user-agent -- use the default Emacs Mail package 3312 `sendmail-user-agent' -- use the default Emacs Mail package.
3684 mh-e-user-agent -- use the Emacs interface to the MH mail system 3313 See Info node `(emacs)Sending Mail'.
3685 message-user-agent -- use the GNUS mail sending package 3314 `mh-e-user-agent' -- use the Emacs interface to the MH mail system.
3315 See Info node `(mh-e)'.
3316 `message-user-agent' -- use the Gnus Message package.
3317 See Info node `(message)'.
3318 `gnus-user-agent' -- like `message-user-agent', but with Gnus
3319 paraphernalia, particularly the Gcc: header for
3320 archiving.
3686 3321
3687 Additional valid symbols may be available; check with the author of 3322 Additional valid symbols may be available; check with the author of
3688 your package for details." 3323 your package for details. The function should return non-nil if it
3324 succeeds.
3325
3326 See also `read-mail-command' concerning reading mail."
3689 :type '(radio (function-item :tag "Default Emacs mail" 3327 :type '(radio (function-item :tag "Default Emacs mail"
3690 :format "%t\n" 3328 :format "%t\n"
3691 sendmail-user-agent) 3329 sendmail-user-agent)
3692 (function-item :tag "Gnus mail sending package" 3330 (function-item :tag "Emacs interface to MH"
3331 :format "%t\n"
3332 mh-e-user-agent)
3333 (function-item :tag "Gnus Message package"
3693 :format "%t\n" 3334 :format "%t\n"
3694 message-user-agent) 3335 message-user-agent)
3336 (function-item :tag "Gnus Message with full Gnus features"
3337 :format "%t\n"
3338 gnus-user-agent)
3695 (function :tag "Other")) 3339 (function :tag "Other"))
3696 :group 'mail) 3340 :group 'mail)
3697 3341
3698 (defun define-mail-user-agent (symbol composefunc sendfunc 3342 (defun define-mail-user-agent (symbol composefunc sendfunc
3699 &optional abortfunc hookvar) 3343 &optional abortfunc hookvar)
3734 'sendmail-user-agent-compose 'mail-send-and-exit) 3378 'sendmail-user-agent-compose 'mail-send-and-exit)
3735 3379
3736 (define-mail-user-agent 'message-user-agent 3380 (define-mail-user-agent 'message-user-agent
3737 'message-mail 'message-send-and-exit 3381 'message-mail 'message-send-and-exit
3738 'message-kill-buffer 'message-send-hook) 3382 'message-kill-buffer 'message-send-hook)
3383
3384 (defun rfc822-goto-eoh ()
3385 ;; Go to header delimiter line in a mail message, following RFC822 rules
3386 (goto-char (point-min))
3387 (while (looking-at "^[^: \n]+:\\|^[ \t]")
3388 (forward-line 1))
3389 (point))
3739 3390
3740 (defun sendmail-user-agent-compose (&optional to subject other-headers continue 3391 (defun sendmail-user-agent-compose (&optional to subject other-headers continue
3741 switch-function yank-action 3392 switch-function yank-action
3742 send-actions) 3393 send-actions)
3743 (if switch-function 3394 (if switch-function
3745 (special-display-regexps nil) 3396 (special-display-regexps nil)
3746 (same-window-buffer-names nil) 3397 (same-window-buffer-names nil)
3747 (same-window-regexps nil)) 3398 (same-window-regexps nil))
3748 (funcall switch-function "*mail*"))) 3399 (funcall switch-function "*mail*")))
3749 (let ((cc (cdr (assoc-ignore-case "cc" other-headers))) 3400 (let ((cc (cdr (assoc-ignore-case "cc" other-headers)))
3750 (in-reply-to (cdr (assoc-ignore-case "in-reply-to" other-headers)))) 3401 (in-reply-to (cdr (assoc-ignore-case "in-reply-to" other-headers)))
3402 (body (cdr (assoc-ignore-case "body" other-headers))))
3751 (or (declare-fboundp 3403 (or (declare-fboundp
3752 (mail continue to subject in-reply-to cc yank-action send-actions)) 3404 (mail continue to subject in-reply-to cc yank-action send-actions))
3753 continue 3405 continue
3754 (error "Message aborted")) 3406 (error "Message aborted"))
3755 (save-excursion 3407 (save-excursion
3756 (goto-char (point-min)) 3408 (rfc822-goto-eoh)
3757 (search-forward (declare-boundp mail-header-separator))
3758 (beginning-of-line)
3759 (while other-headers 3409 (while other-headers
3760 (if (not (member (car (car other-headers)) '("in-reply-to" "cc"))) 3410 (unless (member* (car (car other-headers))
3411 '("in-reply-to" "cc" "body")
3412 :test 'equalp)
3761 (insert (car (car other-headers)) ": " 3413 (insert (car (car other-headers)) ": "
3762 (cdr (car other-headers)) "\n")) 3414 (cdr (car other-headers)) "\n"))
3763 (setq other-headers (cdr other-headers))) 3415 (setq other-headers (cdr other-headers)))
3416 (when body
3417 (forward-line 1)
3418 (insert body))
3764 t))) 3419 t)))
3765 3420
3766 (define-mail-user-agent 'mh-e-user-agent 3421 (define-mail-user-agent 'mh-e-user-agent
3767 'mh-user-agent-compose 'mh-send-letter 'mh-fully-kill-draft 3422 'mh-smail-batch 'mh-send-letter 'mh-fully-kill-draft
3768 'mh-before-send-letter-hook) 3423 'mh-before-send-letter-hook)
3769 3424
3770 (defun compose-mail (&optional to subject other-headers continue 3425 (defun compose-mail (&optional to subject other-headers continue
3771 switch-function yank-action send-actions) 3426 switch-function yank-action send-actions)
3772 "Start composing a mail message to send. 3427 "Start composing a mail message to send.
3820 3475
3821 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 3476 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3822 ;; set variable ;; 3477 ;; set variable ;;
3823 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 3478 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3824 3479
3480 (defvar set-variable-value-history nil
3481 "History of values entered with `set-variable'.")
3482
3825 (defun set-variable (var val) 3483 (defun set-variable (var val)
3826 "Set VARIABLE to VALUE. VALUE is a Lisp object. 3484 "Set VARIABLE to VALUE. VALUE is a Lisp object.
3827 When using this interactively, supply a Lisp expression for VALUE. 3485 When using this interactively, enter a Lisp object for VALUE.
3828 If you want VALUE to be a string, you must surround it with doublequotes. 3486 If you want VALUE to be a string, you must surround it with doublequotes.
3487 VALUE is used literally, not evaluated.
3488
3829 If VARIABLE is a specifier, VALUE is added to it as an instantiator in 3489 If VARIABLE is a specifier, VALUE is added to it as an instantiator in
3830 the 'global locale with nil tag set (see `set-specifier'). 3490 the 'global locale with nil tag set (see `set-specifier').
3831 3491
3832 If VARIABLE has a `variable-interactive' property, that is used as if 3492 If VARIABLE has a `variable-interactive' property, that is used as if
3833 it were the arg to `interactive' (which see) to interactively read the value." 3493 it were the arg to `interactive' (which see) to interactively read VALUE.
3494
3495 If VARIABLE has been defined with `defcustom', then the type information
3496 in the definition is used to check that VALUE is valid."
3834 (interactive 3497 (interactive
3835 (let* ((var (read-variable "Set variable: ")) 3498 (let* ((default-var (variable-at-point))
3836 ;; #### - yucky code replication here. This should use something 3499 (var (if (symbolp default-var)
3837 ;; from help.el or hyper-apropos.el 3500 (read-variable (format "Set variable (default %s): " default-var)
3838 (myhelp 3501 default-var)
3839 #'(lambda () 3502 (read-variable "Set variable: ")))
3840 (with-output-to-temp-buffer "*Help*" 3503 (minibuffer-help-form '(describe-variable var))
3841 (prin1 var) 3504 (prop (get var 'variable-interactive))
3842 (princ "\nDocumentation:\n") 3505 (prompt (format "Set %s to value: " var))
3843 (princ (substring (documentation-property var 'variable-documentation) 3506 (val (if prop
3844 1)) 3507 ;; Use VAR's `variable-interactive' property
3845 (if (boundp var) 3508 ;; as an interactive spec for prompting.
3846 (let ((print-length 20)) 3509 (call-interactively `(lambda (arg)
3847 (princ "\n\nCurrent value: ") 3510 (interactive ,prop)
3848 (prin1 (symbol-value var)))) 3511 arg))
3849 (save-excursion 3512 (read
3850 (set-buffer standard-output) 3513 (read-string prompt nil
3851 (help-mode)) 3514 'set-variable-value-history)))))
3852 nil))) 3515 (list var val)))
3853 (minibuffer-help-form 3516
3854 '(funcall myhelp))) 3517 (let ((type (get var 'custom-type)))
3855 (list var 3518 (when type
3856 (let ((prop (get var 'variable-interactive))) 3519 ;; Match with custom type.
3857 (if prop 3520 (require 'cus-edit)
3858 ;; Use VAR's `variable-interactive' property 3521 (setq type (widget-convert type))
3859 ;; as an interactive spec for prompting. 3522 (unless (widget-apply type :match val)
3860 (call-interactively (list 'lambda '(arg) 3523 (error "Value `%S' does not match type %S of %S"
3861 (list 'interactive prop) 3524 val (car type) var))))
3862 'arg))
3863 (eval-minibuffer (format "Set %s to value: " var)))))))
3864 (if (and (boundp var) (specifierp (symbol-value var))) 3525 (if (and (boundp var) (specifierp (symbol-value var)))
3865 (set-specifier (symbol-value var) val) 3526 (set-specifier (symbol-value var) val)
3866 (set var val))) 3527 (set var val))
3528
3529 ;; Force a thorough redisplay for the case that the variable
3530 ;; has an effect on the display, like `tab-width' has.
3531 (force-mode-line-update))
3532
3533
3534
3535 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3536 ;; forking a twin copy of a buffer ;;
3537 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3538
3539 (defvar clone-buffer-hook nil
3540 "Normal hook to run in the new buffer at the end of `clone-buffer'.")
3541
3542 (defun clone-process (process &optional newname)
3543 "Create a twin copy of PROCESS.
3544 If NEWNAME is nil, it defaults to PROCESS' name;
3545 NEWNAME is modified by adding or incrementing <N> at the end as necessary.
3546 If PROCESS is associated with a buffer, the new process will be associated
3547 with the current buffer instead.
3548 Returns nil if PROCESS has already terminated."
3549 (setq newname (or newname (process-name process)))
3550 (if (string-match "<[0-9]+>\\'" newname)
3551 (setq newname (substring newname 0 (match-beginning 0))))
3552 (when (memq (process-status process) '(run stop open))
3553 (let* ((process-connection-type (process-tty-name process))
3554 (old-kwoq (process-kill-without-query process nil))
3555 (new-process
3556 (if (memq (process-status process) '(open))
3557 (apply 'open-network-stream newname
3558 (if (process-buffer process) (current-buffer))
3559 ;; FSF: (process-contact process)
3560 (process-command process))
3561 (apply 'start-process newname
3562 (if (process-buffer process) (current-buffer))
3563 (process-command process)))))
3564 (process-kill-without-query new-process old-kwoq)
3565 (process-kill-without-query process old-kwoq)
3566 ;; FSF 21.2:
3567 ; (set-process-inherit-coding-system-flag
3568 ; new-process (process-inherit-coding-system-flag process))
3569 (set-process-filter new-process (process-filter process))
3570 (set-process-sentinel new-process (process-sentinel process))
3571 new-process)))
3572
3573 ;; things to maybe add (currently partly covered by `funcall mode':
3574 ;; - syntax-table
3575 ;; - overlays
3576 (defun clone-buffer (&optional newname display-flag)
3577 "Create a twin copy of the current buffer.
3578 If NEWNAME is nil, it defaults to the current buffer's name;
3579 NEWNAME is modified by adding or incrementing <N> at the end as necessary.
3580
3581 If DISPLAY-FLAG is non-nil, the new buffer is shown with `pop-to-buffer'.
3582 This runs the normal hook `clone-buffer-hook' in the new buffer
3583 after it has been set up properly in other respects."
3584 (interactive (list (if current-prefix-arg (read-string "Name: "))
3585 t))
3586 (if buffer-file-name
3587 (error "Cannot clone a file-visiting buffer"))
3588 (if (get major-mode 'no-clone)
3589 (error "Cannot clone a buffer in %s mode" mode-name))
3590 (setq newname (or newname (buffer-name)))
3591 (if (string-match "<[0-9]+>\\'" newname)
3592 (setq newname (substring newname 0 (match-beginning 0))))
3593 (let ((buf (current-buffer))
3594 (ptmin (point-min))
3595 (ptmax (point-max))
3596 (pt (point))
3597 (mk (mark t)) ;(if mark-active (mark t)))
3598 (modified (buffer-modified-p))
3599 (mode major-mode)
3600 (lvars (buffer-local-variables))
3601 (process (get-buffer-process (current-buffer)))
3602 (new (generate-new-buffer (or newname (buffer-name)))))
3603 (save-restriction
3604 (widen)
3605 (with-current-buffer new
3606 (insert-buffer-substring buf)))
3607 (with-current-buffer new
3608 (narrow-to-region ptmin ptmax)
3609 (goto-char pt)
3610 (if mk (set-mark mk))
3611 (set-buffer-modified-p modified)
3612
3613 ;; Clone the old buffer's process, if any.
3614 (when process (clone-process process))
3615
3616 ;; Now set up the major mode.
3617 (funcall mode)
3618
3619 ;; Set up other local variables.
3620 (mapcar (lambda (v)
3621 (condition-case () ;in case var is read-only
3622 (if (symbolp v)
3623 (makunbound v)
3624 (set (make-local-variable (car v)) (cdr v)))
3625 (error nil)))
3626 lvars)
3627
3628 ;; Run any hooks (typically set up by the major mode
3629 ;; for cloning to work properly).
3630 (run-hooks 'clone-buffer-hook))
3631 (if display-flag (pop-to-buffer new))
3632 new))
3633
3634
3635 (defun clone-indirect-buffer (newname display-flag &optional norecord)
3636 "Create an indirect buffer that is a twin copy of the current buffer.
3637
3638 Give the indirect buffer name NEWNAME. Interactively, read NEW-NAME
3639 from the minibuffer when invoked with a prefix arg. If NEWNAME is nil
3640 or if not called with a prefix arg, NEWNAME defaults to the current
3641 buffer's name. The name is modified by adding a `<N>' suffix to it
3642 or by incrementing the N in an existing suffix.
3643
3644 DISPLAY-FLAG non-nil means show the new buffer with `pop-to-buffer'.
3645 This is always done when called interactively.
3646
3647 Optional last arg NORECORD non-nil means do not put this buffer at the
3648 front of the list of recently selected ones."
3649 (interactive (list (if current-prefix-arg
3650 (read-string "BName of indirect buffer: "))
3651 t))
3652 (setq newname (or newname (buffer-name)))
3653 (if (string-match "<[0-9]+>\\'" newname)
3654 (setq newname (substring newname 0 (match-beginning 0))))
3655 (let* ((name (generate-new-buffer-name newname))
3656 (buffer (make-indirect-buffer (current-buffer) name t)))
3657 (when display-flag
3658 (pop-to-buffer buffer norecord))
3659 buffer))
3660
3661
3662 (defun clone-indirect-buffer-other-window (buffer &optional norecord)
3663 "Create an indirect buffer that is a twin copy of BUFFER.
3664 Select the new buffer in another window.
3665 Optional second arg NORECORD non-nil means do not put this buffer at
3666 the front of the list of recently selected ones."
3667 (interactive "bClone buffer in other window: ")
3668 (let ((pop-up-windows t))
3669 (set-buffer buffer)
3670 (clone-indirect-buffer nil t norecord)))
3671
3672 ;; END SYNCHED WITH FSF 21.2.
3867 3673
3868 3674
3869 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 3675 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3870 ;; case changing code ;; 3676 ;; case changing code ;;
3871 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 3677 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;