]> 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 cdbf22463132b5882410897e6ee5342339619732..429d0bf2292959e1632936a8dd8873a82c63bcf2 100644 (file)
@@ -957,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.
@@ -1137,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.
@@ -1182,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)