Mercurial > emacs
diff lisp/progmodes/cc-cmds.el @ 36920:32a4317c6aa5
Update to version 5.28.
author | Gerd Moellmann <gerd@gnu.org> |
---|---|
date | Wed, 21 Mar 2001 12:58:33 +0000 |
parents | dd613770eb0f |
children | 22964e38f4c2 |
line wrap: on
line diff
--- a/lisp/progmodes/cc-cmds.el Wed Mar 21 12:56:09 2001 +0000 +++ b/lisp/progmodes/cc-cmds.el Wed Mar 21 12:58:33 2001 +0000 @@ -1,6 +1,6 @@ ;;; cc-cmds.el --- user level commands for CC Mode -;; Copyright (C) 1985,87,92,93,94,95,96,97,98,99,2000 Free Software Foundation, Inc. +;; Copyright (C) 1985,1987,1992-2001 Free Software Foundation, Inc. ;; Authors: 2000- Martin Stjernholm ;; 1998-1999 Barry A. Warsaw and Martin Stjernholm @@ -25,19 +25,29 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; along with this program; see the file COPYING. If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. (eval-when-compile (let ((load-path - (if (and (boundp 'byte-compile-current-file) - (stringp byte-compile-current-file)) - (cons (file-name-directory byte-compile-current-file) - load-path) + (if (and (boundp 'byte-compile-dest-file) + (stringp byte-compile-dest-file)) + (cons (file-name-directory byte-compile-dest-file) load-path) load-path))) - (load "cc-defs" nil t))) -(require 'cc-engine) + (require 'cc-bytecomp))) + +(cc-require 'cc-defs) +(cc-require 'cc-vars) +(cc-require 'cc-langs) +(cc-require 'cc-engine) + +;; Silence the compiler. +(cc-bytecomp-defvar delete-key-deletes-forward) ; XEmacs 20+ +(cc-bytecomp-defun delete-forward-p) ; XEmacs 21+ +(cc-bytecomp-obsolete-fun insert-and-inherit) ; Marked obsolete in XEmacs 19 +(cc-bytecomp-defvar filladapt-mode) ; c-fill-paragraph contains a kludge + ; which looks at this. (defun c-calculate-state (arg prevstate) @@ -50,10 +60,11 @@ (> arg 0))) ;; Auto-newline and hungry-delete -(defun c-toggle-auto-state (arg) +(defun c-toggle-auto-state (&optional arg) "Toggle auto-newline feature. -Optional numeric ARG, if supplied turns on auto-newline when positive, -turns it off when negative, and just toggles it when zero. +Optional numeric ARG, if supplied, turns on auto-newline when +positive, turns it off when negative, and just toggles it when zero or +left out. When the auto-newline feature is enabled (as evidenced by the `/a' or `/ah' on the modeline after the mode name) newlines are automatically @@ -64,10 +75,11 @@ (c-update-modeline) (c-keep-region-active)) -(defun c-toggle-hungry-state (arg) +(defun c-toggle-hungry-state (&optional arg) "Toggle hungry-delete-key feature. -Optional numeric ARG, if supplied turns on hungry-delete when positive, -turns it off when negative, and just toggles it when zero. +Optional numeric ARG, if supplied, turns on hungry-delete when +positive, turns it off when negative, and just toggles it when zero or +left out. When the hungry-delete-key feature is enabled (as evidenced by the `/h' or `/ah' on the modeline after the mode name) the delete key @@ -77,11 +89,11 @@ (c-update-modeline) (c-keep-region-active)) -(defun c-toggle-auto-hungry-state (arg) +(defun c-toggle-auto-hungry-state (&optional arg) "Toggle auto-newline and hungry-delete-key features. -Optional numeric ARG, if supplied turns on auto-newline and +Optional numeric ARG, if supplied, turns on auto-newline and hungry-delete when positive, turns them off when negative, and just -toggles them when zero. +toggles them when zero or left out. See `c-toggle-auto-state' and `c-toggle-hungry-state' for details." (interactive "P") @@ -258,9 +270,6 @@ ;; Do not try to insert newlines around a special (Pike-style) ;; brace list. (if (and c-special-brace-lists - (c-intersect-lists '(brace-list-open brace-list-close - brace-list-intro brace-entry-open) - syntax) (save-excursion (c-safe (if (= (char-before) ?{) (forward-char -1) @@ -278,9 +287,12 @@ (if (memq 'before newlines) ;; we leave the newline we've put in there before, ;; but we need to re-indent the line above - (let ((pos (- (point-max) (point))) + (let (old-ind + (old-point-max (point-max)) + (pos (- (point-max) (point))) (here (point))) (forward-line -1) + (setq old-ind (c-point 'boi)) (let ((c-state-cache (c-whack-state (point) c-state-cache))) ;; we may need to update the cache. this should ;; still be faster than recalculating the state @@ -296,9 +308,9 @@ (setq c-state-cache (c-hack-state (point) 'open c-state-cache))))) (if c-syntactic-indentation - (c-indent-line))) - (setq c-state-cache (c-adjust-state (c-point 'bol) here - (- (point) (c-point 'bol)) + (indent-according-to-mode))) + (setq c-state-cache (c-adjust-state (c-point 'bol) old-point-max + (- (c-point 'boi) old-ind) c-state-cache)) (goto-char (- (point-max) pos)) ;; if the buffer has changed due to the indentation, we @@ -327,17 +339,19 @@ (setq syntax (c-guess-basic-syntax)) ;; gotta punt. this requires some horrible kludgery (beginning-of-line) - (makunbound 'c-state-cache) - (setq c-state-cache (c-parse-state) + (setq c-state-cache nil + c-state-cache (c-parse-state) syntax nil)))) ) - ;; now adjust the line's indentation. don't update the state - ;; cache since c-guess-basic-syntax isn't called when the - ;; syntax is passed to c-indent-line - (let* ((here (point))) - (c-indent-line syntax) - (setq c-state-cache (c-adjust-state (c-point 'bol) here - (- (c-point 'boi) (c-point 'bol)) + ;; Now adjust the line's indentation. Don't update the state + ;; cache since c-guess-basic-syntax isn't called when + ;; c-syntactic-context is set. + (let* ((old-ind (c-point 'boi)) + (old-point-max (point-max)) + (c-syntactic-context syntax)) + (indent-according-to-mode) + (setq c-state-cache (c-adjust-state (c-point 'bol) old-point-max + (- (c-point 'boi) old-ind) c-state-cache))) ;; Do all appropriate clean ups (let ((here (point)) @@ -396,7 +410,7 @@ (let* ((bufpos (- (point) 2)) (which (if (eq (char-after bufpos) ?{) 'open 'close)) (c-state-cache (c-hack-state bufpos which c-state-cache))) - (c-indent-line)))) + (indent-according-to-mode)))) ;; blink the paren (and (eq last-command-char ?\}) old-blink-paren @@ -432,7 +446,7 @@ (c-echo-syntactic-information-p nil)) (self-insert-command (prefix-numeric-value arg)) (if indentp - (c-indent-line)))) + (indent-according-to-mode)))) (defun c-electric-star (arg) "Insert a star character. @@ -455,9 +469,8 @@ (forward-char -1)) (skip-chars-backward " \t") (bolp))) - ;; shut this up - (let (c-echo-syntactic-information-p) - (c-indent-line)) + (let (c-echo-syntactic-information-p) ; shut this up + (indent-according-to-mode)) )) (defun c-electric-semi&comma (arg) @@ -490,7 +503,7 @@ ;; turned on (if (not c-auto-newline) (if c-syntactic-indentation - (c-indent-line)) + (indent-according-to-mode)) ;; clean ups (let ((pos (- (point-max) (point)))) (if (and (or (and @@ -509,7 +522,7 @@ (goto-char (- (point-max) pos))) ;; re-indent line (if c-syntactic-indentation - (c-indent-line)) + (indent-according-to-mode)) ;; check to see if a newline should be added (let ((criteria c-hanging-semi&comma-criteria) answer add-newline-p) @@ -524,7 +537,7 @@ )) (if add-newline-p (progn (newline) - (c-indent-line))) + (indent-according-to-mode))) ))))) (defun c-electric-colon (arg) @@ -587,7 +600,8 @@ c-hanging-colons-alist)))) ;; indent the current line if it's done syntactically. (if c-syntactic-indentation - (c-indent-line syntax)) + (let ((c-syntactic-context syntax)) + (indent-according-to-mode))) ;; does a newline go before the colon? Watch out for already ;; non-hung colons. However, we don't unhang them because that ;; would be a cleanup (and anti-social). @@ -599,14 +613,14 @@ (let ((pos (- (point-max) (point)))) (forward-char -1) (newline) - (c-indent-line) + (indent-according-to-mode) (goto-char (- (point-max) pos)))) ;; does a newline go after the colon? (if (and (memq 'after (cdr-safe newlines)) (not is-scope-op)) (progn (newline) - (c-indent-line))) + (indent-according-to-mode))) ))) (defun c-electric-lt-gt (arg) @@ -625,14 +639,13 @@ (c-echo-syntactic-information-p nil)) (self-insert-command (prefix-numeric-value arg)) (if indentp - (c-indent-line)))) + (indent-according-to-mode)))) (defun c-electric-paren (arg) "Insert a parenthesis. -If the auto-newline feature is turned on, as evidenced by the \"/a\" -or \"/ah\" string on the mode line, some newline cleanups are done if -appropriate; see the variable `c-cleanup-list'. +Some newline cleanups are done if appropriate; see the variable +`c-cleanup-list'. Also, the line is re-indented unless a numeric ARG is supplied, there are non-whitespace characters present on the line after the @@ -642,7 +655,6 @@ (let (;; shut this up (c-echo-syntactic-information-p nil)) (if (or arg - (not (looking-at "[ \t]*$")) (c-in-literal (c-point 'bod))) (self-insert-command (prefix-numeric-value arg)) ;; do some special stuff with the character @@ -652,43 +664,86 @@ (old-blink-paren blink-paren-function) blink-paren-function) (self-insert-command (prefix-numeric-value arg)) - (if c-syntactic-indentation - (c-indent-line)) - (when c-auto-newline - ;; Do all appropriate clean ups - (let ((here (point)) - (pos (- (point-max) (point))) - mbeg mend) - ;; clean up brace-elseif-brace - (if (and (memq 'brace-elseif-brace c-cleanup-list) - (eq last-command-char ?\() - (re-search-backward "}[ \t\n]*else[ \t\n]+if[ \t\n]*(" - nil t) - (save-excursion - (setq mbeg (match-beginning 0) - mend (match-end 0)) - (= mend here)) - (not (c-in-literal))) - (progn - (delete-region mbeg mend) - (insert "} else if ("))) - ;; clean up brace-catch-brace - (if (and (memq 'brace-catch-brace c-cleanup-list) - (eq last-command-char ?\() - (re-search-backward "}[ \t\n]*catch[ \t\n]*(" nil t) - (save-excursion - (setq mbeg (match-beginning 0) - mend (match-end 0)) - (= mend here)) - (not (c-in-literal))) - (progn - (delete-region mbeg mend) - (insert "} catch ("))) - (goto-char (- (point-max) pos)) - )) + (when (looking-at "[ \t]*$") + (if c-syntactic-indentation + (indent-according-to-mode)) + (when c-auto-newline + ;; Do all appropriate clean ups + (let ((here (point)) + (pos (- (point-max) (point))) + mbeg mend) + ;; clean up brace-elseif-brace + (if (and (memq 'brace-elseif-brace c-cleanup-list) + (eq last-command-char ?\() + (re-search-backward "}[ \t\n]*else[ \t\n]+if[ \t\n]*(" + nil t) + (save-excursion + (setq mbeg (match-beginning 0) + mend (match-end 0)) + (= mend here)) + (not (c-in-literal))) + (progn + (delete-region mbeg mend) + (insert "} else if ("))) + ;; clean up brace-catch-brace + (if (and (memq 'brace-catch-brace c-cleanup-list) + (eq last-command-char ?\() + (re-search-backward "}[ \t\n]*catch[ \t\n]*(" nil t) + (save-excursion + (setq mbeg (match-beginning 0) + mend (match-end 0)) + (= mend here)) + (not (c-in-literal))) + (progn + (delete-region mbeg mend) + (insert "} catch ("))) + (goto-char (- (point-max) pos)) + ))) + (let (beg (end (1- (point)))) + (cond ((and (memq 'space-before-funcall c-cleanup-list) + (eq last-command-char ?\() + (save-excursion + (backward-char) + (skip-chars-backward " \t") + (setq beg (point)) + (c-on-identifier))) + (save-excursion + (delete-region beg end) + (goto-char beg) + (insert " "))) + ((and (memq 'compact-empty-funcall c-cleanup-list) + (eq last-command-char ?\)) + (save-excursion + (c-safe (backward-char 2)) + (when (looking-at "()") + (setq end (point)) + (skip-chars-backward " \t") + (setq beg (point)) + (c-on-identifier)))) + (delete-region beg end)))) (if old-blink-paren (funcall old-blink-paren)))))) +(defun c-electric-continued-statement () + "Reindent the current line if appropriate. + +This function is used to reindent the line after a keyword which +continues an earlier statement is typed, e.g. an \"else\" or the +\"while\" in a do-while block. + +The line is reindented if there is nothing but whitespace before the +keyword on the line, the keyword is not inserted inside a literal, and +`c-syntactic-indentation' is non-nil." + (let (;; shut this up + (c-echo-syntactic-information-p nil)) + (when (and c-syntactic-indentation + (not (eq last-command-char ?_)) + (= (save-excursion + (skip-syntax-backward "w") + (point)) + (c-point 'boi)) + (not (c-in-literal (c-point 'bod)))) + (indent-according-to-mode)))) ;; better movement routines for ThisStyleOfVariablesCommonInCPlusPlus @@ -792,14 +847,13 @@ With prefix arg, go back N - 1 statements. If already at the beginning of a statement then go to the beginning of the closest preceding one, moving into nested blocks if necessary (use -\\[backward-sexp] to skip over a block). If within a comment, or next -to a comment (only whitespace between), move by sentences instead of -statements. +\\[backward-sexp] to skip over a block). If within or next to a +comment or multiline string, move by sentences instead of statements. When called from a program, this function takes 3 optional args: the repetition count, a buffer position limit which is the farthest back -to search, and a flag saying whether to do sentence motion when in a -comment." +to search for the syntactic context, and a flag saying whether to do +sentence motion in or near comments and multiline strings." (interactive (list (prefix-numeric-value current-prefix-arg) nil t)) (let* ((count (or count 1)) @@ -812,48 +866,85 @@ (save-excursion ;; Find the comment next to point if we're not in one. (if (> count 0) - (setq range (if (c-forward-comment -1) - (cons (point) - (progn (c-forward-comment 1) (point))))) - (skip-chars-forward " \t\n") - (setq range (point)) - (setq range (if (c-forward-comment 1) - (cons range (point)) - nil))) + (if (c-forward-comment -1) + (setq range (cons (point) + (progn (c-forward-comment 1) (point)))) + (skip-chars-backward " \t\n\r\f") + (setq range (point)) + (setq range + (if (eq (char-before) ?\") + (c-safe (c-backward-sexp 1) + (cons (point) range))))) + ;; skip-syntax-* doesn't count \n as whitespace.. + (skip-chars-forward " \t\n\r\f") + (if (eq (char-after) ?\") + (setq range (cons (point) + (progn + (c-forward-sexp 1) + (point)))) + (setq range (point)) + (setq range (if (c-forward-comment 1) + (cons range (point)) + nil)))) (setq range (c-collect-line-comments range)))) (if (and (< count 0) (= here (point-max))) ;; Special case because eob might be in a literal. (setq range nil)) (if range (if (and sentence-flag - (/= (char-syntax (char-after (car range))) ?\")) + (or (/= (char-syntax (char-after (car range))) ?\") + ;; Only visit a string if it spans more than one line. + (save-excursion + (goto-char (car range)) + (skip-chars-forward "^\n" (cdr range)) + (< (point) (cdr range))))) (let* ((lit-type (c-literal-type range)) - (beg (save-excursion - (goto-char (car range)) - (looking-at (if (eq lit-type 'c) - comment-start-skip - (concat "\\(" - c-comment-prefix-regexp - "\\)[ \t]*"))) - (goto-char (match-end 0)) - (point))) - (end (save-excursion - (goto-char (- (cdr range) - (if (eq lit-type 'c) 2 1))) - (point)))) - ;; move by sentence, but not past the limit of the literal + (line-prefix (concat "[ \t]*\\(" + c-current-comment-prefix + "\\)[ \t]*")) + (beg (if (eq lit-type 'string) + (1+ (car range)) + (save-excursion + (goto-char (car range)) + (max (progn + (looking-at comment-start-skip) + (match-end 0)) + (progn + (looking-at line-prefix) + (match-end 0)))))) + (end (- (cdr range) (if (eq lit-type 'c) 2 1))) + (beg-of-para (if (eq lit-type 'string) + (lambda ()) + (lambda () + (beginning-of-line) + (if (looking-at line-prefix) + (goto-char (match-end 0))))))) (save-restriction - (narrow-to-region beg end) + ;; Move by sentence, but not past the limit of the + ;; literal, narrowed to the appropriate + ;; paragraph(s). + (narrow-to-region (save-excursion + (let ((pos (min here end))) + (goto-char pos) + (forward-paragraph -1) + (if (looking-at paragraph-separate) + (forward-line)) + (when (> (point) beg) + (funcall beg-of-para) + (when (>= (point) pos) + (forward-paragraph -2) + (funcall beg-of-para))) + (max (point) beg))) + end) (c-safe (forward-sentence (if (< count 0) 1 -1))) (if (and (memq lit-type '(c c++)) ;; Check if we stopped due to a comment ;; prefix and not a sentence end. - (/= (point) beg) + (/= (point) (point-min)) + (/= (point) (point-max)) (save-excursion (beginning-of-line) - (looking-at (concat "[ \t]*\\(" - c-comment-prefix-regexp - "\\)[ \t]*"))) + (looking-at line-prefix)) (>= (point) (match-beginning 0)) (/= (match-beginning 1) (match-end 1)) (or (< (point) (match-end 0)) @@ -883,16 +974,22 @@ ;; comment ender, stop before it. Stop after ;; the ender if there's either nothing or ;; newlines between. - (when (and (eq lit-type 'c) (eq (point) end)) + (when (and (eq lit-type 'c) + (eq (point) (point-max))) (widen) - (skip-chars-backward " \t") - (when (or (eq (point) end) (bolp)) + (when (or (= (skip-chars-backward " \t") 0) + (eq (point) (point-max)) + (bolp)) (goto-char (cdr range))))) - (when (and (eq (point) beg) (looking-at "[ \t]*$")) + (when (and (eq (point) (point-min)) + (looking-at "[ \t]*$")) ;; Stop before instead of after the comment ;; starter if nothing follows it. (widen) - (goto-char (car range)))))) + (goto-char (car range)) + (if (and (eq lit-type 'string) (/= (point) here)) + (setq count (1+ count) + range nil)))))) ;; See if we should escape the literal. (if (> count 0) (if (< (point) here) @@ -915,15 +1012,19 @@ ;; Stop before `{' and after `;', `{', `}' and `};' ;; when not followed by `}' or `)', but on the other ;; side of the syntactic ws. Move by sexps and move - ;; into parens. Also stop before `#' when it's first + ;; into parens. Also stop before `#' when it's at boi ;; on a line. - (let ((comment-pos (not sentence-flag)) + (let ((literal-pos (not sentence-flag)) (large-enough (- (point-max))) last last-below-line) (catch 'done (while t (setq last (point)) - (when (and (looking-at "{\\|^#") (/= here last)) + (when (and (or (eq (char-after) ?\{) + (and (eq (char-after) ?#) + (eq (point) (c-point 'boi))) + ) + (/= here last)) (unless (and c-special-brace-lists (eq (char-after) ?{) (c-looking-at-special-brace-list)) @@ -932,13 +1033,13 @@ (not (eq last-below-line here))) (goto-char last-below-line)) (throw 'done t))) - (if comment-pos + (if literal-pos (c-forward-comment large-enough) (when (c-forward-comment -1) ;; Record position of first comment. (save-excursion (c-forward-comment 1) - (setq comment-pos (point))) + (setq literal-pos (point))) (c-forward-comment large-enough))) (unless last-below-line (if (save-excursion @@ -963,40 +1064,48 @@ (goto-char last) (throw 'done t)))) ((= (char-syntax (char-after)) ?\") - (forward-char) - (c-backward-sexp)) + (let ((end (point))) + (forward-char) + (c-backward-sexp) + (save-excursion + (skip-chars-forward "^\n" end) + (when (< (point) end) + ;; Break at multiline string. + (setq literal-pos (1+ end)) + (throw 'done t))))) (t (skip-syntax-backward "w_")) ; Speedup only. ))) - (if (and (numberp comment-pos) - (< (point) comment-pos)) - ;; We jumped over a comment that should be investigated. - (goto-char comment-pos) + (if (and (numberp literal-pos) + (< (point) literal-pos)) + ;; We jumped over a comment or string that + ;; should be investigated. + (goto-char literal-pos) (setq count (1- count)))) (error (goto-char (point-min)) (setq count 0))) (condition-case nil - ;; Stop before `{', `}', and `#' when it's first on a + ;; Stop before `{', `}', and `#' when it's at boi on a ;; line, but on the other side of the syntactic ws, and ;; after `;', `}' and `};'. Only stop before `{' if at ;; top level or inside braces, though. Move by sexps ;; and move into parens. Also stop at eol of lines - ;; starting with `#'. - (let ((comment-pos (not sentence-flag)) + ;; with `#' at the boi. + (let ((literal-pos (not sentence-flag)) (large-enough (point-max)) last) (catch 'done (while t (setq last (point)) - (if comment-pos + (if literal-pos (c-forward-comment large-enough) (if (progn (skip-chars-forward " \t\n\r\f") ;; Record position of first comment. - (setq comment-pos (point)) + (setq literal-pos (point)) (c-forward-comment 1)) (c-forward-comment large-enough) - (setq comment-pos nil))) + (setq literal-pos nil))) (cond ((and (eq (char-after) ?{) (not (and c-special-brace-lists (c-looking-at-special-brace-list))) @@ -1017,7 +1126,8 @@ (/= here last)) (goto-char last) (throw 'done t)) - ((looking-at "^#") + ((and (eq (char-after) ?#) + (= (point) (c-point 'boi))) (if (= here last) (or (re-search-forward "\\(^\\|[^\\]\\)$" nil t) (goto-char (point-max))) @@ -1027,15 +1137,22 @@ (goto-char (match-end 0)) (throw 'done t)) ((= (char-syntax (char-after)) ?\") - (c-forward-sexp)) + (let ((beg (point))) + (c-forward-sexp) + (save-excursion + (skip-chars-backward "^\n" beg) + (when (> (point) beg) + ;; Break at multiline string. + (setq literal-pos beg) + (throw 'done t))))) (t (forward-char 1) (skip-syntax-forward "w_")) ; Speedup only. ))) - (if (and (numberp comment-pos) - (> (point) comment-pos)) + (if (and (numberp literal-pos) + (> (point) literal-pos)) ;; We jumped over a comment that should be investigated. - (goto-char comment-pos) + (goto-char literal-pos) (setq count (1+ count)))) (error (goto-char (point-max)) @@ -1044,23 +1161,20 @@ ;; If we haven't moved we're near a buffer limit. (when (and (not (zerop count)) (= (point) here)) (goto-char (if (> count 0) (point-min) (point-max))) - (setq count 0))) - ;; its possible we've been left up-buf of lim - (if lim (goto-char (max (point) lim)))) + (setq count 0)))) (c-keep-region-active)) (defun c-end-of-statement (&optional count lim sentence-flag) "Go to the end of the innermost C statement. With prefix arg, go forward N - 1 statements. Move forward to the end of the next statement if already at end, and move into nested blocks -\(use \\[forward-sexp] to skip over a block). If within a comment, or -next to a comment (only whitespace between), move by sentences instead -of statements. +\(use \\[forward-sexp] to skip over a block). If within or next to a +comment or multiline string, move by sentences instead of statements. When called from a program, this function takes 3 optional args: the repetition count, a buffer position limit which is the farthest back -to search, and a flag saying whether to do sentence motion when in a -comment." +to search for the syntactic context, and a flag saying whether to do +sentence motion in or near comments and multiline strings." (interactive (list (prefix-numeric-value current-prefix-arg) nil t)) (c-beginning-of-statement (- (or count 1)) lim sentence-flag) @@ -1107,8 +1221,8 @@ (search-forward "}") (1+ (current-column))) ;; CASE 2: 2 spaces after #endif - ((or (looking-at "^#[ \t]*endif[ \t]*") - (looking-at "^#[ \t]*else[ \t]*")) + ((or (looking-at "[ \t]*#[ \t]*endif[ \t]*") + (looking-at "[ \t]*#[ \t]*else[ \t]*")) 7) ;; CASE 3: when c-indent-comments-syntactically-p is t, ;; calculate the offset according to c-offsets-alist. @@ -1127,8 +1241,7 @@ ;; to ignore any anchoring as specified by ;; c-comment-only-line-offset since it doesn't apply here. (if (save-excursion - (beginning-of-line) - (skip-chars-forward " \t") + (back-to-indentation) (eolp)) (c-add-syntax 'comment-intro)) (let ((c-comment-only-line-offset @@ -1136,7 +1249,7 @@ c-comment-only-line-offset (cons c-comment-only-line-offset c-comment-only-line-offset)))) - (apply '+ (mapcar 'c-get-offset syntax))))) + (c-get-syntactic-indentation syntax)))) ;; CASE 4: If previous line is a comment-only line, use its ;; indentation if it's greater than comment-column. Leave at ;; least one space between the comment and the last nonblank @@ -1346,7 +1459,7 @@ (let ((bod (c-point 'bod)) (indent-function (if c-syntactic-indentation - (symbol-function 'c-indent-line) + (symbol-function 'indent-according-to-mode) (lambda () (let ((steps (cond ((not current-prefix-arg) 1) ((equal current-prefix-arg '(4)) -1) @@ -1357,8 +1470,15 @@ ;; If c-syntactic-indentation and got arg, always indent this ;; line as C and shift remaining lines of expression the same ;; amount. - (let ((shift-amt (c-indent-line)) + (let ((shift-amt (save-excursion + (back-to-indentation) + (current-column))) beg end) + (c-indent-line) + (setq shift-amt (- (save-excursion + (back-to-indentation) + (current-column)) + shift-amt)) (save-excursion (if (eq c-tab-always-indent t) (beginning-of-line)) @@ -1369,7 +1489,7 @@ (forward-line 1) (setq beg (point))) (if (> end beg) - (indent-code-rigidly beg end (- shift-amt) "#"))) + (indent-code-rigidly beg end shift-amt "#"))) ;; Else use c-tab-always-indent to determine behavior. (cond ;; CASE 1: indent when at column zero or in lines indentation, @@ -1392,57 +1512,39 @@ ))))) (defun c-indent-exp (&optional shutup-p) - "Indent each line in balanced expression following point syntactically. -Optional SHUTUP-P if non-nil, inhibits message printing and error checking." + "Indent each line in the balanced expression following point syntactically. +If optional SHUTUP-P is non-nil, no errors are signalled if no +balanced expression is found." (interactive "*P") (let ((here (point-marker)) - end progress-p) + end) (set-marker-insertion-type here t) (unwind-protect - (let ((c-echo-syntactic-information-p nil) ;keep quiet for speed - (start (progn + (let ((start (progn ;; try to be smarter about finding the range of ;; lines to indent. skip all following - ;; whitespace. failing that, try to find any - ;; opening brace on the current line + ;; whitespace, then try to find any + ;; opening paren on the current line (skip-chars-forward " \t\n") - (if (memq (char-after) '(?\( ?\[ ?\{)) - (point) - (let ((state (parse-partial-sexp (point) - (c-point 'eol)))) - (and (nth 1 state) - (goto-char (nth 1 state)) - (memq (char-after) '(?\( ?\[ ?\{)) - (point))))))) + (save-restriction + (narrow-to-region (point-min) (c-point 'eol)) + (c-safe (1- (scan-lists (point) 1 -1))))))) ;; find balanced expression end (setq end (and (c-safe (progn (c-forward-sexp 1) t)) - (point-marker))) + (point))) ;; sanity check - (and (not start) - (not shutup-p) - (error "Cannot find start of balanced expression to indent.")) - (and (not end) - (not shutup-p) - (error "Cannot find end of balanced expression to indent.")) - (c-progress-init start end 'c-indent-exp) - (setq progress-p t) - (goto-char start) - (beginning-of-line) - (while (< (point) end) - (if (not (looking-at "[ \t]*$")) - (c-indent-line)) - (c-progress-update) - (forward-line 1))) - ;; make sure marker is deleted - (and end - (set-marker end nil)) - (and progress-p - (c-progress-fini 'c-indent-exp)) + (if (not start) + (unless shutup-p + (error "Cannot find start of balanced expression to indent")) + (if (not end) + (unless shutup-p + (error "Cannot find end of balanced expression to indent")) + (c-indent-region start end)))) (goto-char here) (set-marker here nil)))) (defun c-indent-defun () - "Re-indents the current top-level function def, struct or class declaration + "Indent the current top-level function def, struct or class declaration syntactically." (interactive "*") (let ((here (point-marker)) @@ -1467,96 +1569,37 @@ (goto-char here) (set-marker here nil)))) -(defun c-indent-region (start end) - ;; Indent every line whose first char is between START and END inclusive. +(defun c-indent-region (start end &optional quiet) + "Indent every line whose first char is between START and END inclusive. +Be silent about syntactic errors if the optional argument QUIET is non-nil." (save-excursion (goto-char start) ;; Advance to first nonblank line. (skip-chars-forward " \t\n") (beginning-of-line) - (let (endmark) - (unwind-protect - (let ((c-tab-always-indent t) - ;; shut up any echo msgs on indiv lines - (c-echo-syntactic-information-p nil) - fence) - (c-progress-init start end 'c-indent-region) - (setq endmark (copy-marker end)) - (while (and (bolp) - (not (eobp)) - (< (point) endmark)) - ;; update progress - (c-progress-update) - ;; Indent one line as with TAB. - (let (nextline sexpend sexpbeg) - ;; skip blank lines - (skip-chars-forward " \t\n") - (beginning-of-line) - ;; indent the current line - (c-indent-line) - (setq fence (point)) - (if (save-excursion - (beginning-of-line) - (looking-at "[ \t]*#")) - (forward-line 1) - (save-excursion - ;; Find beginning of following line. - (setq nextline (c-point 'bonl)) - ;; Find first beginning-of-sexp for sexp extending past - ;; this line. - (beginning-of-line) - (while (< (point) nextline) - (condition-case nil - (progn - (c-forward-sexp 1) - (setq sexpend (point))) - (error (setq sexpend nil) - (goto-char nextline))) - (c-forward-syntactic-ws)) - (if sexpend - (progn - ;; make sure the sexp we found really starts on the - ;; current line and extends past it - (goto-char sexpend) - (setq sexpend (point-marker)) - (c-safe (c-backward-sexp 1)) - (setq sexpbeg (point)))) - (if (and sexpbeg (< sexpbeg fence)) - (setq sexpbeg fence))) - ;; Since we move by sexps we might have missed - ;; comment-only lines. - (if sexpbeg - (save-excursion - (while (progn - (forward-line 1) - (skip-chars-forward " \t") - (< (point) sexpbeg)) - (if (looking-at c-comment-start-regexp) - (setq sexpbeg (c-point 'bol)))))) - ;; If that sexp ends within the region, indent it all at - ;; once, fast. - (condition-case nil - (if (and sexpend - (> sexpend nextline) - (<= sexpend endmark)) - (progn - (goto-char sexpbeg) - (c-indent-exp 'shutup) - (c-progress-update) - (goto-char sexpend))) - (error - (goto-char sexpbeg) - (c-indent-line))) - ;; Move to following line and try again. - (and sexpend - (markerp sexpend) - (set-marker sexpend nil)) - (forward-line 1) - (setq fence (point)))))) - (set-marker endmark nil) - (c-progress-fini 'c-indent-region) - (c-echo-parsing-error) - )))) + (setq c-parsing-error + (or (let ((endmark (copy-marker end)) + (c-parsing-error nil) + ;; shut up any echo msgs on indiv lines + (c-echo-syntactic-information-p nil)) + (unwind-protect + (progn + (c-progress-init start end 'c-indent-region) + (while (and (bolp) + (not (eobp)) + (< (point) endmark)) + ;; update progress + (c-progress-update) + ;; skip blank lines + (skip-chars-forward " \t\n") + (beginning-of-line) + ;; indent the current line + (c-indent-line nil t) + (forward-line))) + (set-marker endmark nil) + (c-progress-fini 'c-indent-region)) + (c-echo-parsing-error quiet)) + c-parsing-error)))) (defun c-mark-function () "Put mark at end of current top-level defun, point at beginning." @@ -1582,10 +1625,10 @@ (c-backward-syntactic-ws) (skip-chars-backward ";") (point)) - (cdar state))) + (cdr (car state)))) (progn (setq eod (point)) - (goto-char (caar state)) + (goto-char (car (car state))) (c-beginning-of-statement-1)) (if (= ?{ (save-excursion (c-end-of-statement-1) @@ -1613,13 +1656,18 @@ (push-mark here) (push-mark eod nil t))) +(defun c-fn-region-is-active-p () + ;; Function version of the macro for use in places that aren't + ;; compiled, e.g. in the menus. + (c-region-is-active-p)) + (defun c-indent-line-or-region () "When the region is active, indent it. Otherwise indent the current line." ;; Emacs has a variable called mark-active, XEmacs uses region-active-p (interactive) (if (c-region-is-active-p) (c-indent-region (region-beginning) (region-end)) - (c-indent-command))) + (indent-according-to-mode))) ;; for progress reporting @@ -1632,7 +1680,7 @@ ;; Start the progress update messages. If this Emacs doesn't have ;; a built-in timer, just be dumb about it. ((not (fboundp 'current-time)) - (message "indenting region... (this may take a while)")) + (message "Indenting region... (this may take a while)")) ;; If progress has already been initialized, do nothing. otherwise ;; initialize the counter with a vector of: ;; [start end lastsec context] @@ -1643,7 +1691,7 @@ (point-marker)) (nth 1 (current-time)) context)) - (message "indenting region...")) + (message "Indenting region...")) )) (defun c-progress-update () @@ -1658,7 +1706,7 @@ ;; what's the right value? (if (< c-progress-interval (- now lastsecs)) (progn - (message "indenting region... (%d%% complete)" + (message "Indenting region... (%d%% complete)" (/ (* 100 (- (point) start)) (- end start))) (aset c-progress-info 2 now))) ))) @@ -1672,7 +1720,7 @@ (progn (set-marker (aref c-progress-info 1) nil) (setq c-progress-info nil) - (message "indenting region...done"))))) + (message "Indenting region... done"))))) @@ -1748,6 +1796,10 @@ ;;; Line breaking and paragraph filling. +(defvar c-auto-fill-prefix t) +(defvar c-lit-limits nil) +(defvar c-lit-type nil) + ;; The filling code is based on a simple theory; leave the intricacies ;; of the text handling to the currently active mode for that ;; (e.g. adaptive-fill-mode or filladapt-mode) and do as little as @@ -1772,12 +1824,12 @@ ;; function also uses the value of point in some heuristics. (let* ((here (point)) (prefix-regexp (concat "[ \t]*\\(" - c-comment-prefix-regexp + c-current-comment-prefix "\\)[ \t]*")) (comment-start-regexp (if (eq lit-type 'c++) prefix-regexp comment-start-skip)) - prefix-line comment-prefix res) + prefix-line comment-prefix res comment-text-end) (cond (fill-prefix (setq res (cons fill-prefix @@ -1796,7 +1848,8 @@ ((eq lit-type 'c++) (save-excursion ;; Set fallback for comment-prefix if none is found. - (setq comment-prefix "// ") + (setq comment-prefix "// " + comment-text-end (cdr lit-limits)) (beginning-of-line) (if (> (point) (car lit-limits)) ;; The current line is not the comment starter, so the @@ -1847,6 +1900,7 @@ ))))) (t (save-excursion + (setq comment-text-end (- (cdr lit-limits) 2)) (beginning-of-line) (if (and (> (point) (car lit-limits)) (not (and (looking-at "[ \t]*\\*/") @@ -1868,7 +1922,7 @@ ;; The comment is either one line or the next line ;; contains just the comment ender. Also, if point is ;; on the comment opener line and the following line is - ;; empty or doesn't match c-comment-prefix-regexp we + ;; empty or doesn't match c-current-comment-prefix we ;; assume that this is in fact a not yet closed one line ;; comment, so we shouldn't look for the comment prefix ;; on the next line. In these cases we have no @@ -1910,7 +1964,7 @@ ;; "" or ends with whitespace. (insert "x\n" comment-prefix ?x) (setq tmp-post (point-marker)) - (c-indent-line) + (indent-according-to-mode) (goto-char (1- tmp-post)) (cons (buffer-substring-no-properties (c-point 'bol) (point)) @@ -1931,37 +1985,56 @@ (test-line (lambda () (when (and (looking-at prefix-regexp) - (< (match-end 0) (1- (cdr lit-limits)))) + (<= (match-end 0) comment-text-end)) + (unless (eq (match-end 0) (c-point 'eol)) + ;; The match is fine if there's text after it. + (throw 'found (cons (buffer-substring-no-properties + (match-beginning 0) (match-end 0)) + (progn (goto-char (match-end 0)) + (current-column))))) (unless fb-string + ;; This match is better than nothing, so let's + ;; remember it in case nothing better is found + ;; on another line. (setq fb-string (buffer-substring-no-properties (match-beginning 0) (match-end 0)) fb-endpos (match-end 0))) - (unless (eq (match-end 0) (c-point 'eol)) - (throw 'found t)) t)))) - (if (catch 'found + (or (catch 'found ;; Search for a line which has text after the prefix ;; so that we get the proper amount of whitespace ;; after it. We start with the current line, then ;; search backwards, then forwards. (goto-char prefix-line) (when (and (funcall test-line) - (/= (match-end 1) (match-end 0))) + (or (/= (match-end 1) (match-end 0)) + ;; The whitespace is sucked up by the + ;; first [ \t]* glob if the prefix is empty. + (and (= (match-beginning 1) (match-end 1)) + (/= (match-beginning 0) (match-end 0))))) ;; If the current line doesn't have text but do ;; have whitespace after the prefix, we'll use it. - (throw 'found t)) - (while (and (zerop (forward-line -1)) - (> (point) (car lit-limits))) - (funcall test-line)) + (throw 'found (cons fb-string + (progn (goto-char fb-endpos) + (current-column))))) + (if (eq lit-type 'c++) + ;; For line comments we can search up to and + ;; including the first line. + (while (and (zerop (forward-line -1)) + (>= (point) (car lit-limits))) + (funcall test-line)) + ;; For block comments we must stop before the + ;; block starter. + (while (and (zerop (forward-line -1)) + (> (point) (car lit-limits))) + (funcall test-line))) (goto-char prefix-line) (while (and (zerop (forward-line 1)) (< (point) (cdr lit-limits))) (funcall test-line)) + (goto-char prefix-line) nil) - ;; A good line with text after the prefix was found. - (cons (buffer-substring-no-properties (point) (match-end 0)) - (progn (goto-char (match-end 0)) (current-column))) - (if fb-string + (when fb-string ;; A good line wasn't found, but at least we have a ;; fallback that matches the comment prefix regexp. (cond ((string-match "\\s \\'" fb-string) @@ -1997,13 +2070,14 @@ (c-point 'bol) (point)) (current-column))) - (delete-region tmp (point))))) + (delete-region tmp (point)) + (set-buffer-modified-p buffer-modified)))) (t ;; Last resort: Just add a single space after ;; the prefix. (cons (concat fb-string " ") (progn (goto-char fb-endpos) - (1+ (current-column)))))) + (1+ (current-column))))))) ;; The line doesn't match the comment prefix regexp. (if comment-prefix ;; We have a fallback for line comments that we must use. @@ -2016,7 +2090,7 @@ ;; comment where the lines doesn't have any comment ;; prefix at all and we should just fill it as ;; normal text. - '("" . 0))))))) + '("" . 0)))))) )) (defun c-fill-paragraph (&optional arg) @@ -2043,193 +2117,240 @@ (let (lit-limits lit-type fill ;; beg and end limits the region to be filled. end is a marker. beg end - ;; tmp-pre and tmp-post marks strings that are temporarily + ;; tmp-pre and tmp-post mark strings that are temporarily ;; inserted at the start and end of the region. tmp-pre is a ;; cons of the positions of the prepended string. tmp-post is ;; a marker pointing to the single character of the appended ;; string. tmp-pre tmp-post - hang-ender-stuck) + ;; If hang-ender-stuck isn't nil, the comment ender is + ;; hanging. In that case it's set to the number of spaces + ;; that should be between the text and the ender. + hang-ender-stuck + (here (point))) ;; Restore point on undo. It's necessary since we do a lot of ;; hidden inserts and deletes below that should be as transparent ;; as possible. (if (and buffer-undo-list (not (eq buffer-undo-list t))) (setq buffer-undo-list (cons (point) buffer-undo-list))) + (save-restriction + ;; Widen to catch comment limits correctly. + (widen) + (setq lit-limits (c-collect-line-comments (c-literal-limits nil t)) + lit-type (c-literal-type lit-limits))) (save-excursion - (save-restriction - ;; Widen to catch comment limits correctly. - (widen) - (setq lit-limits (c-collect-line-comments (c-literal-limits nil t)) - lit-type (c-literal-type lit-limits))) - (forward-paragraph) - (setq end (point-marker)) - (backward-paragraph) + (unless (c-safe (backward-char) + (forward-paragraph) + (>= (point) here)) + (goto-char here) + (forward-paragraph)) + (setq end (point-marker))) + (save-excursion + (unless (c-safe (forward-char) + (backward-paragraph) + (<= (point) here)) + (goto-char here) + (backward-paragraph)) (setq beg (point))) - (when (and (>= (point) beg) (<= (point) end)) - (unwind-protect - (progn - (cond - ((eq lit-type 'c++) ; Line comment. - (save-excursion - ;; Fill to the comment or paragraph end, whichever - ;; comes first. - (set-marker end (min end (cdr lit-limits))) - (when (<= beg (car lit-limits)) - ;; The region to be filled includes the comment - ;; starter, so we must check it. - (goto-char (car lit-limits)) - (back-to-indentation) - (if (eq (point) (car lit-limits)) - ;; Include the first line in the fill. - (setq beg (c-point 'bol)) - ;; The first line contains code before the - ;; comment. We must fake a line that doesn't. - (setq tmp-pre t))) - )) - ((eq lit-type 'c) ; Block comment. - (save-excursion - (when (>= end (cdr lit-limits)) - ;; The region to be filled includes the comment ender. - (goto-char (cdr lit-limits)) - (beginning-of-line) - (if (and (looking-at (concat "[ \t]*\\(" - c-comment-prefix-regexp - "\\)\\*/")) - (eq (cdr lit-limits) (match-end 0))) - ;; Leave the comment ender on its own line. - (set-marker end (point)) - ;; The comment ender should hang. Replace all - ;; cruft between it and the last word with a 'x' - ;; and include it in the fill. We'll change it - ;; back to a space afterwards. - (let ((ender-start (progn - (goto-char (cdr lit-limits)) - (skip-syntax-backward "^w ") - (point))) - spaces) - (goto-char (cdr lit-limits)) - (setq tmp-post (point-marker)) - (insert ?\n) - (set-marker end (point)) - (forward-line -1) - (if (and (looking-at (concat "[ \t]*\\(\\(" - c-comment-prefix-regexp - "\\)[ \t]*\\)")) - (eq ender-start (match-end 0))) - ;; The comment ender is prefixed by nothing - ;; but a comment line prefix. Remove it - ;; along with surrounding ws. - (setq spaces (- (match-end 1) (match-end 2))) - (goto-char ender-start)) - (skip-chars-backward " \t\r\n") - (when (/= (point) ender-start) - ;; Keep one or two spaces between the text and - ;; the ender, depending on how many there are now. - (unless spaces (setq spaces (- ender-start (point)))) - (setq spaces (max (min spaces 2) 1)) - ; Insert the filler first to keep marks right. - (insert (make-string spaces ?x)) - (delete-region (point) (+ ender-start spaces)) - (setq hang-ender-stuck spaces))))) - (when (<= beg (car lit-limits)) - ;; The region to be filled includes the comment starter. - (goto-char (car lit-limits)) - (if (looking-at (concat "\\(" comment-start-skip "\\)$")) - ;; Begin filling with the next line. - (setq beg (c-point 'bonl)) - ;; Fake the fill prefix in the first line. - (setq tmp-pre t))) - )) - ((eq lit-type 'string) ; String. - (save-excursion - (when (>= end (cdr lit-limits)) - (goto-char (1- (cdr lit-limits))) - (setq tmp-post (point-marker)) - (insert ?\n) - (set-marker end (point))) - (when (<= beg (car lit-limits)) - (goto-char (1+ (car lit-limits))) - (setq beg (if (looking-at "\\\\$") - ;; Leave the start line if it's - ;; nothing but an escaped newline. - (1+ (match-end 0)) - (point)))))) - (t (setq beg nil))) - (when tmp-pre - ;; Temporarily insert the fill prefix after the comment - ;; starter so that the first line looks like any other - ;; comment line in the narrowed region. - (setq fill (c-guess-fill-prefix lit-limits lit-type)) - (unless (string-match (concat "\\`[ \t]*\\(" - c-comment-prefix-regexp - "\\)[ \t]*\\'") - (car fill)) - ;; Oops, the prefix doesn't match the comment prefix - ;; regexp. This could produce very confusing - ;; results with adaptive fill packages together with - ;; the insert prefix magic below, since the prefix - ;; often doesn't appear at all. So let's warn about - ;; it. - (message "\ -Warning: `c-comment-prefix-regexp' doesn't match the comment prefix %S" - (car fill))) - ;; Find the right spot on the line, break it, insert - ;; the fill prefix and make sure we're back in the - ;; same column by temporarily prefixing the first word - ;; with a number of 'x'. + (unwind-protect + (progn + (cond + ((eq lit-type 'c++) ; Line comment. + (save-excursion + ;; Fill to the comment or paragraph end, whichever + ;; comes first. + (set-marker end (min end (cdr lit-limits))) + (when (<= beg (car lit-limits)) + ;; The region to be filled includes the comment + ;; starter, so we must check it. + (goto-char (car lit-limits)) + (back-to-indentation) + (if (eq (point) (car lit-limits)) + ;; Include the first line in the fill. + (setq beg (c-point 'bol)) + ;; The first line contains code before the + ;; comment. We must fake a line that doesn't. + (setq tmp-pre t))) + )) + ((eq lit-type 'c) ; Block comment. + (when (>= end (cdr lit-limits)) + ;; The region to be filled includes the comment ender. + (unless (save-excursion + (goto-char (cdr lit-limits)) + (beginning-of-line) + (and (looking-at (concat "[ \t]*\\(" + c-current-comment-prefix + "\\)\\*/")) + (eq (cdr lit-limits) (match-end 0)) + ;; Leave the comment ender on its own line. + (set-marker end (point)))) + ;; The comment ender should hang. Replace all cruft + ;; between it and the last word with one or two 'x' + ;; and include it in the fill. We'll change them back + ;; spaces afterwards. + (let* ((ender-start (save-excursion + (goto-char (cdr lit-limits)) + (skip-syntax-backward "^w ") + (point))) + (point-rel (- ender-start here)) + spaces) + (save-excursion + (goto-char (cdr lit-limits)) + (setq tmp-post (point-marker)) + (insert ?\n) + (set-marker end (point)) + (forward-line -1) + (if (and (looking-at (concat "[ \t]*\\(\\(" + c-current-comment-prefix + "\\)[ \t]*\\)")) + (eq ender-start (match-end 0))) + ;; The comment ender is prefixed by nothing + ;; but a comment line prefix. Remove it + ;; along with surrounding ws. + (setq spaces (- (match-end 1) (match-end 2))) + (goto-char ender-start)) + (skip-chars-backward " \t\r\n") + (if (/= (point) ender-start) + (progn + (if (<= here (point)) + ;; Don't adjust point below if it's + ;; before the string we replace. + (setq point-rel -1)) + ;; Keep one or two spaces between the text and + ;; the ender, depending on how many there are now. + (unless spaces (setq spaces (- ender-start (point)))) + (setq spaces (max (min spaces 2) 1)) + ;; Insert the filler first to keep marks right. + (insert (make-string spaces ?x)) + (delete-region (point) (+ ender-start spaces)) + (setq hang-ender-stuck spaces) + (setq point-rel + (and (>= point-rel 0) + (- (point) (min point-rel spaces))))) + (setq point-rel nil))) + (if point-rel + ;; Point was in the middle of the string we + ;; replaced above, so put it back in the same + ;; relative position, counting from the end. + (goto-char point-rel)) + ))) + (when (<= beg (car lit-limits)) + ;; The region to be filled includes the comment starter. (save-excursion (goto-char (car lit-limits)) - (if (looking-at (if (eq lit-type 'c++) - c-comment-prefix-regexp - comment-start-skip)) - (goto-char (match-end 0)) - (forward-char 2) - (skip-chars-forward " \t")) - (while (< (current-column) (cdr fill)) (forward-char 1)) - (let ((col (current-column))) - (setq beg (1+ (point)) - tmp-pre (list (point))) - (unwind-protect - (progn - (insert ?\n (car fill)) - (insert (make-string (- col (current-column)) ?x))) - (setcdr tmp-pre (point)))))) - (when beg - (let ((fill-paragraph-function - ;; Avoid infinite recursion. - (if (not (eq fill-paragraph-function 'c-fill-paragraph)) - fill-paragraph-function)) - (fill-prefix - (or fill-prefix - (when (and (eq lit-type 'c++) - (not (string-match - "\\`[ \t]*//" - (or (fill-context-prefix beg end) - "")))) - ;; Kludge: If the function that adapts the - ;; fill prefix doesn't produce the required - ;; comment starter for line comments, then - ;; force it by setting fill-prefix. - (car (or fill (c-guess-fill-prefix - lit-limits lit-type))))))) - ;; Preparations finally done! Now we can call the - ;; real fill function. - (save-restriction - (narrow-to-region beg end) - (fill-paragraph arg))))) - (when (consp tmp-pre) - (delete-region (car tmp-pre) (cdr tmp-pre))) - (when tmp-post - (save-excursion - (goto-char tmp-post) - (delete-char 1) - (when hang-ender-stuck - (skip-syntax-backward "^w ") - (forward-char (- hang-ender-stuck)) - (insert (make-string hang-ender-stuck ?\ )) - (delete-char hang-ender-stuck)) - (set-marker tmp-post nil))))) - (set-marker end nil)) + (if (looking-at (concat "\\(" comment-start-skip "\\)$")) + ;; Begin filling with the next line. + (setq beg (c-point 'bonl)) + ;; Fake the fill prefix in the first line. + (setq tmp-pre t))))) + ((eq lit-type 'string) ; String. + (save-excursion + (when (>= end (cdr lit-limits)) + (goto-char (1- (cdr lit-limits))) + (setq tmp-post (point-marker)) + (insert ?\n) + (set-marker end (point))) + (when (<= beg (car lit-limits)) + (goto-char (1+ (car lit-limits))) + (setq beg (if (looking-at "\\\\$") + ;; Leave the start line if it's + ;; nothing but an escaped newline. + (1+ (match-end 0)) + (point)))))) + (t (setq beg nil))) + (when tmp-pre + ;; Temporarily insert the fill prefix after the comment + ;; starter so that the first line looks like any other + ;; comment line in the narrowed region. + (setq fill (c-guess-fill-prefix lit-limits lit-type)) + (unless (string-match (concat "\\`[ \t]*\\(" + c-current-comment-prefix + "\\)[ \t]*\\'") + (car fill)) + ;; Oops, the prefix doesn't match the comment prefix + ;; regexp. This could produce very confusing + ;; results with adaptive fill packages together with + ;; the insert prefix magic below, since the prefix + ;; often doesn't appear at all. So let's warn about + ;; it. + (message "\ +Warning: Regexp from `c-comment-prefix-regexp' doesn't match the comment prefix %S" + (car fill))) + ;; Find the right spot on the line, break it, insert + ;; the fill prefix and make sure we're back in the + ;; same column by temporarily prefixing the first word + ;; with a number of 'x'. + (save-excursion + (goto-char (car lit-limits)) + (if (looking-at (if (eq lit-type 'c++) + c-comment-prefix-regexp + comment-start-skip)) + (goto-char (match-end 0)) + (forward-char 2) + (skip-chars-forward " \t")) + (while (< (current-column) (cdr fill)) (forward-char 1)) + (let ((col (current-column))) + (setq beg (1+ (point)) + tmp-pre (list (point))) + (unwind-protect + (progn + (insert ?\n (car fill)) + (insert (make-string (- col (current-column)) ?x))) + (setcdr tmp-pre (point)))))) + (when beg + (let ((fill-paragraph-function + ;; Avoid infinite recursion. + (if (not (eq fill-paragraph-function 'c-fill-paragraph)) + fill-paragraph-function)) + (fill-prefix + (or fill-prefix + ;; Kludge: If the function that adapts the fill prefix + ;; doesn't produce the required comment starter for line + ;; comments, then force it by setting fill-prefix. + (when (and (eq lit-type 'c++) + ;; Kludge the kludge: filladapt-mode doesn't + ;; have this problem, but it doesn't override + ;; fill-context-prefix currently (version + ;; 2.12). + (not (and (boundp 'filladapt-mode) + filladapt-mode)) + (not (string-match + "\\`[ \t]*//" + (or (fill-context-prefix beg end) + "")))) + (car (or fill (c-guess-fill-prefix + lit-limits lit-type)))))) + (point-rel (cond ((< here beg) (- here beg)) + ((> here end) (- here end))))) + ;; Preparations finally done! Now we can call the + ;; real fill function. + (save-restriction + (narrow-to-region beg end) + (fill-paragraph arg)) + (if point-rel + ;; Restore point if it was outside the region. + (if (< point-rel 0) + (goto-char (+ beg point-rel)) + (goto-char (+ end point-rel)))) + ))) + (when (consp tmp-pre) + (delete-region (car tmp-pre) (cdr tmp-pre))) + (when tmp-post + (save-excursion + (goto-char tmp-post) + (delete-char 1)) + (when hang-ender-stuck + ;; Preserve point even if it's in the middle of the string + ;; we replace; save-excursion doesn't work in that case. + (setq here (point)) + (goto-char tmp-post) + (skip-syntax-backward "^w ") + (forward-char (- hang-ender-stuck)) + (insert (make-string hang-ender-stuck ?\ )) + (delete-char hang-ender-stuck) + (goto-char here)) + (set-marker tmp-post nil)) + (set-marker end nil))) ;; Always return t. This has the effect that if filling isn't done ;; above, it isn't done at all, and it's therefore effectively ;; disabled in normal code. @@ -2267,9 +2388,9 @@ (if soft (insert-and-inherit ?\n) (newline 1)))) ;; Already know the literal type and limits when called from ;; c-context-line-break. - (c-lit-limits (if (boundp 'c-lit-limits) c-lit-limits)) - (c-lit-type (if (boundp 'c-lit-type) c-lit-type))) - (when (boundp 'c-auto-fill-prefix) + (c-lit-limits c-lit-limits) + (c-lit-type c-lit-type)) + (when (not (eq c-auto-fill-prefix t)) ;; Called from do-auto-fill. (unless c-lit-limits (setq c-lit-limits (c-literal-limits nil nil t))) @@ -2325,7 +2446,7 @@ (if (save-excursion (back-to-indentation) (> (point) (car c-lit-limits)) - (looking-at c-comment-prefix-regexp)) + (looking-at c-current-comment-prefix)) (progn ;; Skip forward past the fill prefix in case ;; we're standing in it. @@ -2390,13 +2511,14 @@ ;; advice for indent-new-comment-line for older Emacsen (unless (boundp 'comment-line-break-function) + (defvar c-inside-line-break-advice nil) (defadvice indent-new-comment-line (around c-line-break-advice activate preactivate) "Call `c-indent-new-comment-line' if in CC Mode." - (if (or (boundp 'c-inside-line-break-advice) + (if (or c-inside-line-break-advice (not c-buffer-is-cc-mode)) ad-do-it - (let (c-inside-line-break-advice) + (let ((c-inside-line-break-advice t)) (c-indent-new-comment-line (ad-get-arg 0)))))) (defun c-context-line-break () @@ -2431,8 +2553,8 @@ (= (forward-line -1) 0)))) (current-column)))) (indent-to col)) - (c-indent-line)))) + (indent-according-to-mode)))) -(provide 'cc-cmds) +(cc-provide 'cc-cmds) ;;; cc-cmds.el ends here