]> code.delx.au - gnu-emacs/blobdiff - lisp/progmodes/c-mode.el
(c-indent-region): As first thing, advance to a nonblank line.
[gnu-emacs] / lisp / progmodes / c-mode.el
index 667f1d174e9e17379e50e1762bfe436c58382b07..429d0bf2292959e1632936a8dd8873a82c63bcf2 100644 (file)
@@ -642,6 +642,8 @@ Returns nil if line starts inside a string, t if in a comment."
                                     ;; Make sure the "function decl" we found
                                     ;; is not inside a comment.
                                     (progn
+                                      ;; Move back to the `(' starting arglist
+                                      (goto-char lim)
                                       (beginning-of-line)
                                       (while (and (not comment)
                                                   (search-forward "/*" lim t))
@@ -955,10 +957,10 @@ If within a string or comment, move by sentences instead of statements."
   (beginning-of-defun)
   (backward-paragraph))
 \f
+;; Idea of ENDPOS is, indent each line, stopping when
+;; ENDPOS is encountered.  But it's too much of a pain to make that work.
 (defun indent-c-exp (&optional endpos)
-  "Indent each line of the C grouping following point.
-If optional arg ENDPOS is given, indent each line, stopping when
-ENDPOS is encountered."
+  "Indent each line of the C grouping following point."
   (interactive)
   (let* ((indent-stack (list nil))
         (opoint (point))  ;; May be altered below.
@@ -989,7 +991,7 @@ ENDPOS is encountered."
         restart outer-loop-done inner-loop-done state ostate
         this-indent last-sexp
         at-else at-brace at-while
-        last-depth
+        last-depth this-point
         (next-depth 0))
     ;; If the braces don't match, get an error right away.
     (save-excursion
@@ -1033,9 +1035,12 @@ ENDPOS is encountered."
          (if (and (car (cdr (cdr state)))
                   (>= (car (cdr (cdr state))) 0))
              (setq last-sexp (car (cdr (cdr state)))))
-         (if (or (nth 4 ostate))
+         ;; If this line started within a comment, indent it as such.
+         (if (or (nth 4 ostate) (nth 7 ostate))
              (c-indent-line))
-         (if (or (nth 3 state))
+         ;; If it ends outside of comments or strings, exit the inner loop.
+         ;; Otherwise move on to next line.
+         (if (or (nth 3 state) (nth 4 state) (nth 7 state))
              (forward-line 1)
            (setq inner-loop-done t)))
        (and endpos
@@ -1085,6 +1090,7 @@ ENDPOS is encountered."
                  ;; Is it a new statement?  Is it an else?
                  ;; Find last non-comment character before this line
                  (save-excursion
+                   (setq this-point (point))
                    (setq at-else (looking-at "else\\W"))
                    (setq at-brace (= (following-char) ?{))
                    (setq at-while (looking-at "while\\b"))
@@ -1105,6 +1111,9 @@ ENDPOS is encountered."
                                                  (current-indentation))))
                            ((and at-while (c-backward-to-start-of-do opoint))
                             (setq this-indent (current-indentation)))
+                           ((eq (preceding-char) ?\,)
+                            (goto-char this-point)
+                            (setq this-indent (calculate-c-indent)))
                            (t (setq this-indent (car indent-stack)))))))
              ;; Just started a new nesting level.
              ;; Compute the standard indent for this level.
@@ -1112,6 +1121,10 @@ ENDPOS is encountered."
                           (if (car indent-stack)
                               (- (car indent-stack))
                             opoint))))
+               ;; t means we are in a block comment and should
+               ;; calculate accordingly.
+               (if (eq val t)
+                   (setq val (calculate-c-indent-within-comment)))
                (setcar indent-stack
                        (setq this-indent val))))
            ;; Adjust line indentation according to its contents
@@ -1124,7 +1137,16 @@ ENDPOS is encountered."
            (if (= (following-char) ?})
                (setq this-indent (- this-indent c-indent-level)))
            (if (= (following-char) ?{)
-               (setq this-indent (+ this-indent c-brace-offset)))
+               ;; Don't move an open-brace in column 0.
+               ;; This is good when constructs such as
+               ;; `extern "C" {' surround a function definition
+               ;; that should be indented as usual.
+               ;; It is also good for nested functions.
+               ;; It is bad when an open-brace is indented at column 0
+               ;; and you want to fix that, but we can't win 'em all.
+               (if (zerop (current-column))
+                   (setq this-indent 0)
+                 (setq this-indent (+ this-indent c-brace-offset))))
            ;; Don't leave indentation in empty lines.
            (if (eolp) (setq this-indent 0))
            ;; Put chosen indentation into effect.
@@ -1169,10 +1191,46 @@ ENDPOS is encountered."
 (defun c-indent-region (start end)
   (save-excursion
     (goto-char start)
-    (let ((endmark (copy-marker end)))
-      (and (bolp) (not (eolp))
-          (c-indent-line))
-      (indent-c-exp endmark)
+    ;; Advance to first nonblank line.
+    (skip-chars-forward " \t\n")
+    (beginning-of-line)
+    (let ((endmark (copy-marker end))
+         (c-tab-always-indent t))
+      (while (and (bolp) (not (eolp)))
+       ;; Indent one line as with TAB.
+       (let ((shift-amt (c-indent-line))
+             nextline sexpbeg sexpend)
+         (save-excursion
+           ;; Find beginning of following line.
+           (save-excursion
+             (forward-line 1) (setq nextline (point)))
+           ;; Find first beginning-of-sexp for sexp extending past this line.
+           (beginning-of-line)
+           (while (< (point) nextline)
+             (condition-case nil
+                 (progn
+                   (forward-sexp 1)
+                   (setq sexpend (point-marker)))
+               (error (setq sexpend nil)
+                      (goto-char nextline)))
+             (skip-chars-forward " \t\n"))
+           (if sexpend
+               (progn
+                 ;; Make sure the sexp we found really starts on the
+                 ;; current line and extends past it.
+                 (goto-char sexpend)
+                 (backward-sexp 1)
+                 (setq sexpbeg (point)))))
+         ;; If that sexp ends within the region,
+         ;; indent it all at once, fast.
+         (if (and sexpend (> sexpend nextline) (<= sexpend endmark)
+                  (< sexpbeg nextline))
+             (progn
+               (indent-c-exp)
+               (goto-char sexpend)))
+         ;; Move to following line and try again.
+         (and sexpend (set-marker sexpend nil))
+         (forward-line 1)))
       (set-marker endmark nil))))
 \f
 (defun set-c-style (style &optional global)