+ (setq beg (point))
+ (goto-char end)
+ (c-backward-syntactic-ws beg)
+ (forward-line)
+ (set-marker end (point))))))
+
+ (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-save-buffer-state nil
+ (c-guess-fill-prefix c-lit-limits c-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 c-lit-limits))
+ (if (looking-at (if (eq c-lit-type 'c++)
+ c-current-comment-prefix
+ comment-start-skip))
+ (goto-char (match-end 0))
+ (forward-char 2)
+ (skip-chars-forward " \t"))
+ (while (and (< (current-column) (cdr fill))
+ (not (eolp)))
+ (forward-char 1))
+ (let ((col (current-column)))
+ (setq beg (1+ (point))
+ tmp-pre (list (point)))
+ (unwind-protect
+ (progn
+ (insert-and-inherit "\n" (car fill))
+ (insert-char ?x (- col (current-column)) t))
+ (setcdr tmp-pre (point))))))
+
+ (when apply-outside-literal
+ ;; `apply-outside-literal' is always set to t here if
+ ;; we're inside a literal.
+
+ (let ((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 c-lit-type 'c++)
+ ;; Kludge the kludge: filladapt-mode doesn't
+ ;; have this problem, but it currently
+ ;; doesn't override fill-context-prefix
+ ;; (version 2.12).
+ (not (and (boundp 'filladapt-mode)
+ filladapt-mode))
+ (not (string-match
+ "\\`[ \t]*//"
+ (or (fill-context-prefix beg end)
+ ""))))
+ (c-save-buffer-state nil
+ (car (or fill (c-guess-fill-prefix
+ c-lit-limits c-lit-type)))))))
+
+ ;; Save the relative position of point if it's outside the
+ ;; region we're going to narrow. Want to restore it in that
+ ;; case, but otherwise it should be moved according to the
+ ;; called function.
+ (point-rel (cond ((< (point) beg) (- (point) beg))
+ ((> (point) end) (- (point) end)))))
+
+ ;; Preparations finally done! Now we can call the
+ ;; actual function.
+ (prog1
+ (save-restriction
+ (narrow-to-region beg end)
+ (apply fun args))
+ (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-char ?\ hang-ender-stuck t)
+ (delete-char hang-ender-stuck)
+ (goto-char here))
+ (set-marker tmp-post nil))
+
+ (set-marker end nil))))
+
+(defun c-fill-paragraph (&optional arg)
+ "Like \\[fill-paragraph] but handles C and C++ style comments.
+If any of the current line is a comment or within a comment, fill the
+comment or the paragraph of it that point is in, preserving the
+comment indentation or line-starting decorations (see the
+`c-comment-prefix-regexp' and `c-block-comment-prefix' variables for
+details).
+
+If point is inside multiline string literal, fill it. This currently
+does not respect escaped newlines, except for the special case when it
+is the very first thing in the string. The intended use for this rule
+is in situations like the following:
+
+char description[] = \"\\
+A very long description of something that you want to fill to make
+nicely formatted output.\"\;
+
+If point is in any other situation, i.e. in normal code, do nothing.
+
+Optional prefix ARG means justify paragraph as well."
+ (interactive "*P")
+ (let ((fill-paragraph-function
+ ;; Avoid infinite recursion.
+ (if (not (eq fill-paragraph-function 'c-fill-paragraph))
+ fill-paragraph-function)))
+ (c-mask-paragraph t nil 'fill-paragraph arg))
+ ;; 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.
+ t)
+
+(defun c-do-auto-fill ()
+ ;; Do automatic filling if not inside a context where it should be
+ ;; ignored.
+ ;;
+ ;; This function does not do any hidden buffer changes.
+ (let ((c-auto-fill-prefix
+ ;; The decision whether the line should be broken is actually
+ ;; done in c-indent-new-comment-line, which do-auto-fill
+ ;; calls to break lines. We just set this special variable
+ ;; so that we'll know when we're called from there. It's
+ ;; also used to detect whether fill-prefix is user set or
+ ;; generated automatically by do-auto-fill.
+ fill-prefix))
+ (c-mask-paragraph nil t 'do-auto-fill)))
+
+(defun c-indent-new-comment-line (&optional soft allow-auto-fill)
+ "Break line at point and indent, continuing comment or macro if within one.
+If inside a comment and `comment-multi-line' is non-nil, the
+indentation and line prefix are preserved (see the
+`c-comment-prefix-regexp' and `c-block-comment-prefix' variables for
+details). If inside a single line comment and `comment-multi-line' is
+nil, a new comment of the same type is started on the next line and
+indented as appropriate for comments. If inside a macro, a line
+continuation backslash is inserted and aligned as appropriate, and the
+new line is indented according to `c-syntactic-indentation'.
+
+If a fill prefix is specified, it overrides all the above."
+ ;; allow-auto-fill is used from c-context-line-break to allow auto
+ ;; filling to break the line more than once. Since this function is
+ ;; used from auto-fill itself, that's normally disabled to avoid
+ ;; unnecessary recursion.
+ (interactive)
+ (let ((fill-prefix fill-prefix)
+ (do-line-break
+ (lambda ()
+ (delete-horizontal-space)
+ (if soft
+ (insert-and-inherit ?\n)
+ (newline (if allow-auto-fill nil 1)))))
+ ;; Already know the literal type and limits when called from
+ ;; c-context-line-break.
+ (c-lit-limits c-lit-limits)
+ (c-lit-type c-lit-type)
+ (c-macro-start c-macro-start))
+ (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)))
+ (unless c-lit-type
+ (setq c-lit-type (c-literal-type c-lit-limits)))
+ (if (memq (cond ((c-query-and-set-macro-start) 'cpp)
+ ((null c-lit-type) 'code)
+ (t c-lit-type))
+ c-ignore-auto-fill)
+ (setq fill-prefix t) ; Used as flag in the cond.
+ (if (and (null c-auto-fill-prefix)
+ (eq c-lit-type 'c)
+ (<= (c-point 'bol) (car c-lit-limits)))
+ ;; The adaptive fill function has generated a prefix, but
+ ;; we're on the first line in a block comment so it'll be
+ ;; wrong. Ignore it to guess a better one below.
+ (setq fill-prefix nil)
+ (when (and (eq c-lit-type 'c++)
+ (not (string-match "\\`[ \t]*//" (or fill-prefix ""))))
+ ;; Kludge: If the function that adapted the fill prefix
+ ;; doesn't produce the required comment starter for line
+ ;; comments, then we ignore it.
+ (setq fill-prefix nil)))
+ ))
+ (cond ((eq fill-prefix t)
+ ;; A call from do-auto-fill which should be ignored.
+ )
+ (fill-prefix
+ ;; A fill-prefix overrides anything.
+ (funcall do-line-break)
+ (insert-and-inherit fill-prefix))
+ ((progn
+ (unless c-lit-limits
+ (setq c-lit-limits (c-literal-limits)))
+ (unless c-lit-type
+ (setq c-lit-type (c-literal-type c-lit-limits)))
+ (memq c-lit-type '(c c++)))
+ ;; Some sort of comment.
+ (if (or comment-multi-line
+ (save-excursion
+ (goto-char (car c-lit-limits))
+ (end-of-line)
+ (< (point) (cdr c-lit-limits))))
+ ;; Inside a comment that should be continued.
+ (let ((fill (c-save-buffer-state nil
+ (c-guess-fill-prefix
+ (setq c-lit-limits
+ (c-collect-line-comments c-lit-limits))
+ c-lit-type)))
+ (pos (point))
+ (comment-text-end
+ (or (and (eq c-lit-type 'c)
+ (save-excursion
+ (goto-char (- (cdr c-lit-limits) 2))
+ (if (looking-at "\\*/") (point))))
+ (cdr c-lit-limits))))
+ ;; Skip forward past the fill prefix in case
+ ;; we're standing in it.
+ ;;
+ ;; FIXME: This doesn't work well in cases like
+ ;;
+ ;; /* Bla bla bla bla bla
+ ;; bla bla
+ ;;
+ ;; If point is on the 'B' then the line will be
+ ;; broken after "Bla b".
+ (while (and (< (current-column) (cdr fill))
+ (not (eolp)))
+ (forward-char 1))
+ (if (and (> (point) comment-text-end)
+ (> (c-point 'bol) (car c-lit-limits)))
+ (progn
+ ;; The skip takes us out of the (block)
+ ;; comment; insert the fill prefix at bol
+ ;; instead and keep the position.
+ (setq pos (copy-marker pos t))
+ (beginning-of-line)
+ (insert-and-inherit (car fill))
+ (if soft (insert-and-inherit ?\n) (newline 1))
+ (goto-char pos)
+ (set-marker pos nil))
+ ;; Don't break in the middle of a comment starter
+ ;; or ender.
+ (cond ((> (point) comment-text-end)
+ (goto-char comment-text-end))
+ ((< (point) (+ (car c-lit-limits) 2))
+ (goto-char (+ (car c-lit-limits) 2))))
+ (funcall do-line-break)
+ (insert-and-inherit (car fill))))
+ ;; Inside a comment that should be broken.
+ (let ((comment-start comment-start)
+ (comment-end comment-end)
+ col)
+ (if (eq c-lit-type 'c)
+ (unless (string-match "[ \t]*/\\*" comment-start)
+ (setq comment-start "/* " comment-end " */"))
+ (unless (string-match "[ \t]*//" comment-start)
+ (setq comment-start "// " comment-end "")))
+ (setq col (save-excursion
+ (back-to-indentation)
+ (current-column)))
+ (funcall do-line-break)
+ (when (and comment-end (not (equal comment-end "")))
+ (forward-char -1)
+ (insert-and-inherit comment-end)
+ (forward-char 1))
+ ;; c-comment-indent may look at the current
+ ;; indentation, so let's start out with the same
+ ;; indentation as the previous one.
+ (indent-to col)
+ (insert-and-inherit comment-start)
+ (indent-for-comment))))
+ ((c-query-and-set-macro-start)
+ ;; In a macro.
+ (unless (looking-at "[ \t]*\\\\$")
+ ;; Do not clobber the alignment of the line continuation
+ ;; slash; c-backslash-region might look at it.
+ (delete-horizontal-space))
+ ;; Got an asymmetry here: In normal code this command
+ ;; doesn't indent the next line syntactically, and otoh a
+ ;; normal syntactically indenting newline doesn't continue
+ ;; the macro.
+ (c-newline-and-indent (if allow-auto-fill nil 1)))
+ (t
+ ;; Somewhere else in the code.
+ (let ((col (save-excursion
+ (beginning-of-line)
+ (while (and (looking-at "[ \t]*\\\\?$")
+ (= (forward-line -1) 0)))
+ (current-indentation))))
+ (funcall do-line-break)
+ (indent-to col))))))
+
+(defalias 'c-comment-line-break-function 'c-indent-new-comment-line)
+(make-obsolete 'c-comment-line-break-function 'c-indent-new-comment-line)
+
+;; 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 c-inside-line-break-advice
+ (not c-buffer-is-cc-mode))
+ ad-do-it
+ (let ((c-inside-line-break-advice t))
+ (c-indent-new-comment-line (ad-get-arg 0))))))
+
+(defun c-context-line-break ()
+ "Do a line break suitable to the context.
+
+When point is outside a comment or macro, insert a newline and indent
+according to the syntactic context, unless `c-syntactic-indentation'
+is nil, in which case the new line is indented as the previous
+non-empty line instead.
+
+When point is inside the content of a preprocessor directive, a line
+continuation backslash is inserted before the line break and aligned
+appropriately. The end of the cpp directive doesn't count as inside
+it.
+
+When point is inside a comment, continue it with the appropriate
+comment prefix (see the `c-comment-prefix-regexp' and
+`c-block-comment-prefix' variables for details). The end of a
+C++-style line comment doesn't count as inside it."
+ (interactive "*")
+ (let* ((c-lit-limits (c-literal-limits nil nil t))
+ (c-lit-type (c-literal-type c-lit-limits))
+ (c-macro-start c-macro-start))
+ (if (or (eq c-lit-type 'c)
+ (and (eq c-lit-type 'c++)
+ (< (save-excursion
+ (skip-chars-forward " \t")
+ (point))
+ (1- (cdr (setq c-lit-limits
+ (c-collect-line-comments c-lit-limits))))))
+ (and (or (not (looking-at "\\s *$"))
+ (eq (char-before) ?\\))
+ (c-query-and-set-macro-start)
+ (<= (save-excursion
+ (goto-char c-macro-start)
+ (if (looking-at c-opt-cpp-start)
+ (goto-char (match-end 0)))
+ (point))
+ (point))))
+ (let ((comment-multi-line t)
+ (fill-prefix nil))
+ (c-indent-new-comment-line nil t))
+ (delete-horizontal-space)
+ (newline)
+ ;; c-indent-line may look at the current indentation, so let's
+ ;; start out with the same indentation as the previous line.
+ (let ((col (save-excursion
+ (forward-line -1)
+ (while (and (looking-at "[ \t]*\\\\?$")
+ (= (forward-line -1) 0)))
+ (current-indentation))))
+ (indent-to col))
+ (indent-according-to-mode))))
+
+(defun c-context-open-line ()
+ "Insert a line break suitable to the context and leave point before it.
+This is the `c-context-line-break' equivalent to `open-line', which is
+normally bound to C-o. See `c-context-line-break' for the details."
+ (interactive "*")
+ (let ((here (point)))
+ (unwind-protect
+ (progn
+ ;; Temporarily insert a non-whitespace char to keep any
+ ;; preceding whitespace intact.
+ (insert ?x)
+ (c-context-line-break))
+ (goto-char here)
+ (delete-char 1))))