]> code.delx.au - gnu-emacs/blobdiff - lisp/progmodes/cc-cmds.el
Merge multi-tty branch
[gnu-emacs] / lisp / progmodes / cc-cmds.el
index dfe34be8e66b938c5feb75cf65ad0d851ab5e51d..48fa7d99f5a792b66720d6671a2c921a1efdafa5 100644 (file)
@@ -1,9 +1,12 @@
 ;;; cc-cmds.el --- user level commands for CC Mode
 
-;; Copyright (C) 1985,87,92,93,94,95,96,97,98 Free Softare Foundation, Inc.
+;; Copyright (C) 1985, 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+;;   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+;;   Free Software Foundation, Inc.
 
-;; Authors:    1998 Barry A. Warsaw and Martin Stjernholm
-;;             1992-1997 Barry A. Warsaw
+;; Authors:    2003- Alan Mackenzie
+;;             1998- Martin Stjernholm
+;;             1992-1999 Barry A. Warsaw
 ;;             1987 Dave Detlefs and Stewart Clamen
 ;;             1985 Richard M. Stallman
 ;; Maintainer: bug-cc-mode@gnu.org
@@ -15,7 +18,7 @@
 
 ;; GNU Emacs is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
+;; the Free Software Foundation; either version 3, or (at your option)
 ;; any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
 ;; 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,
-;; Boston, MA 02111-1307, USA.
+;; along with this program; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
+;;; Commentary:
+
+;;; Code:
 
-\f
 (eval-when-compile
-  (require 'cc-defs))
-
-(defun c-calculate-state (arg prevstate)
-  ;; Calculate the new state of PREVSTATE, t or nil, based on arg. If
-  ;; arg is nil or zero, toggle the state. If arg is negative, turn
-  ;; the state off, and if arg is positive, turn the state on
-  (if (or (not arg)
-         (zerop (setq arg (prefix-numeric-value arg))))
-      (not prevstate)
-    (> arg 0)))
-
-;; Auto-newline and hungry-delete
-(defun c-toggle-auto-state (arg)
+  (let ((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-bytecomp" nil t)))
+
+(cc-require 'cc-defs)
+(cc-require 'cc-vars)
+(cc-require 'cc-engine)
+
+;; Silence the compiler.
+(cc-bytecomp-defun delete-forward-p)   ; XEmacs
+(cc-bytecomp-defvar filladapt-mode)    ; c-fill-paragraph contains a kludge
+                                       ; which looks at this.
+(cc-bytecomp-defun c-forward-subword)
+(cc-bytecomp-defun c-backward-subword)
+\f
+;; Indentation / Display syntax functions
+(defvar c-fix-backslashes t)
+
+(defun c-indent-line (&optional syntax quiet ignore-point-pos)
+  "Indent the current line according to the syntactic context,
+if `c-syntactic-indentation' is non-nil.  Optional SYNTAX is the
+syntactic information for the current line.  Be silent about syntactic
+errors if the optional argument QUIET is non-nil, even if
+`c-report-syntactic-errors' is non-nil.  Normally the position of
+point is used to decide where the old indentation is on a lines that
+is otherwise empty \(ignoring any line continuation backslash), but
+that's not done if IGNORE-POINT-POS is non-nil.  Returns the amount of
+indentation change \(in columns)."
+
+  (let ((line-cont-backslash (save-excursion
+                              (end-of-line)
+                              (eq (char-before) ?\\)))
+       (c-fix-backslashes c-fix-backslashes)
+       bs-col
+       shift-amt)
+    (when (and (not ignore-point-pos)
+              (save-excursion
+                (beginning-of-line)
+                (looking-at (if line-cont-backslash
+                                ;; Don't use "\\s " - ^L doesn't count as WS
+                                ;; here
+                                "\\([ \t]*\\)\\\\$"
+                              "\\([ \t]*\\)$")))
+              (<= (point) (match-end 1)))
+      ;; Delete all whitespace after point if there's only whitespace
+      ;; on the line, so that any code that does back-to-indentation
+      ;; or similar gets the current column in this case.  If this
+      ;; removes a line continuation backslash it'll be restored
+      ;; at the end.
+      (unless c-auto-align-backslashes
+       ;; Should try to keep the backslash alignment
+       ;; in this case.
+       (save-excursion
+         (goto-char (match-end 0))
+         (setq bs-col (1- (current-column)))))
+      (delete-region (point) (match-end 0))
+      (setq c-fix-backslashes t))
+    (if c-syntactic-indentation
+       (setq c-parsing-error
+             (or (let ((c-parsing-error nil)
+                       (c-syntactic-context
+                        (or syntax
+                            (and (boundp 'c-syntactic-context)
+                                 c-syntactic-context))))
+                   (c-save-buffer-state (indent)
+                     (unless c-syntactic-context
+                       (setq c-syntactic-context (c-guess-basic-syntax)))
+                     (setq indent (c-get-syntactic-indentation
+                                   c-syntactic-context))
+                     (and (not (c-echo-parsing-error quiet))
+                          c-echo-syntactic-information-p
+                          (message "syntax: %s, indent: %d"
+                                   c-syntactic-context indent))
+                     (setq shift-amt (- indent (current-indentation))))
+                   (c-shift-line-indentation shift-amt)
+                   (run-hooks 'c-special-indent-hook)
+                   c-parsing-error)
+                 c-parsing-error))
+      (let ((indent 0))
+       (save-excursion
+         (while (and (= (forward-line -1) 0)
+                     (if (looking-at "\\s *\\\\?$")
+                         t
+                       (setq indent (current-indentation))
+                       nil))))
+       (setq shift-amt (- indent (current-indentation)))
+       (c-shift-line-indentation shift-amt)))
+    (when (and c-fix-backslashes line-cont-backslash)
+      (if bs-col
+         (save-excursion
+           (indent-to bs-col)
+           (insert ?\\))
+       (when c-auto-align-backslashes
+         ;; Realign the line continuation backslash.
+         (c-backslash-region (point) (point) nil t))))
+    shift-amt))
+
+(defun c-newline-and-indent (&optional newline-arg)
+  "Insert a newline and indent the new line.
+This function fixes line continuation backslashes if inside a macro,
+and takes care to set the indentation before calling
+`indent-according-to-mode', so that lineup functions like
+`c-lineup-dont-change' works better."
+
+  ;; TODO: Backslashes before eol in comments and literals aren't
+  ;; kept intact.
+  (let ((c-macro-start (c-query-macro-start))
+       ;; Avoid calling c-backslash-region from c-indent-line if it's
+       ;; called during the newline call, which can happen due to
+       ;; c-electric-continued-statement, for example.  We also don't
+       ;; want any backslash alignment from indent-according-to-mode.
+       (c-fix-backslashes nil)
+       has-backslash insert-backslash
+       start col)
+    (save-excursion
+      (beginning-of-line)
+      (setq start (point))
+      (while (and (looking-at "[ \t]*\\\\?$")
+                 (= (forward-line -1) 0)))
+      (setq col (current-indentation)))
+    (when c-macro-start
+      (if (and (eolp) (eq (char-before) ?\\))
+         (setq insert-backslash t
+               has-backslash t)
+       (setq has-backslash (eq (char-before (c-point 'eol)) ?\\))))
+    (newline newline-arg)
+    (indent-to col)
+    (when c-macro-start
+      (if insert-backslash
+         (progn
+           ;; The backslash stayed on the previous line.  Insert one
+           ;; before calling c-backslash-region, so that
+           ;; bs-col-after-end in it works better.  Fixup the
+           ;; backslashes on the newly inserted line.
+           (insert ?\\)
+           (backward-char)
+           (c-backslash-region (point) (point) nil t))
+       ;; The backslash moved to the new line, if there was any.  Let
+       ;; c-backslash-region fix a backslash on the previous line,
+       ;; and the one that might be on the new line.
+       ;; c-auto-align-backslashes is intentionally ignored here;
+       ;; maybe the moved backslash should be left alone if it's set,
+       ;; but we fix both lines on the grounds that the old backslash
+       ;; has been moved anyway and is now in a different context.
+       (c-backslash-region start (if has-backslash (point) start) nil t)))
+    (when c-syntactic-indentation
+      ;; Reindent syntactically.  The indentation done above is not
+      ;; wasted, since c-indent-line might look at the current
+      ;; indentation.
+      (let ((c-syntactic-context (c-save-buffer-state nil
+                                  (c-guess-basic-syntax))))
+       ;; We temporarily insert another line break, so that the
+       ;; lineup functions will see the line as empty.  That makes
+       ;; e.g. c-lineup-cpp-define more intuitive since it then
+       ;; proceeds to the preceding line in this case.
+       (insert ?\n)
+       (delete-horizontal-space)
+       (setq start (- (point-max) (point)))
+       (unwind-protect
+           (progn
+             (backward-char)
+             (indent-according-to-mode))
+         (goto-char (- (point-max) start))
+         (delete-char -1)))
+      (when has-backslash
+       ;; Must align the backslash again after reindentation.  The
+       ;; c-backslash-region call above can't be optimized to ignore
+       ;; this line, since it then won't align correctly with the
+       ;; lines below if the first line in the macro is broken.
+       (c-backslash-region (point) (point) nil t)))))
+
+(defun c-show-syntactic-information (arg)
+  "Show syntactic information for current line.
+With universal argument, inserts the analysis as a comment on that line."
+  (interactive "P")
+  (let* ((c-parsing-error nil)
+        (syntax (if (boundp 'c-syntactic-context)
+                    ;; Use `c-syntactic-context' in the same way as
+                    ;; `c-indent-line', to be consistent.
+                    c-syntactic-context
+                  (c-save-buffer-state nil
+                    (c-guess-basic-syntax)))))
+    (if (not (consp arg))
+       (let (elem pos ols)
+         (message "Syntactic analysis: %s" syntax)
+         (unwind-protect
+             (progn
+               (while syntax
+                 (setq elem (pop syntax))
+                 (when (setq pos (c-langelem-pos elem))
+                   (push (c-put-overlay pos (1+ pos)
+                                        'face 'highlight)
+                         ols))
+                 (when (setq pos (c-langelem-2nd-pos elem))
+                   (push (c-put-overlay pos (1+ pos)
+                                        'face 'secondary-selection)
+                         ols)))
+               (sit-for 10))
+           (while ols
+             (c-delete-overlay (pop ols)))))
+      (indent-for-comment)
+      (insert-and-inherit (format "%s" syntax))
+      ))
+  (c-keep-region-active))
+
+(defun c-syntactic-information-on-region (from to)
+  "Insert a comment with the syntactic analysis on every line in the region."
+  (interactive "*r")
+  (save-excursion
+    (save-restriction
+      (narrow-to-region from to)
+      (goto-char (point-min))
+      (while (not (eobp))
+       (c-show-syntactic-information '(0))
+       (forward-line)))))
+
+\f
+;; Minor mode functions.
+(defun c-update-modeline ()
+  (let ((fmt (format "/%s%s%s%s"
+                    (if c-electric-flag "l" "")
+                    (if (and c-electric-flag c-auto-newline)
+                        "a" "")
+                    (if c-hungry-delete-key "h" "")
+                    (if (and
+                         ;; cc-subword might not be loaded.
+                         (boundp 'c-subword-mode)
+                         (symbol-value 'c-subword-mode))
+                        "w"
+                      "")))
+       (bare-mode-name (if (string-match "\\(^[^/]*\\)/" mode-name)
+                           (substring mode-name (match-beginning 1) (match-end 1))
+                         mode-name)))
+;;     (setq c-submode-indicators
+;;       (if (> (length fmt) 1)
+;;           fmt))
+    (setq mode-name
+         (if (> (length fmt) 1)
+             (concat bare-mode-name fmt)
+       bare-mode-name))
+    (force-mode-line-update)))
+
+(defun c-toggle-syntactic-indentation (&optional arg)
+  "Toggle syntactic indentation.
+Optional numeric ARG, if supplied, turns on syntactic indentation when
+positive, turns it off when negative, and just toggles it when zero or
+left out.
+
+When syntactic indentation is turned on (the default), the indentation
+functions and the electric keys indent according to the syntactic
+context keys, when applicable.
+
+When it's turned off, the electric keys don't reindent, the indentation
+functions indents every new line to the same level as the previous
+nonempty line, and \\[c-indent-command] adjusts the indentation in steps
+specified by `c-basic-offset'.  The indentation style has no effect in
+this mode, nor any of the indentation associated variables,
+e.g. `c-special-indent-hook'.
+
+This command sets the variable `c-syntactic-indentation'."
+  (interactive "P")
+  (setq c-syntactic-indentation
+       (c-calculate-state arg c-syntactic-indentation))
+  (c-keep-region-active))
+
+(defun c-toggle-auto-newline (&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
-inserted after special characters such as brace, comma, semi-colon,
-and colon."
+Turning on auto-newline automatically enables electric indentation.
+
+When the auto-newline feature is enabled (indicated by \"/la\" on the
+modeline after the mode name) newlines are automatically inserted
+after special characters such as brace, comma, semi-colon, and colon."
   (interactive "P")
-  (setq c-auto-newline (c-calculate-state arg c-auto-newline))
+  (setq c-auto-newline
+       (c-calculate-state arg (and c-auto-newline c-electric-flag)))
+  (if c-auto-newline (setq c-electric-flag t))
   (c-update-modeline)
   (c-keep-region-active))
 
-(defun c-toggle-hungry-state (arg)
+(defalias 'c-toggle-auto-state 'c-toggle-auto-newline)
+(make-obsolete 'c-toggle-auto-state 'c-toggle-auto-newline)
+
+(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
-gobbles all preceding whitespace in one fell swoop."
+When the hungry-delete-key feature is enabled (indicated by \"/h\" on
+the modeline after the mode name) the delete key gobbles all preceding
+whitespace in one fell swoop."
   (interactive "P")
   (setq c-hungry-delete-key (c-calculate-state arg c-hungry-delete-key))
   (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."
+See `c-toggle-auto-newline' and `c-toggle-hungry-state' for details."
   (interactive "P")
   (setq c-auto-newline (c-calculate-state arg c-auto-newline))
   (setq c-hungry-delete-key (c-calculate-state arg c-hungry-delete-key))
   (c-update-modeline)
   (c-keep-region-active))
 
+(defun c-toggle-electric-state (&optional arg)
+  "Toggle the electric indentation feature.
+Optional numeric ARG, if supplied, turns on electric indentation when
+positive, turns it off when negative, and just toggles it when zero or
+left out."
+  (interactive "P")
+  (setq c-electric-flag (c-calculate-state arg c-electric-flag))
+  (c-update-modeline)
+  (c-keep-region-active))
+
 \f
 ;; Electric keys
 
-;; Note: In XEmacs 20.3 the Delete and BackSpace keysyms have been
-;; separated and "\177" is no longer an alias for both keys.  Also,
-;; the variable delete-key-deletes-forward controls in which direction
-;; the Delete keysym deletes characters.  The functions
-;; c-electric-delete and c-electric-backspace attempt to deal with
-;; this new functionality.  For Emacs 19 and XEmacs 19 backwards
-;; compatibility, the old behavior has moved to c-electric-backspace
-;; and c-backspace-function.
-
 (defun c-electric-backspace (arg)
-  "Deletes preceding character or whitespace.
-If `c-hungry-delete-key' is non-nil, as evidenced by the \"/h\" or
-\"/ah\" string on the mode line, then all preceding whitespace is
-consumed.  If however an ARG is supplied, or `c-hungry-delete-key' is
-nil, or point is inside a literal then the function in the variable
-`c-backspace-function' is called.
-
-See also \\[c-electric-delete]."
+  "Delete the preceding character or whitespace.
+If `c-hungry-delete-key' is non-nil (indicated by \"/h\" on the mode
+line) then all preceding whitespace is consumed.  If however a prefix
+argument is supplied, or `c-hungry-delete-key' is nil, or point is
+inside a literal then the function in the variable
+`c-backspace-function' is called."
   (interactive "*P")
-  (if (or (not c-hungry-delete-key)
-         arg
-         (c-in-literal))
+  (if (c-save-buffer-state ()
+       (or (not c-hungry-delete-key)
+           arg
+           (c-in-literal)))
       (funcall c-backspace-function (prefix-numeric-value arg))
-    (let ((here (point)))
-      (skip-chars-backward " \t\n")
-      (if (/= (point) here)
-         (delete-region (point) here)
-       (funcall c-backspace-function 1)
-       ))))
+    (c-hungry-delete-backwards)))
 
+(defun c-hungry-delete-backwards ()
+  "Delete the preceding character or all preceding whitespace
+back to the previous non-whitespace character.
+See also \\[c-hungry-delete-forward]."
+  (interactive)
+  (let ((here (point)))
+    (c-skip-ws-backward)
+    (if (/= (point) here)
+       (delete-region (point) here)
+      (funcall c-backspace-function 1))))
+
+(defalias 'c-hungry-backspace 'c-hungry-delete-backwards)
+
+(defun c-electric-delete-forward (arg)
+  "Delete the following character or whitespace.
+If `c-hungry-delete-key' is non-nil (indicated by \"/h\" on the mode
+line) then all following whitespace is consumed.  If however a prefix
+argument is supplied, or `c-hungry-delete-key' is nil, or point is
+inside a literal then the function in the variable `c-delete-function'
+is called."
+  (interactive "*P")
+  (if (c-save-buffer-state ()
+       (or (not c-hungry-delete-key)
+           arg
+           (c-in-literal)))
+      (funcall c-delete-function (prefix-numeric-value arg))
+    (c-hungry-delete-forward)))
+
+(defun c-hungry-delete-forward ()
+  "Delete the following character or all following whitespace
+up to the next non-whitespace character.
+See also \\[c-hungry-delete-backwards]."
+  (interactive)
+  (let ((here (point)))
+    (c-skip-ws-forward)
+    (if (/= (point) here)
+       (delete-region (point) here)
+      (funcall c-delete-function 1))))
+
+;; This function is only used in XEmacs.
 (defun c-electric-delete (arg)
   "Deletes preceding or following character or whitespace.
+This function either deletes forward as `c-electric-delete-forward' or
+backward as `c-electric-backspace', depending on the configuration: If
+the function `delete-forward-p' is defined and returns non-nil, it
+deletes forward.  Otherwise it deletes backward.
 
-The behavior of this function depends on the variable
-`delete-key-deletes-forward'.  If this variable is nil (or does not
-exist, as in older Emacsen), then this function behaves identical to
-\\[c-electric-backspace].
-
-If `delete-key-deletes-forward' is non-nil and is supported in your
-Emacs, then deletion occurs in the forward direction.  So if
-`c-hungry-delete-key' is non-nil, as evidenced by the \"/h\" or
-\"/ah\" string on the mode line, then all following whitespace is
-consumed.  If however an ARG is supplied, or `c-hungry-delete-key' is
-nil, or point is inside a literal then the function in the variable
-`c-delete-function' is called."
+Note: This is the way in XEmacs to choose the correct action for the
+\[delete] key, whichever key that means.  Other flavors don't use this
+function to control that."
   (interactive "*P")
-  (if (or (and (fboundp 'delete-forward-p) ;XEmacs 21
-              (delete-forward-p))
-         (and (boundp 'delete-key-deletes-forward) ;XEmacs 20
-              delete-key-deletes-forward))
-      (if (or (not c-hungry-delete-key)
-             arg
-             (c-in-literal))
-         (funcall c-delete-function (prefix-numeric-value arg))
-       (let ((here (point)))
-         (skip-chars-forward " \t\n")
-         (if (/= (point) here)
-             (delete-region (point) here)
-           (funcall c-delete-function 1))))
-    ;; act just like c-electric-backspace
+  (if (and (fboundp 'delete-forward-p)
+          (delete-forward-p))
+      (c-electric-delete-forward arg)
     (c-electric-backspace arg)))
 
+;; This function is only used in XEmacs.
+(defun c-hungry-delete ()
+  "Delete a non-whitespace char, or all whitespace up to the next non-whitespace char.
+The direction of deletion depends on the configuration: If the
+function `delete-forward-p' is defined and returns non-nil, it deletes
+forward using `c-hungry-delete-forward'.  Otherwise it deletes
+backward using `c-hungry-backspace'.
+
+Note: This is the way in XEmacs to choose the correct action for the
+\[delete] key, whichever key that means.  Other flavors don't use this
+function to control that."
+  (interactive)
+  (if (and (fboundp 'delete-forward-p)
+          (delete-forward-p))
+      (c-hungry-delete-forward)
+    (c-hungry-delete-backwards)))
+
 (defun c-electric-pound (arg)
-  "Electric pound (`#') insertion.
-Inserts a `#' character specially depending on the variable
-`c-electric-pound-behavior'.  If a numeric ARG is supplied, or if
-point is inside a literal, nothing special happens."
+  "Insert a \"#\".
+If `c-electric-flag' is set, handle it specially according to the variable
+`c-electric-pound-behavior'.  If a numeric ARG is supplied, or if point is
+inside a literal or a macro, nothing special happens."
   (interactive "*P")
-  (if (or arg
-         (not (memq 'alignleft c-electric-pound-behavior))
-         (save-excursion (skip-chars-backward " \t") (not (bolp)))
-         (c-in-literal))
+  (if (c-save-buffer-state ()
+       (or arg
+           (not c-electric-flag)
+           (not (memq 'alignleft c-electric-pound-behavior))
+           (save-excursion
+             (skip-chars-backward " \t")
+             (not (bolp)))
+           (save-excursion
+             (and (= (forward-line -1) 0)
+                  (progn (end-of-line)
+                         (eq (char-before) ?\\))))
+           (c-in-literal)))
       ;; do nothing special
       (self-insert-command (prefix-numeric-value arg))
     ;; place the pound character at the left edge
@@ -165,756 +478,2118 @@ point is inside a literal, nothing special happens."
          (bolp (bolp)))
       (beginning-of-line)
       (delete-horizontal-space)
-      (insert-char last-command-char 1)
+      (insert last-command-char)
       (and (not bolp)
           (goto-char (- (point-max) pos)))
       )))
 
+(defun c-point-syntax ()
+  ;; Return the syntactic context of the construct at point.  (This is NOT
+  ;; nec. the same as the s.c. of the line point is on).  N.B. This won't work
+  ;; between the `#' of a cpp thing and what follows (see c-opt-cpp-prefix).
+  (c-save-buffer-state (;; shut this up too
+       (c-echo-syntactic-information-p nil)
+       syntax)
+    (c-tentative-buffer-changes
+      ;; insert a newline to isolate the construct at point for syntactic
+      ;; analysis.
+      (insert-char ?\n 1)
+      ;; In AWK (etc.) or in a macro, make sure this CR hasn't changed
+      ;; the syntax.  (There might already be an escaped NL there.)
+      (when (or (c-at-vsemi-p (1- (point)))
+               (let ((pt (point)))
+                 (save-excursion
+                   (backward-char)
+                   (and (c-beginning-of-macro)
+                        (progn (c-end-of-macro)
+                               (< (point) pt))))))
+       (backward-char)
+       (insert-char ?\\ 1)
+       (forward-char))
+      (let ((c-syntactic-indentation-in-macros t)
+           (c-auto-newline-analysis t))
+       ;; Turn on syntactic macro analysis to help with auto
+       ;; newlines only.
+       (setq syntax (c-guess-basic-syntax))
+       nil))
+    syntax))
+
+(defun c-brace-newlines (syntax)
+  ;; A brace stands at point.  SYNTAX is the syntactic context of this brace
+  ;; (not necessarily the same as the S.C. of the line it is on).  Return
+  ;; NEWLINES, the list containing some combination of the symbols `before'
+  ;; and `after' saying where newlines should be inserted.
+  (c-save-buffer-state
+      ((syms
+       ;; This is the list of brace syntactic symbols that can hang.
+       ;; If any new ones are added to c-offsets-alist, they should be
+       ;; added here as well.
+       '(class-open class-close defun-open defun-close
+                    inline-open inline-close
+                    brace-list-open brace-list-close
+                    brace-list-intro brace-entry-open
+                    block-open block-close
+                    substatement-open statement-case-open
+                    extern-lang-open extern-lang-close
+                    namespace-open namespace-close
+                    module-open module-close
+                    composition-open composition-close
+                    inexpr-class-open inexpr-class-close
+                    ;; `statement-cont' is here for the case with a brace
+                    ;; list opener inside a statement.  C.f. CASE B.2 in
+                    ;; `c-guess-continued-construct'.
+                    statement-cont))
+       ;; shut this up too
+       (c-echo-syntactic-information-p nil)
+       symb-newlines)               ; e.g. (substatement-open . (after))
+
+    (setq symb-newlines
+         ;; Do not try to insert newlines around a special
+         ;; (Pike-style) brace list.
+         (if (and c-special-brace-lists
+                  (save-excursion
+                    (c-safe (if (= (char-before) ?{)
+                                (forward-char -1)
+                              (c-forward-sexp -1))
+                            (c-looking-at-special-brace-list))))
+             nil
+           ;; Seek the matching entry in c-hanging-braces-alist.
+           (or (c-lookup-lists
+                syms
+                ;; Substitute inexpr-class and class-open or
+                ;; class-close with inexpr-class-open or
+                ;; inexpr-class-close.
+                (if (assq 'inexpr-class syntax)
+                    (cond ((assq 'class-open syntax)
+                           '((inexpr-class-open)))
+                          ((assq 'class-close syntax)
+                           '((inexpr-class-close)))
+                          (t syntax))
+                  syntax)
+                c-hanging-braces-alist)
+               '(ignore before after)))) ; Default, when not in c-h-b-l.
+
+    ;; If syntax is a function symbol, then call it using the
+    ;; defined semantics.
+    (if (and (not (consp (cdr symb-newlines)))
+            (functionp (cdr symb-newlines)))
+       (let ((c-syntactic-context syntax))
+         (funcall (cdr symb-newlines)
+                  (car symb-newlines)
+                  (point)))
+      (cdr symb-newlines))))
+
+(defun c-try-one-liner ()
+  ;; Point is just after a newly inserted }.  If the non-whitespace
+  ;; content of the braces is a single line of code, compact the whole
+  ;; construct to a single line, if this line isn't too long.  The Right
+  ;; Thing is done with comments.
+  ;;
+  ;; Point will be left after the }, regardless of whether the clean-up is
+  ;; done.  Return NON-NIL if the clean-up happened, NIL if it didn't.
+
+  (let ((here (point))
+       (pos (- (point-max) (point)))
+       mbeg1 mend1 mbeg4 mend4
+       eol-col cmnt-pos cmnt-col cmnt-gap)
+
+    (when
+       (save-excursion
+         (save-restriction
+           ;; Avoid backtracking over a very large block.  The one we
+           ;; deal with here can never be more than three lines.
+           (narrow-to-region (save-excursion
+                               (forward-line -2)
+                               (point))
+                             (point))
+           (and (c-safe (c-backward-sexp))
+                (progn
+                  (forward-char)
+                  (narrow-to-region (point) (1- here)) ; innards of {.}
+                  (looking-at
+                   (cc-eval-when-compile
+                     (concat
+                      "\\("            ; (match-beginning 1)
+                      "[ \t]*\\([\r\n][ \t]*\\)?" ; WS with opt. NL
+                      "\\)"            ; (match-end 1)
+                      "[^ \t\r\n]+\\([ \t]+[^ \t\r\n]+\\)*" ; non-WS
+                      "\\("            ; (match-beginning 4)
+                      "[ \t]*\\([\r\n][ \t]*\\)?" ; WS with opt. NL
+                      "\\)\\'")))))))  ; (match-end 4) at EOB.
+
+      (if (c-tentative-buffer-changes
+           (setq mbeg1 (match-beginning 1) mend1 (match-end 1)
+                 mbeg4 (match-beginning 4) mend4 (match-end 4))
+           (backward-char)             ; back over the `}'
+           (save-excursion
+             (setq cmnt-pos (and (c-backward-single-comment)
+                                 (- (point) (- mend1 mbeg1)))))
+           (delete-region mbeg4 mend4)
+           (delete-region mbeg1 mend1)
+           (setq eol-col (save-excursion (end-of-line) (current-column)))
+
+           ;; Necessary to put the closing brace before any line
+           ;; oriented comment to keep it syntactically significant.
+           ;; This isn't necessary for block comments, but the result
+           ;; looks nicer anyway.
+           (when cmnt-pos
+             (delete-char 1)           ; the `}' has blundered into a comment
+             (goto-char cmnt-pos)
+             (setq cmnt-col (1+ (current-column)))
+             (setq cmnt-pos (1+ cmnt-pos)) ; we're inserting a `}'
+             (c-skip-ws-backward)
+             (insert-char ?\} 1)       ; reinsert the `}' before the comment.
+             (setq cmnt-gap (- cmnt-col (current-column)))
+             (when (zerop cmnt-gap)
+               (insert-char ?\  1)     ; Put a space before a bare comment.
+               (setq cmnt-gap 1)))
+
+           (or (null c-max-one-liner-length)
+               (zerop c-max-one-liner-length)
+               (<= eol-col c-max-one-liner-length)
+               ;; Can we trim space before comment to make the line fit?
+               (and cmnt-gap
+                    (< (- eol-col cmnt-gap) c-max-one-liner-length)
+                    (progn (goto-char cmnt-pos)
+                           (backward-delete-char-untabify
+                            (- eol-col c-max-one-liner-length))
+                           t))))
+         (goto-char (- (point-max) pos))))))
+
 (defun c-electric-brace (arg)
   "Insert a brace.
 
-If the auto-newline feature is turned on, as evidenced by the \"/a\"
-or \"/ah\" string on the mode line, newlines are inserted before and
-after braces based on the value of `c-hanging-braces-alist'.
+If `c-electric-flag' is non-nil, the brace is not inside a literal and a
+numeric ARG hasn't been supplied, the command performs several electric
+actions:
 
-Also, the line is re-indented unless a numeric ARG is supplied, there
-are non-whitespace characters present on the line after the brace, or
-the brace is inserted inside a literal.
+\(a) If the auto-newline feature is turned on (indicated by \"/la\" on
+the mode line) newlines are inserted before and after the brace as
+directed by the settings in `c-hanging-braces-alist'.
+
+\(b) Any auto-newlines are indented.  The original line is also
+reindented unless `c-syntactic-indentation' is nil.
+
+\(c) If auto-newline is turned on, various newline cleanups based on the
+settings of `c-cleanup-list' are done."
 
-This function does various newline cleanups based on the value of
-`c-cleanup-list'."
   (interactive "*P")
-  (let* ((c-state-cache (c-parse-state))
-        (safepos (c-safe-position (point) c-state-cache))
-        (literal (c-in-literal safepos)))
-    ;; if we're in a literal, or we're not at the end of the line, or
-    ;; a numeric arg is provided, or auto-newlining is turned off,
-    ;; then just insert the character.
-    (if (or literal
-           arg
-           (not (looking-at "[ \t]*$")))
-       (self-insert-command (prefix-numeric-value arg))
-      (let* ((syms
-             ;; This is the list of brace syntactic symbols that can
-             ;; hang.  If any new ones are added to c-offsets-alist,
-             ;; they should be added here as well.
-             '(class-open class-close defun-open defun-close
-               inline-open inline-close
-               brace-list-open brace-list-close
-               brace-list-intro brace-entry-open
-               block-open block-close
-               substatement-open statement-case-open
-               extern-lang-open extern-lang-close
-               namespace-open namespace-close
-               inexpr-class-open inexpr-class-close
-               ))
-           ;; we want to inhibit blinking the paren since this will
-           ;; be most disruptive. we'll blink it ourselves later on
-           (old-blink-paren blink-paren-function)
-           blink-paren-function
-           (insertion-point (point))
-           delete-temp-newline
-           (preserve-p (and (not (bobp))
-                            (eq ?\  (char-syntax (char-before)))))
-           ;; shut this up too
-           (c-echo-syntactic-information-p nil)
-           (syntax (progn
-                     ;; only insert a newline if there is
-                     ;; non-whitespace behind us
-                     (if (save-excursion
-                           (skip-chars-backward " \t")
-                           (not (bolp)))
-                         (progn (newline)
-                                (setq delete-temp-newline t)))
-                     (self-insert-command (prefix-numeric-value arg))
-                     ;; state cache doesn't change
-                     (c-guess-basic-syntax)))
-           (newlines (and
-                      c-auto-newline
-                      (or (c-lookup-lists
-                           syms
-                           ;; Substitute inexpr-class and class-open
-                           ;; or class-close with inexpr-class-open
-                           ;; or inexpr-class-close.
-                           (if (assq 'inexpr-class syntax)
-                               (cond ((assq 'class-open syntax)
-                                      '((inexpr-class-open)))
-                                     ((assq 'class-close syntax)
-                                      '((inexpr-class-close)))
-                                     (t syntax))
-                             syntax)
-                           c-hanging-braces-alist)
-                          '(ignore before after)))))
-       ;; 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)
-                            (c-forward-sexp -1))
-                          (c-looking-at-special-brace-list))))
-           (setq newlines nil))
-       ;; If syntax is a function symbol, then call it using the
-       ;; defined semantics.
-       (if (and (not (consp (cdr newlines)))
-                (functionp (cdr newlines)))
-           (let ((c-syntactic-context syntax))
-             (setq newlines
-                   (funcall (cdr newlines) (car newlines) insertion-point))))
-       ;; does a newline go before the open brace?
-       (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)))
-                 (here (point)))
-             (forward-line -1)
-             (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
-               ;; in many cases
-               (save-excursion
-                 (save-restriction
-                   (narrow-to-region here (point))
-                   (if (and (c-safe (progn (backward-up-list -1) t))
-                            (memq (char-before) '(?\) ?}))
-                            (progn (widen)
-                                   (c-safe (progn (c-forward-sexp -1)
-                                                  t))))
-                       (setq c-state-cache
-                             (c-hack-state (point) 'open c-state-cache)))))
-               (c-indent-line))
-             (setq c-state-cache (c-adjust-state (c-point 'bol) here
-                                                 (- (point) (c-point 'bol))
-                                                 c-state-cache))
+  (let (safepos literal
+       ;; We want to inhibit blinking the paren since this would be
+       ;; most disruptive.  We'll blink it ourselves later on.
+       (old-blink-paren blink-paren-function)
+       blink-paren-function)
+
+    (c-save-buffer-state ()
+      (setq safepos (c-safe-position (point) (c-parse-state))
+           literal (c-in-literal safepos)))
+
+    ;; Insert the brace.  Note that expand-abbrev might reindent
+    ;; the line here if there's a preceding "else" or something.
+    (self-insert-command (prefix-numeric-value arg))
+
+    (when (and c-electric-flag (not literal) (not arg))
+      (if (not (looking-at "[ \t]*\\\\?$"))
+         (if c-syntactic-indentation
+             (indent-according-to-mode))
+
+       (let ( ;; shut this up too
+             (c-echo-syntactic-information-p nil)
+             newlines
+             ln-syntax br-syntax syntax) ; Syntactic context of the original line,
+                       ; of the brace itself, of the line the brace ends up on.
+         (c-save-buffer-state ((c-syntactic-indentation-in-macros t)
+                               (c-auto-newline-analysis t))
+           (setq ln-syntax (c-guess-basic-syntax)))
+         (if c-syntactic-indentation
+             (c-indent-line ln-syntax))
+
+         (when c-auto-newline
+           (backward-char)
+           (setq br-syntax (c-point-syntax)
+                 newlines (c-brace-newlines br-syntax))
+
+           ;; Insert the BEFORE newline, if wanted, and reindent the newline.
+           (if (and (memq 'before newlines)
+                    (> (current-column) (current-indentation)))
+               (if c-syntactic-indentation
+                   ;; Only a plain newline for now - it's indented
+                   ;; after the cleanups when the line has its final
+                   ;; appearance.
+                   (newline)
+                 (c-newline-and-indent)))
+           (forward-char)
+
+           ;; `syntax' is the syntactic context of the line which ends up
+           ;; with the brace on it.
+           (setq syntax (if (memq 'before newlines) br-syntax ln-syntax))
+
+           ;; Do all appropriate clean ups
+           (let ((here (point))
+                 (pos (- (point-max) (point)))
+                 mbeg mend
+                 )
+
+             ;; `}': clean up empty defun braces
+             (when (c-save-buffer-state ()
+                     (and (memq 'empty-defun-braces c-cleanup-list)
+                          (eq last-command-char ?\})
+                          (c-intersect-lists '(defun-close class-close inline-close)
+                                             syntax)
+                          (progn
+                            (forward-char -1)
+                            (c-skip-ws-backward)
+                            (eq (char-before) ?\{))
+                          ;; make sure matching open brace isn't in a comment
+                          (not (c-in-literal))))
+               (delete-region (point) (1- here))
+               (setq here (- (point-max) pos)))
+             (goto-char here)
+
+             ;; `}': compact to a one-liner defun?
+             (save-match-data
+               (when
+                   (and (eq last-command-char ?\})
+                        (memq 'one-liner-defun c-cleanup-list)
+                        (c-intersect-lists '(defun-close) syntax)
+                        (c-try-one-liner))
+                 (setq here (- (point-max) pos))))
+
+             ;; `{': clean up brace-else-brace and brace-elseif-brace
+             (when (eq last-command-char ?\{)
+               (cond
+                ((and (memq 'brace-else-brace c-cleanup-list)
+                      (re-search-backward
+                       (concat "}"
+                               "\\([ \t\n]\\|\\\\\n\\)*"
+                               "else"
+                               "\\([ \t\n]\\|\\\\\n\\)*"
+                               "{"
+                               "\\=")
+                       nil t))
+                 (delete-region (match-beginning 0) (match-end 0))
+                 (insert-and-inherit "} else {"))
+                ((and (memq 'brace-elseif-brace c-cleanup-list)
+                      (progn
+                        (goto-char (1- here))
+                        (setq mend (point))
+                        (c-skip-ws-backward)
+                        (setq mbeg (point))
+                        (eq (char-before) ?\)))
+                      (zerop (c-save-buffer-state nil (c-backward-token-2 1 t)))
+                      (eq (char-after) ?\()
+                     ; (progn
+                       ; (setq tmp (point))
+                        (re-search-backward
+                         (concat "}"
+                                 "\\([ \t\n]\\|\\\\\n\\)*"
+                                 "else"
+                                 "\\([ \t\n]\\|\\\\\n\\)+"
+                                 "if"
+                                 "\\([ \t\n]\\|\\\\\n\\)*"
+                                 "\\=")
+                         nil t);)
+                      ;(eq (match-end 0) tmp);
+                        )
+                 (delete-region mbeg mend)
+                 (goto-char mbeg)
+                 (insert ?\ ))))
+
              (goto-char (- (point-max) pos))
-             ;; if the buffer has changed due to the indentation, we
-             ;; need to recalculate syntax for the current line, but
-             ;; we won't need to update the state cache.
-             (if (/= (point) here)
-                 (setq syntax (c-guess-basic-syntax))))
-         ;; must remove the newline we just stuck in (if we really did it)
-         (and delete-temp-newline
-              (save-excursion
-                ;; if there is whitespace before point, then preserve
-                ;; at least one space.
-                (delete-indentation)
-                (just-one-space)
-                (if (not preserve-p)
-                    (delete-char -1))))
-         ;; since we're hanging the brace, we need to recalculate
-         ;; syntax.  Update the state to accurately reflect the
-         ;; beginning of the line.  We punt if we cross any open or
-         ;; closed parens because its just too hard to modify the
-         ;; known state.  This limitation will be fixed in v5.
-         (save-excursion
-           (let ((bol (c-point 'bol)))
-             (if (zerop (car (parse-partial-sexp bol (1- (point)))))
-                 (setq c-state-cache (c-whack-state bol c-state-cache)
-                       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)
-                     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))
-                                             c-state-cache)))
-       ;; Do all appropriate clean ups
-       (let ((here (point))
-             (pos (- (point-max) (point)))
-             mbeg mend)
-         ;; clean up empty defun braces
-         (if (and c-auto-newline
-                  (memq 'empty-defun-braces c-cleanup-list)
-                  (eq last-command-char ?\})
-                  (c-intersect-lists '(defun-close class-close inline-close)
-                                     syntax)
-                  (progn
-                    (forward-char -1)
-                    (skip-chars-backward " \t\n")
-                    (eq (char-before) ?\{))
-                  ;; make sure matching open brace isn't in a comment
-                  (not (c-in-literal)))
-             (delete-region (point) (1- here)))
-         ;; clean up brace-else-brace
-         (if (and c-auto-newline
-                  (memq 'brace-else-brace c-cleanup-list)
-                  (eq last-command-char ?\{)
-                  (re-search-backward "}[ \t\n]*else[ \t\n]*{" nil t)
-                  (progn
-                    (setq mbeg (match-beginning 0)
-                          mend (match-end 0))
-                    (= mend here))
-                  (not (c-in-literal)))
-             (progn
-               (delete-region mbeg mend)
-               (insert "} else {")))
-         (goto-char (- (point-max) pos))
-         )
-       ;; does a newline go after the brace?
-       (if (memq 'after newlines)
-           (progn
-             (newline)
-             ;; update on c-state-cache
-             (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))))
-       ;; blink the paren
-       (and (eq last-command-char ?\})
-            old-blink-paren
-            (save-excursion
-              (c-backward-syntactic-ws safepos)
-              (funcall old-blink-paren)))
-       ))))
+
+             ;; Indent the line after the cleanups since it might
+             ;; very well indent differently due to them, e.g. if
+             ;; c-indent-one-line-block is used together with the
+             ;; one-liner-defun cleanup.
+             (when c-syntactic-indentation
+               (c-indent-line)))
+
+           ;; does a newline go after the brace?
+           (if (memq 'after newlines)
+               (c-newline-and-indent))
+           ))))
+
+    ;; blink the paren
+    (and (eq last-command-char ?\})
+        (not executing-kbd-macro)
+        old-blink-paren
+        (save-excursion
+          (c-save-buffer-state nil
+            (c-backward-syntactic-ws safepos))
+          (funcall old-blink-paren)))))
 
 (defun c-electric-slash (arg)
   "Insert a slash character.
 
+If the slash is inserted immediately after the comment prefix in a c-style
+comment, the comment might get closed by removing whitespace and possibly
+inserting a \"*\".  See the variable `c-cleanup-list'.
+
 Indent the line as a comment, if:
 
-  1. The slash is second of a `//' line oriented comment introducing
+  1. The slash is second of a \"//\" line oriented comment introducing
      token and we are on a comment-only-line, or
 
-  2. The slash is part of a `*/' token that closes a block oriented
+  2. The slash is part of a \"*/\" token that closes a block oriented
      comment.
 
-If numeric ARG is supplied or point is inside a literal, indentation
+If a numeric ARG is supplied, point is inside a literal, or
+`c-syntactic-indentation' is nil or `c-electric-flag' is nil, indentation
 is inhibited."
   (interactive "*P")
-  (let* ((ch (char-before))
-        (indentp (and (not arg)
+  (let ((literal (c-save-buffer-state () (c-in-literal)))
+       indentp
+       ;; shut this up
+       (c-echo-syntactic-information-p nil))
+
+    ;; comment-close-slash cleanup?  This DOESN'T need `c-electric-flag' or
+    ;; `c-syntactic-indentation' set.
+    (when (and (not arg)
+              (eq literal 'c)
+              (memq 'comment-close-slash c-cleanup-list)
+              (eq last-command-char ?/)
+              (looking-at (concat "[ \t]*\\("
+                                  (regexp-quote comment-end) "\\)?$"))
+       ; (eq c-block-comment-ender "*/") ; C-style comments ALWAYS end in */
+              (save-excursion
+                (save-restriction
+                  (narrow-to-region (point-min) (point))
+                  (back-to-indentation)
+                  (looking-at (concat c-current-comment-prefix "[ \t]*$")))))
+      (delete-region (progn (forward-line 0) (point))
+                    (progn (end-of-line) (point)))
+      (insert-char ?* 1)) ; the / comes later. ; Do I need a t (retain sticky properties) here?
+
+    (setq indentp (and (not arg)
+                      c-syntactic-indentation
+                      c-electric-flag
                       (eq last-command-char ?/)
-                      (or (and (eq ch ?/)
-                               (not (c-in-literal)))
-                          (and (eq ch ?*)
-                               (c-in-literal)))
-                      ))
-        ;; shut this up
-        (c-echo-syntactic-information-p nil))
+                      (eq (char-before) (if literal ?* ?/))))
     (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.
-If the star is the second character of a C style comment introducing
-construct, and we are on a comment-only-line, indent line as comment.
-If numeric ARG is supplied or point is inside a literal, indentation
-is inhibited."
+If `c-electric-flag' and `c-syntactic-indentation' are both non-nil, and
+the star is the second character of a C style comment starter on a
+comment-only-line, indent the line as a comment.  If a numeric ARG is
+supplied, point is inside a literal, or `c-syntactic-indentation' is nil,
+this indentation is inhibited."
+
   (interactive "*P")
   (self-insert-command (prefix-numeric-value arg))
-  ;; if we are in a literal, or if arg is given do not re-indent the
+  ;; if we are in a literal, or if arg is given do not reindent the
   ;; current line, unless this star introduces a comment-only line.
-  (if (and (not arg)
-          (memq (c-in-literal) '(c))
-          (eq (char-before) ?*)
-          (save-excursion
-            (forward-char -1)
-            (skip-chars-backward "*")
-            (if (eq (char-before) ?/)
-                (forward-char -1))
-            (skip-chars-backward " \t")
-            (bolp)))
-      ;; shut this up
-      (let (c-echo-syntactic-information-p)
-       (c-indent-line))
+  (if (c-save-buffer-state ()
+       (and c-syntactic-indentation
+            c-electric-flag
+            (not arg)
+            (eq (c-in-literal) 'c)
+            (eq (char-before) ?*)
+            (save-excursion
+              (forward-char -1)
+              (skip-chars-backward "*")
+              (if (eq (char-before) ?/)
+                  (forward-char -1))
+              (skip-chars-backward " \t")
+              (bolp))))
+      (let (c-echo-syntactic-information-p) ; shut this up
+       (indent-according-to-mode))
     ))
 
 (defun c-electric-semi&comma (arg)
   "Insert a comma or semicolon.
-When the auto-newline feature is turned on, as evidenced by the \"/a\"
-or \"/ah\" string on the mode line, a newline might be inserted.  See
-the variable `c-hanging-semi&comma-criteria' for how newline insertion
-is determined.
 
-When semicolon is inserted, the line is re-indented unless a numeric
-arg is supplied, point is inside a literal, or there are
-non-whitespace characters on the line following the semicolon.
+If `c-electric-flag' is non-nil, point isn't inside a literal and a
+numeric ARG hasn't been supplied, the command performs several electric
+actions:
+
+\(a) When the auto-newline feature is turned on (indicated by \"/la\" on
+the mode line) a newline might be inserted.  See the variable
+`c-hanging-semi&comma-criteria' for how newline insertion is determined.
 
-Based on the value of `c-cleanup-list', this function cleans up commas
-following brace lists and semicolons following defuns."
+\(b) Any auto-newlines are indented.  The original line is also
+reindented unless `c-syntactic-indentation' is nil.
+
+\(c) If auto-newline is turned on, a comma following a brace list or a
+semicolon following a defun might be cleaned up, depending on the
+settings of `c-cleanup-list'."
   (interactive "*P")
-  (let* ((lim (c-most-enclosing-brace (c-parse-state)))
-        (literal (c-in-literal lim))
+  (let* (lim literal c-syntactic-context
         (here (point))
         ;; shut this up
         (c-echo-syntactic-information-p nil))
-    (if (or literal
-           arg
-           (not (looking-at "[ \t]*$")))
-       (self-insert-command (prefix-numeric-value arg))
-      ;; do some special stuff with the character
-      (self-insert-command (prefix-numeric-value arg))
-      ;; do all cleanups and newline insertions if c-auto-newline is
-      ;; turned on
-      (if (not c-auto-newline)
-         (c-indent-line)
-       ;; clean ups
-       (let ((pos (- (point-max) (point))))
-         (if (and (or (and
-                       (eq last-command-char ?,)
-                       (memq 'list-close-comma c-cleanup-list))
-                      (and
-                       (eq last-command-char ?\;)
-                       (memq 'defun-close-semi c-cleanup-list)))
-                  (progn
-                    (forward-char -1)
-                    (skip-chars-backward " \t\n")
-                    (eq (char-before) ?}))
-                  ;; make sure matching open brace isn't in a comment
-                  (not (c-in-literal lim)))
-             (delete-region (point) here))
-         (goto-char (- (point-max) pos)))
-       ;; re-indent line
-       (c-indent-line)
-       ;; check to see if a newline should be added
-       (let ((criteria c-hanging-semi&comma-criteria)
-             answer add-newline-p)
-         (while criteria
-           (setq answer (funcall (car criteria)))
-           ;; only nil value means continue checking
-           (if (not answer)
-               (setq criteria (cdr criteria))
-             (setq criteria nil)
-             ;; only 'stop specifically says do not add a newline
-             (setq add-newline-p (not (eq answer 'stop)))
-             ))
-         (if add-newline-p
-             (progn (newline)
-                    (c-indent-line)))
-         )))))
+
+    (c-save-buffer-state ()
+      (setq lim (c-most-enclosing-brace (c-parse-state))
+           literal (c-in-literal lim)))
+
+    (self-insert-command (prefix-numeric-value arg))
+
+    (if (and c-electric-flag (not literal) (not arg))
+       ;; do all cleanups and newline insertions if c-auto-newline is on.
+       (if (or (not c-auto-newline)
+               (not (looking-at "[ \t]*\\\\?$")))
+           (if c-syntactic-indentation
+               (c-indent-line))
+         ;; clean ups: list-close-comma or defun-close-semi
+         (let ((pos (- (point-max) (point))))
+           (if (c-save-buffer-state ()
+                 (and (or (and
+                           (eq last-command-char ?,)
+                           (memq 'list-close-comma c-cleanup-list))
+                          (and
+                           (eq last-command-char ?\;)
+                           (memq 'defun-close-semi c-cleanup-list)))
+                      (progn
+                        (forward-char -1)
+                        (c-skip-ws-backward)
+                        (eq (char-before) ?}))
+                      ;; make sure matching open brace isn't in a comment
+                      (not (c-in-literal lim))))
+               (delete-region (point) here))
+           (goto-char (- (point-max) pos)))
+         ;; reindent line
+         (when c-syntactic-indentation
+           (setq c-syntactic-context (c-guess-basic-syntax))
+           (c-indent-line c-syntactic-context))
+         ;; check to see if a newline should be added
+         (let ((criteria c-hanging-semi&comma-criteria)
+               answer add-newline-p)
+           (while criteria
+             (setq answer (funcall (car criteria)))
+             ;; only nil value means continue checking
+             (if (not answer)
+                 (setq criteria (cdr criteria))
+               (setq criteria nil)
+               ;; only 'stop specifically says do not add a newline
+               (setq add-newline-p (not (eq answer 'stop)))
+               ))
+           (if add-newline-p
+               (c-newline-and-indent))
+           )))))
 
 (defun c-electric-colon (arg)
   "Insert a colon.
 
-If the auto-newline feature is turned on, as evidenced by the \"/a\"
-or \"/ah\" string on the mode line, newlines are inserted before and
-after colons based on the value of `c-hanging-colons-alist'.
+If `c-electric-flag' is non-nil, the colon is not inside a literal and a
+numeric ARG hasn't been supplied, the command performs several electric
+actions:
+
+\(a) If the auto-newline feature is turned on (indicated by \"/la\" on
+the mode line) newlines are inserted before and after the colon based on
+the settings in `c-hanging-colons-alist'.
 
-Also, the line is re-indented unless a numeric ARG is supplied, there
-are non-whitespace characters present on the line after the colon, or
-the colon is inserted inside a literal.
+\(b) Any auto-newlines are indented.  The original line is also
+reindented unless `c-syntactic-indentation' is nil.
+
+\(c) If auto-newline is turned on, whitespace between two colons will be
+\"cleaned up\" leaving a scope operator, if this action is set in
+`c-cleanup-list'."
 
-This function cleans up double colon scope operators based on the
-value of `c-cleanup-list'."
   (interactive "*P")
   (let* ((bod (c-point 'bod))
-        (literal (c-in-literal bod))
-        syntax newlines is-scope-op
+        (literal (c-save-buffer-state () (c-in-literal bod)))
+        newlines is-scope-op
         ;; shut this up
         (c-echo-syntactic-information-p nil))
-    (if (or literal
-           arg
-           (not (looking-at "[ \t]*$")))
-       (self-insert-command (prefix-numeric-value arg))
-      ;; insert the colon, then do any specified cleanups
-      (self-insert-command (prefix-numeric-value arg))
-      (let ((pos (- (point-max) (point)))
-           (here (point)))
-       (if (and c-auto-newline
-                (memq 'scope-operator c-cleanup-list)
-                (eq (char-before) ?:)
-                (progn
-                  (forward-char -1)
-                  (skip-chars-backward " \t\n")
-                  (eq (char-before) ?:))
-                (not (c-in-literal))
-                (not (eq (char-after (- (point) 2)) ?:)))
-           (progn
-             (delete-region (point) (1- here))
-             (setq is-scope-op t)))
-       (goto-char (- (point-max) pos)))
-      ;; lets do some special stuff with the colon character
-      (setq syntax (c-guess-basic-syntax)
-           ;; some language elements can only be determined by
-           ;; checking the following line.  Lets first look for ones
-           ;; that can be found when looking on the line with the
-           ;; colon
-           newlines
-           (and c-auto-newline
-                (or (c-lookup-lists '(case-label label access-label)
-                                    syntax c-hanging-colons-alist)
-                    (c-lookup-lists '(member-init-intro inher-intro)
-                                    (let ((buffer-undo-list t))
-                                      (insert "\n")
-                                      (unwind-protect
-                                          (c-guess-basic-syntax)
-                                        (delete-char -1)))
-                                    c-hanging-colons-alist))))
-      ;; indent the current line
-      (c-indent-line syntax)
-      ;; 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).
-      (if (and (memq 'before newlines)
-              (not is-scope-op)
-              (save-excursion
-                (skip-chars-backward ": \t")
-                (not (bolp))))
-         (let ((pos (- (point-max) (point))))
-           (forward-char -1)
-           (newline)
-           (c-indent-line)
-           (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)))
-      )))
+    (self-insert-command (prefix-numeric-value arg))
+    ;; Any electric action?
+    (if (and c-electric-flag (not literal) (not arg))
+       ;; Unless we're at EOL, only re-indentation happens.
+       (if (not (looking-at "[ \t]*\\\\?$"))
+           (if c-syntactic-indentation
+               (indent-according-to-mode))
+
+         ;; scope-operator clean-up?
+         (let ((pos (- (point-max) (point)))
+               (here (point)))
+           (if (c-save-buffer-state () ; Why do we need this? [ACM, 2003-03-12]
+                 (and c-auto-newline
+                      (memq 'scope-operator c-cleanup-list)
+                      (eq (char-before) ?:)
+                      (progn
+                        (forward-char -1)
+                        (c-skip-ws-backward)
+                        (eq (char-before) ?:))
+                      (not (c-in-literal))
+                      (not (eq (char-after (- (point) 2)) ?:))))
+               (progn
+                 (delete-region (point) (1- here))
+                 (setq is-scope-op t)))
+           (goto-char (- (point-max) pos)))
+
+         ;; indent the current line if it's done syntactically.
+         (if c-syntactic-indentation
+             ;; Cannot use the same syntax analysis as we find below,
+             ;; since that's made with c-syntactic-indentation-in-macros
+             ;; always set to t.
+             (indent-according-to-mode))
+
+         ;; Calculate where, if anywhere, we want newlines.
+         (c-save-buffer-state
+             ((c-syntactic-indentation-in-macros t)
+              (c-auto-newline-analysis t)
+              ;; Turn on syntactic macro analysis to help with auto newlines
+              ;; only.
+              (syntax (c-guess-basic-syntax))
+              (elem syntax))
+           ;; Translate substatement-label to label for this operation.
+           (while elem
+             (if (eq (car (car elem)) 'substatement-label)
+                 (setcar (car elem) 'label))
+             (setq elem (cdr elem)))
+           ;; some language elements can only be determined by checking
+           ;; the following line.  Lets first look for ones that can be
+           ;; found when looking on the line with the colon
+           (setq newlines
+                 (and c-auto-newline
+                      (or (c-lookup-lists '(case-label label access-label)
+                                          syntax c-hanging-colons-alist)
+                          (c-lookup-lists '(member-init-intro inher-intro)
+                                          (progn
+                                            (insert ?\n)
+                                            (unwind-protect
+                                                (c-guess-basic-syntax)
+                                              (delete-char -1)))
+                                          c-hanging-colons-alist)))))
+         ;; 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).
+         (if (and (memq 'before newlines)
+                  (not is-scope-op)
+                  (save-excursion
+                    (skip-chars-backward ": \t")
+                    (not (bolp))))
+             (let ((pos (- (point-max) (point))))
+               (forward-char -1)
+               (c-newline-and-indent)
+               (goto-char (- (point-max) pos))))
+         ;; does a newline go after the colon?
+         (if (and (memq 'after (cdr-safe newlines))
+                  (not is-scope-op))
+             (c-newline-and-indent))
+         ))))
 
 (defun c-electric-lt-gt (arg)
-  "Insert a less-than, or greater-than character.
-The line will be re-indented if the character inserted is the second
-of a C++ style stream operator and the buffer is in C++ mode.
-Exceptions are when a numeric argument is supplied, or point is inside
-a literal, in which case the line will not be re-indented."
+  "Insert a \"<\" or \">\" character.
+If the current language uses angle bracket parens (e.g. template
+arguments in C++), try to find out if the inserted character is a
+paren and give it paren syntax if appropriate.
+
+If `c-electric-flag' and `c-syntactic-indentation' are both non-nil, the
+line will be reindented if the inserted character is a paren or if it
+finishes a C++ style stream operator in C++ mode.  Exceptions are when a
+numeric argument is supplied, or the point is inside a literal."
+
   (interactive "*P")
-  (let ((indentp (and (not arg)
-                     (eq (char-before) last-command-char)
-                     (not (c-in-literal))))
-       ;; shut this up
-       (c-echo-syntactic-information-p nil))
+  (let ((c-echo-syntactic-information-p nil)
+       final-pos close-paren-inserted)
+
     (self-insert-command (prefix-numeric-value arg))
-    (if indentp
-       (c-indent-line))))
+    (setq final-pos (point))
+
+    (c-save-buffer-state (c-parse-and-markup-<>-arglists
+                         c-restricted-<>-arglists
+                         <-pos)
+
+      (when c-recognize-<>-arglists
+       (if (eq last-command-char ?<)
+           (when (and (progn
+                        (backward-char)
+                        (= (point)
+                           (progn
+                             (c-beginning-of-current-token)
+                             (point))))
+                      (progn
+                        (c-backward-token-2)
+                        (looking-at c-opt-<>-sexp-key)))
+             (c-mark-<-as-paren (1- final-pos)))
+
+         ;; It's a ">".  Check if there's an earlier "<" which either has
+         ;; open paren syntax already or that can be recognized as an arglist
+         ;; together with this ">".  Note that this won't work in cases like
+         ;; "template <x, a < b, y>" but they ought to be rare.
+
+         (save-restriction
+           ;; Narrow to avoid that `c-forward-<>-arglist' below searches past
+           ;; our position.
+           (narrow-to-region (point-min) final-pos)
+
+           (while (and
+                   (progn
+                     (goto-char final-pos)
+                     (c-syntactic-skip-backward "^<;}" nil t)
+                     (eq (char-before) ?<))
+                   (progn
+                     (backward-char)
+                     ;; If the "<" already got open paren syntax we know we
+                     ;; have the matching closer.  Handle it and exit the
+                     ;; loop.
+                     (if (looking-at "\\s\(")
+                         (progn
+                           (c-mark->-as-paren (1- final-pos))
+                           (setq close-paren-inserted t)
+                           nil)
+                       t))
+
+                   (progn
+                     (setq <-pos (point))
+                     (c-backward-syntactic-ws)
+                     (c-simple-skip-symbol-backward))
+                   (or (looking-at c-opt-<>-sexp-key)
+                       (not (looking-at c-keywords-regexp)))
+
+                   (let ((c-parse-and-markup-<>-arglists t)
+                         c-restricted-<>-arglists
+                         (containing-sexp
+                          (c-most-enclosing-brace (c-parse-state))))
+                     (when (and containing-sexp
+                                (progn (goto-char containing-sexp)
+                                       (eq (char-after) ?\())
+                                (not (eq (get-text-property (point) 'c-type)
+                                         'c-decl-arg-start)))
+                       (setq c-restricted-<>-arglists t))
+                     (goto-char <-pos)
+                     (c-forward-<>-arglist nil))
+
+                   ;; Loop here if the "<" we found above belongs to a nested
+                   ;; angle bracket sexp.  When we start over we'll find the
+                   ;; previous or surrounding sexp.
+                   (if (< (point) final-pos)
+                       t
+                     (setq close-paren-inserted t)
+                     nil)))))))
+    (goto-char final-pos)
+
+    ;; Indent the line if appropriate.
+    (when (and c-electric-flag c-syntactic-indentation)
+      (backward-char)
+      (when (prog1 (or (looking-at "\\s\(\\|\\s\)")
+                      (and (c-major-mode-is 'c++-mode)
+                           (progn
+                             (c-beginning-of-current-token)
+                             (looking-at "<<\\|>>"))
+                           (= (match-end 0) final-pos)))
+             (goto-char final-pos))
+       (indent-according-to-mode)))
+
+    (when (and close-paren-inserted
+              (not executing-kbd-macro)
+              blink-paren-function)
+      ;; Note: Most paren blink functions, such as the standard
+      ;; `blink-matching-open', currently doesn't handle paren chars
+      ;; marked with text properties very well.  Maybe we should avoid
+      ;; this call for the time being?
+      (funcall blink-paren-function))))
 
 (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'.
+If `c-syntactic-indentation' and `c-electric-flag' are both non-nil, the
+line is reindented unless a numeric ARG is supplied, or the parenthesis
+is inserted inside a literal.
+
+Whitespace between a function name and the parenthesis may get added or
+removed; 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 colon, or
-the colon is inserted inside a literal."
+Also, if `c-electric-flag' and `c-auto-newline' are both non-nil, some
+newline cleanups are done if appropriate; see the variable `c-cleanup-list'."
   (interactive "*P")
-  (let (;; shut this up
+  (let ((literal (c-save-buffer-state () (c-in-literal)))
+       ;; 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
-      (let* (;; We want to inhibit blinking the paren since this will
-            ;; be most disruptive.  We'll blink it ourselves
-            ;; afterwards.
-            (old-blink-paren blink-paren-function)
-            blink-paren-function)
-       (self-insert-command (prefix-numeric-value arg))
-       (c-indent-line)
-       (when c-auto-newline
-         ;; Do all appropriate clean ups
-         (let ((here (point))
-               (pos (- (point-max) (point)))
-               mbeg mend)
+    (self-insert-command (prefix-numeric-value arg))
+
+    (if (and (not arg) (not literal))
+       (let* ( ;; We want to inhibit blinking the paren since this will
+              ;; be most disruptive.  We'll blink it ourselves
+              ;; afterwards.
+              (old-blink-paren blink-paren-function)
+              blink-paren-function)
+         (if (and c-syntactic-indentation c-electric-flag)
+             (indent-according-to-mode))
+
+         ;; If we're at EOL, check for new-line clean-ups.
+         (when (and c-electric-flag c-auto-newline
+                    (looking-at "[ \t]*\\\\?$"))
+
            ;; clean up brace-elseif-brace
-           (if (and (memq 'brace-elseif-brace c-cleanup-list)
+           (when
+               (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 (")))
+                    (re-search-backward
+                     (concat "}"
+                             "\\([ \t\n]\\|\\\\\n\\)*"
+                             "else"
+                             "\\([ \t\n]\\|\\\\\n\\)+"
+                             "if"
+                             "\\([ \t\n]\\|\\\\\n\\)*"
+                             "("
+                             "\\=")
+                     nil t)
+                    (not  (c-save-buffer-state () (c-in-literal))))
+             (delete-region (match-beginning 0) (match-end 0))
+             (insert-and-inherit "} else if ("))
+
            ;; clean up brace-catch-brace
-           (if (and (memq 'brace-catch-brace c-cleanup-list)
+           (when
+               (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))
-           ))
-       (funcall old-blink-paren)))))
+                    (re-search-backward
+                     (concat "}"
+                             "\\([ \t\n]\\|\\\\\n\\)*"
+                             "catch"
+                             "\\([ \t\n]\\|\\\\\n\\)*"
+                             "("
+                             "\\=")
+                     nil t)
+                    (not  (c-save-buffer-state () (c-in-literal))))
+             (delete-region (match-beginning 0) (match-end 0))
+             (insert-and-inherit "} catch (")))
+
+         ;; Check for clean-ups at function calls.  These two DON'T need
+         ;; `c-electric-flag' or `c-syntactic-indentation' set.
+         ;; Point is currently just after the inserted paren.
+         (let (beg (end (1- (point))))
+           (cond
+
+            ;; space-before-funcall clean-up?
+            ((and (memq 'space-before-funcall c-cleanup-list)
+                  (eq last-command-char ?\()
+                  (save-excursion
+                    (backward-char)
+                    (skip-chars-backward " \t")
+                    (setq beg (point))
+                    (and (c-save-buffer-state () (c-on-identifier))
+                          ;; Don't add a space into #define FOO()....
+                          (not (and (c-beginning-of-macro)
+                                    (c-forward-over-cpp-define-id)
+                                    (eq (point) beg))))))
+             (save-excursion
+               (delete-region beg end)
+               (goto-char beg)
+               (insert ?\ )))
+
+            ;; compact-empty-funcall clean-up?
+                 ((c-save-buffer-state ()
+                    (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))))
+         (and (eq last-input-event ?\))
+              (not executing-kbd-macro)
+              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-electric-flag' and `c-syntactic-indentation' are both non-nil."
+  (let (;; shut this up
+       (c-echo-syntactic-information-p nil))
+    (when (c-save-buffer-state ()
+           (and c-electric-flag
+                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)))))
+      ;; Have to temporarily insert a space so that
+      ;; c-guess-basic-syntax recognizes the keyword.  Follow the
+      ;; space with a nonspace to avoid messing up any whitespace
+      ;; sensitive meddling that might be done, e.g. by
+      ;; `c-backslash-region'.
+      (insert-and-inherit " x")
+      (unwind-protect
+         (indent-according-to-mode)
+       (delete-char -2)))))
 
 \f
-;; better movement routines for ThisStyleOfVariablesCommonInCPlusPlus
-;; originally contributed by Terry_Glanfield.Southern@rxuk.xerox.com
+;; "nomenclature" functions + c-scope-operator.
 (defun c-forward-into-nomenclature (&optional arg)
-  "Move forward to end of a nomenclature section or word.
-With arg, to it arg times."
+  "Compatibility alias for `c-forward-subword'."
   (interactive "p")
-  (let ((case-fold-search nil))
-    (if (> arg 0)
-       (re-search-forward "\\W*\\([A-Z]*[a-z0-9]*\\)" (point-max) t arg)
-      (while (and (< arg 0)
-                 (re-search-backward
-                  "\\(\\(\\W\\|[a-z0-9]\\)[A-Z]+\\|\\W\\w+\\)"
-                  (point-min) 0))
-       (forward-char 1)
-       (setq arg (1+ arg)))))
-  (c-keep-region-active))
+  (require 'cc-subword)
+  (c-forward-subword arg))
+(make-obsolete 'c-forward-into-nomenclature 'c-forward-subword)
 
 (defun c-backward-into-nomenclature (&optional arg)
-  "Move backward to beginning of a nomenclature section or word.
-With optional ARG, move that many times.  If ARG is negative, move
-forward."
+  "Compatibility alias for `c-backward-subword'."
   (interactive "p")
-  (c-forward-into-nomenclature (- arg))
-  (c-keep-region-active))
+  (require 'cc-subword)
+  (c-backward-subword arg))
+(make-obsolete 'c-backward-into-nomenclature 'c-backward-subword)
 
 (defun c-scope-operator ()
   "Insert a double colon scope operator at point.
 No indentation or other \"electric\" behavior is performed."
   (interactive "*")
-  (insert "::"))
+  (insert-and-inherit "::"))
+
+\f
+;; Movement (etc.) by defuns.
+(defun c-in-function-trailer-p (&optional lim)
+  ;; Return non-nil if point is between the closing brace and the semicolon of
+  ;; a brace construct which needs a semicolon, e.g. within the "variables"
+  ;; portion of a declaration like "struct foo {...} bar ;".
+  ;;
+  ;; Return the position of the main declaration.  Otherwise, return nil.
+  ;; Point is assumed to be at the top level and outside of any macro or
+  ;; literal.
+  ;;
+  ;; If LIM is non-nil, it is the bound on a the backward search for the
+  ;; beginning of the declaration.
+  ;;
+  ;; This function might do hidden buffer changes.
+  (and c-opt-block-decls-with-vars-key
+       (save-excursion
+        (c-syntactic-skip-backward "^;}" lim)
+        (let ((eo-block (point))
+              bod)
+          (and (eq (char-before) ?\})
+               (eq (car (c-beginning-of-decl-1 lim)) 'previous)
+               (setq bod (point))
+               ;; Look for struct or union or ...  If we find one, it might
+               ;; be the return type of a function, or the like.  Exclude
+               ;; this case.
+               (c-syntactic-re-search-forward
+                (concat "[;=\(\[{]\\|\\("
+                        c-opt-block-decls-with-vars-key
+                        "\\)")
+                eo-block t t t)
+               (match-beginning 1)     ; Is there a "struct" etc., somewhere?
+               (not (eq (char-before) ?_))
+               (c-syntactic-re-search-forward "[;=\(\[{]" eo-block t t t)
+               (eq (char-before) ?\{)
+               bod)))))
+
+(defun c-where-wrt-brace-construct ()
+  ;; Determine where we are with respect to functions (or other brace
+  ;; constructs, included in the term "function" in the rest of this comment).
+  ;; Point is assumed to be outside any macro or literal.
+  ;; This is used by c-\(begining\|end\)-of-defun.
+  ;;
+  ;; Return one of these symbols:
+  ;; at-header       : we're at the start of a function's header.
+  ;; in-header       : we're inside a function's header, this extending right
+  ;;                   up to the brace.  This bit includes any k&r declarations.
+  ;; in-block        : we're inside a function's brace block.
+  ;; in-trailer      : we're in the area between the "}" and ";" of something
+  ;;                  like "struct foo {...} bar, baz;".
+  ;; at-function-end : we're just after the closing brace (or semicolon) that
+  ;;                   terminates the function.
+  ;; outwith-function: we're not at or in any function.  Being inside a
+  ;;                   non-brace construct also counts as 'outwith-function'.
+  ;;
+  ;; This function might do hidden buffer changes.
+  (save-excursion
+    (let* (kluge-start
+          decl-result brace-decl-p
+          (start (point))
+          (paren-state (c-parse-state))
+          (least-enclosing (c-least-enclosing-brace paren-state)))
+
+      (cond
+       ((and least-enclosing
+            (eq (char-after least-enclosing) ?\{))
+       'in-block)
+       ((c-in-function-trailer-p)
+       'in-trailer)
+       ((and (not least-enclosing)
+            (consp paren-state)
+            (consp (car paren-state))
+            (eq start (cdar paren-state)))
+       'at-function-end)
+       (t
+       ;; Find the start of the current declaration.  NOTE: If we're in the
+       ;; variables after a "struct/eval" type block, we don't get to the
+       ;; real declaration here - we detect and correct for this later.
+
+       ;;If we're in the parameters' parens, move back out of them.
+       (if least-enclosing (goto-char least-enclosing))
+       ;; Kluge so that c-beginning-of-decl-1 won't go back if we're already
+       ;; at a declaration.
+       (if (or (and (eolp) (not (eobp))) ; EOL is matched by "\\s>"
+               (not (looking-at
+"\\([;#]\\|\\'\\|\\s(\\|\\s)\\|\\s\"\\|\\s\\\\|\\s$\\|\\s<\\|\\s>\\|\\s!\\)")))
+           (forward-char))
+       (setq kluge-start (point))
+       (setq decl-result
+             (car (c-beginning-of-decl-1
+                   ;; NOTE: If we're in a K&R region, this might be the start
+                   ;; of a parameter declaration, not the actual function.
+                   (and least-enclosing ; LIMIT for c-b-of-decl-1
+                        (c-safe-position least-enclosing paren-state)))))
+
+       ;; Has the declaration we've gone back to got braces?
+       (setq brace-decl-p
+             (save-excursion
+                   (and (c-syntactic-re-search-forward "[;{]" nil t t)
+                        (or (eq (char-before) ?\{)
+                            (and c-recognize-knr-p
+                                 ;; Might have stopped on the
+                                 ;; ';' in a K&R argdecl.  In
+                                 ;; that case the declaration
+                                 ;; should contain a block.
+                                 (c-in-knr-argdecl))))))
+
+       (cond
+        ((= (point) kluge-start)       ; might be BOB or unbalanced parens.
+         'outwith-function)
+        ((eq decl-result 'same)
+         (if brace-decl-p
+             (if (eq (point) start)
+                 'at-header
+               'in-header)
+           'outwith-function))
+        ((eq decl-result 'previous)
+         (if (and (not brace-decl-p)
+                  (c-in-function-trailer-p))
+             'at-function-end
+           'outwith-function))
+        (t (error
+            "c-where-wrt-brace-construct: c-beginning-of-decl-1 returned %s"
+            decl-result))))))))
+
+(defun c-backward-to-nth-BOF-{ (n where)
+  ;; Skip to the opening brace of the Nth function before point.  If
+  ;; point is inside a function, this counts as the first.  Point must be
+  ;; outside any comment/string or macro.
+  ;;
+  ;; N must be strictly positive.
+  ;; WHERE describes the position of point, one of the symbols `at-header',
+  ;; `in-header', `in-block', `in-trailer', `at-function-end',
+  ;; `outwith-function' as returned by c-where-wrt-brace-construct.
+  ;;
+  ;; If we run out of functions, leave point at BOB.  Return zero on success,
+  ;; otherwise the number of {s still to go.
+  ;;
+  ;; This function may do hidden buffer changes
+  (cond
+   ;; What we do to go back the first defun depends on where we start.
+   ((bobp))
+   ((eq where 'in-block)
+    (goto-char (c-least-enclosing-brace (c-parse-state)))
+    (setq n (1- n)))
+   ((eq where 'in-header)
+    (c-syntactic-re-search-forward "{")
+    (backward-char)
+    (setq n (1- n)))
+   ((memq where '(at-header outwith-function at-function-end in-trailer))
+    (c-syntactic-skip-backward "^}")
+    (when (eq (char-before) ?\})
+      (backward-sexp)
+      (setq n (1- n))))
+   (t (error "Unknown `where' %s in c-backward-to-nth-EOF-{" where)))
+
+   ;; Each time round the loop, go back to a "{" at the outermost level.
+  (while (and (> n 0) (not (bobp)))
+    (c-parse-state)                   ; This call speeds up the following one
+                                       ; by a factor of ~6.  Hmmm.  2006/4/5.
+    (c-syntactic-skip-backward "^}")
+    (when (eq (char-before) ?\})
+      (backward-sexp)
+      (setq n (1- n))))
+   n)
 
 (defun c-beginning-of-defun (&optional arg)
   "Move backward to the beginning of a defun.
-With argument, do it that many times.  Negative arg -N
-means move forward to Nth following beginning of defun.
-Returns t unless search stops due to beginning or end of buffer.
+Every top level declaration that contains a brace paren block is
+considered to be a defun.
+
+With a positive argument, move backward that many defuns.  A negative
+argument -N means move forward to the Nth following beginning.  Return
+t unless search stops due to beginning or end of buffer.
 
 Unlike the built-in `beginning-of-defun' this tries to be smarter
 about finding the char with open-parenthesis syntax that starts the
 defun."
+
   (interactive "p")
-  (if (< arg 0)
-      (c-end-of-defun (- arg))
-    (while (> arg 0)
-      (let ((state (nreverse (c-parse-state)))
-           prevbod bod)
-       (while (and state (not bod))
-         (setq bod (car state)
-               state (cdr state))
-         (if (consp bod)
-             (setq prevbod (car bod)
-                   bod nil)))
-       (cond
-        (bod (goto-char bod))
-        (prevbod (goto-char prevbod))
-        (t (goto-char (c-point 'bod)))))
-      (setq arg (1- arg))))
-  (c-keep-region-active))
+  (or arg (setq arg 1))
+
+  (c-save-buffer-state
+      (beginning-of-defun-function end-of-defun-function
+       (start (point))
+       where paren-state pos)
+
+    ;; Move back out of any macro/comment/string we happen to be in.
+    (c-beginning-of-macro)
+    (setq pos (c-literal-limits))
+    (if pos (goto-char (car pos)))
+
+    (setq where (c-where-wrt-brace-construct))
+
+    (if (< arg 0)
+       ;; Move forward to the closing brace of a function.
+       (progn
+         (if (memq where '(at-function-end outwith-function))
+             (setq arg (1+ arg)))
+         (if (< arg 0)
+             (setq arg (c-forward-to-nth-EOF-} (- arg) where)))
+         ;; Move forward to the next opening brace....
+         (when (and (= arg 0)
+                    (c-syntactic-re-search-forward "{" nil 'eob))
+           (backward-char)
+           ;; ... and backward to the function header.
+           (c-beginning-of-decl-1)
+           t))
+
+      ;; Move backward to the opening brace of a function.
+      (when (and (> arg 0)
+                (eq (setq arg (c-backward-to-nth-BOF-{ arg where)) 0))
+
+       ;; Go backward to this function's header.
+       (c-beginning-of-decl-1)
+
+       (setq pos (point))
+       ;; We're now there, modulo comments and whitespace.
+       ;; Try to be line oriented; position point at the closest
+       ;; preceding boi that isn't inside a comment, but if we hit
+       ;; the previous declaration then we use the current point
+       ;; instead.
+       (while (and (/= (point) (c-point 'boi))
+                   (c-backward-single-comment)))
+       (if (/= (point) (c-point 'boi))
+           (goto-char pos)))
+
+      (c-keep-region-active)
+      (= arg 0))))
+
+(defun c-forward-to-nth-EOF-} (n where)
+  ;; Skip to the closing brace of the Nth function after point.  If
+  ;; point is inside a function, this counts as the first.  Point must be
+  ;; outside any comment/string or macro.
+  ;;
+  ;; N must be strictly positive.
+  ;; WHERE describes the position of point, one of the symbols `at-header',
+  ;; `in-header', `in-block', `in-trailer', `at-function-end',
+  ;; `outwith-function' as returned by c-where-wrt-brace-construct.
+  ;;
+  ;; If we run out of functions, leave point at EOB.  Return zero on success,
+  ;; otherwise the number of }s still to go.
+  ;;
+  ;; This function may do hidden buffer changes.
+
+  (cond
+  ;; What we do to go forward over the first defun depends on where we
+  ;; start.  We go to the closing brace of that defun, even when we go
+  ;; backwards to it (in a "struct foo {...} bar ;").
+   ((eobp))
+   ((eq where 'in-block)
+    (goto-char (c-least-enclosing-brace (c-parse-state)))
+    (forward-sexp)
+    (setq n (1- n)))
+   ((eq where 'in-trailer)
+    (c-syntactic-skip-backward "^}")
+    (setq n (1- n)))
+   ((memq where '(at-function-end outwith-function at-header in-header))
+    (when (c-syntactic-re-search-forward "{" nil 'eob)
+      (backward-char)
+      (forward-sexp)
+      (setq n (1- n))))
+   (t (error "c-forward-to-nth-EOF-}: `where' is %s" where)))
+
+  ;; Each time round the loop, go forward to a "}" at the outermost level.
+  (while (and (> n 0) (not (eobp)))
+                                       ;(c-parse-state)        ; This call speeds up the following one by a factor
+                                       ; of ~6.  Hmmm.  2006/4/5.
+    (when (c-syntactic-re-search-forward "{" nil 'eob)
+      (backward-char)
+      (forward-sexp))
+    (setq n (1- n)))
+  n)
 
 (defun c-end-of-defun (&optional arg)
-  "Move forward to next end of defun.  With argument, do it that many times.
-Negative argument -N means move back to Nth preceding end of defun.
+  "Move forward to the end of a top level declaration.
+With argument, do it that many times.  Negative argument -N means move
+back to Nth preceding end.  Returns t unless search stops due to
+beginning or end of buffer.
 
 An end of a defun occurs right after the close-parenthesis that matches
 the open-parenthesis that starts a defun; see `beginning-of-defun'."
   (interactive "p")
-  (if (not arg)
-      (setq arg 1))
-  (if (< arg 0)
-      (c-beginning-of-defun (- arg))
-    (while (> arg 0)
-      ;; skip down into the next defun-block
-      (while (and (c-safe (down-list 1) t)
-                 (not (eq (char-before) ?{)))
-       (forward-char -1)
-       (c-forward-sexp))
-      (c-beginning-of-defun 1)
-      (c-forward-sexp 1)
-      (setq arg (1- arg)))
-    (forward-line 1))
-  (c-keep-region-active))
+  (or arg (setq arg 1))
+
+  (c-save-buffer-state
+      (beginning-of-defun-function end-of-defun-function
+       (start (point))
+       where paren-state pos)
+
+    ;; Move back out of any macro/comment/string we happen to be in.
+    (c-beginning-of-macro)
+    (setq pos (c-literal-limits))
+    (if pos (goto-char (car pos)))
+
+    (setq where (c-where-wrt-brace-construct))
+
+    (if (< arg 0)
+       ;; Move backwards to the } of a function
+       (progn
+         (if (memq where '(at-header outwith-function))
+             (setq arg (1+ arg)))
+         (if (< arg 0)
+             (setq arg (c-backward-to-nth-BOF-{ (- arg) where)))
+         (if (= arg 0)
+             (c-syntactic-skip-backward "^}")))
+
+      ;; Move forward to the } of a function
+      (if (> arg 0)
+         (setq arg (c-forward-to-nth-EOF-} arg where))))
+
+    ;; Do we need to move forward from the brace to the semicolon?
+    (when (eq arg 0)
+      (if (c-in-function-trailer-p)    ; after "}" of struct/enum, etc.
+         (c-syntactic-re-search-forward ";"))
+
+      (setq pos (point))
+      ;; We're there now, modulo comments and whitespace.
+      ;; Try to be line oriented; position point after the next
+      ;; newline that isn't inside a comment, but if we hit the
+      ;; next declaration then we use the current point instead.
+      (while (and (not (bolp))
+                 (not (looking-at "\\s *$"))
+                 (c-forward-single-comment)))
+      (cond ((bolp))
+           ((looking-at "\\s *$")
+            (forward-line 1))
+           (t
+            (goto-char pos))))
+
+    (c-keep-region-active)
+    (= arg 0)))
+
+(defun c-declaration-limits (near)
+  ;; Return a cons of the beginning and end positions of the current
+  ;; top level declaration or macro.  If point is not inside any then
+  ;; nil is returned, unless NEAR is non-nil in which case the closest
+  ;; following one is chosen instead (if there is any).  The end
+  ;; position is at the next line, providing there is one before the
+  ;; declaration.
+  ;;
+  ;; This function might do hidden buffer changes.
+  (save-excursion
+
+    ;; Note: Some code duplication in `c-beginning-of-defun' and
+    ;; `c-end-of-defun'.
+    (catch 'exit
+      (let ((start (point))
+           (paren-state (c-parse-state))
+           lim pos end-pos)
+       (unless (c-safe
+                 (goto-char (c-least-enclosing-brace paren-state))
+                 ;; If we moved to the outermost enclosing paren then we
+                 ;; can use c-safe-position to set the limit.  Can't do
+                 ;; that otherwise since the earlier paren pair on
+                 ;; paren-state might very well be part of the
+                 ;; declaration we should go to.
+                 (setq lim (c-safe-position (point) paren-state))
+                 t)
+         ;; At top level.  Make sure we aren't inside a literal.
+         (setq pos (c-literal-limits
+                    (c-safe-position (point) paren-state)))
+         (if pos (goto-char (car pos))))
+
+       (when (c-beginning-of-macro)
+         (throw 'exit
+                (cons (point)
+                      (save-excursion
+                        (c-end-of-macro)
+                        (forward-line 1)
+                        (point)))))
+
+       (setq pos (point))
+       (when (or (eq (car (c-beginning-of-decl-1 lim)) 'previous)
+                 (= pos (point)))
+         ;; We moved back over the previous defun.  Skip to the next
+         ;; one.  Not using c-forward-syntactic-ws here since we
+         ;; should not skip a macro.  We can also be directly after
+         ;; the block in a `c-opt-block-decls-with-vars-key'
+         ;; declaration, but then we won't move significantly far
+         ;; here.
+         (goto-char pos)
+         (c-forward-comments)
+
+         (when (and near (c-beginning-of-macro))
+           (throw 'exit
+                  (cons (point)
+                        (save-excursion
+                          (c-end-of-macro)
+                          (forward-line 1)
+                          (point))))))
+
+       (if (eobp) (throw 'exit nil))
+
+       ;; Check if `c-beginning-of-decl-1' put us after the block in a
+       ;; declaration that doesn't end there.  We're searching back and
+       ;; forth over the block here, which can be expensive.
+       (setq pos (point))
+       (if (and c-opt-block-decls-with-vars-key
+                (progn
+                  (c-backward-syntactic-ws)
+                  (eq (char-before) ?}))
+                (eq (car (c-beginning-of-decl-1))
+                    'previous)
+                (save-excursion
+                  (c-end-of-decl-1)
+                  (and (> (point) pos)
+                       (setq end-pos (point)))))
+           nil
+         (goto-char pos))
+
+       (if (and (not near) (> (point) start))
+           nil
+
+         ;; Try to be line oriented; position the limits at the
+         ;; closest preceding boi, and after the next newline, that
+         ;; isn't inside a comment, but if we hit a neighboring
+         ;; declaration then we instead use the exact declaration
+         ;; limit in that direction.
+         (cons (progn
+                 (setq pos (point))
+                 (while (and (/= (point) (c-point 'boi))
+                             (c-backward-single-comment)))
+                 (if (/= (point) (c-point 'boi))
+                     pos
+                   (point)))
+               (progn
+                 (if end-pos
+                     (goto-char end-pos)
+                   (c-end-of-decl-1))
+                 (setq pos (point))
+                 (while (and (not (bolp))
+                             (not (looking-at "\\s *$"))
+                             (c-forward-single-comment)))
+                 (cond ((bolp)
+                        (point))
+                       ((looking-at "\\s *$")
+                        (forward-line 1)
+                        (point))
+                       (t
+                        pos)))))
+       ))))
+
+(defun c-mark-function ()
+  "Put mark at end of the current top-level declaration or macro, point at beginning.
+If point is not inside any then the closest following one is chosen.
+
+As opposed to \\[c-beginning-of-defun] and \\[c-end-of-defun], this
+function does not require the declaration to contain a brace block."
+  (interactive)
+
+  (let (decl-limits)
+    (c-save-buffer-state nil
+      ;; We try to be line oriented, unless there are several
+      ;; declarations on the same line.
+      (if (looking-at c-syntactic-eol)
+         (c-backward-token-2 1 nil (c-point 'bol)))
+      (setq decl-limits (c-declaration-limits t)))
+
+    (if (not decl-limits)
+       (error "Cannot find any declaration")
+      (goto-char (car decl-limits))
+      (push-mark (cdr decl-limits) nil t))))
 
 \f
+;; Movement by statements.
+(defun c-in-comment-line-prefix-p ()
+  ;; Point is within a comment.  Is it also within a comment-prefix?
+  ;; Space at BOL which precedes a comment-prefix counts as part of it.
+  ;;
+  ;; This function might do hidden buffer changes.
+  (let ((here (point)))
+    (save-excursion
+      (beginning-of-line)
+      (skip-chars-forward " \t")
+      (and (looking-at c-current-comment-prefix)
+          (/= (match-beginning 0) (match-end 0))
+          (< here (match-end 0))))))
+
+(defun c-narrow-to-comment-innards (range)
+  ;; Narrow to the "inside" of the comment (block) defined by range, as
+  ;; follows:
+  ;;
+  ;; A c-style block comment has its opening "/*" and its closing "*/" (if
+  ;; present) removed.  A c++-style line comment retains its opening "//" but
+  ;; has any final NL removed.  If POINT is currently outwith these innards,
+  ;; move it to the appropriate boundary.
+  ;;
+  ;; This narrowing simplifies the sentence movement functions, since it
+  ;; eliminates awkward things at the boundaries of the comment (block).
+  ;;
+  ;; This function might do hidden buffer changes.
+  (let* ((lit-type (c-literal-type range))
+        (beg (if (eq lit-type 'c) (+ (car range) 2) (car range)))
+        (end (if (eq lit-type 'c)
+                 (if (and (eq (char-before (cdr range)) ?/)
+                          (eq (char-before (1- (cdr range))) ?*))
+                     (- (cdr range) 2)
+                   (point-max))
+               (if (eq (cdr range) (point-max))
+                   (point-max)
+                 (- (cdr range) 1)))))
+    (if (> (point) end)
+       (goto-char end))                ; This would be done automatically by ...
+    (if (< (point) beg)
+       (goto-char beg))        ;  ... narrow-to-region but is not documented.
+    (narrow-to-region beg end)))
+
+(defun c-beginning-of-sentence-in-comment (range)
+  ;; Move backwards to the "beginning of a sentence" within the comment
+  ;; defined by RANGE, a cons of its starting and ending positions.  If we
+  ;; find a BOS, return NIL.  Otherwise, move point to just before the start
+  ;; of the comment and return T.
+  ;;
+  ;; The BOS is either text which follows a regexp match of sentence-end,
+  ;; or text which is a beginning of "paragraph".
+  ;; Comment-prefixes are treated like WS when calculating BOSes or BOPs.
+  ;;
+  ;; This code was adapted from GNU Emacs's forward-sentence in paragraphs.el.
+  ;; It is not a general function, but is intended only for calling from
+  ;; c-move-over-sentence.  Not all preconditions have been explicitly stated.
+  ;;
+  ;; This function might do hidden buffer changes.
+  (save-match-data
+    (let ((start-point (point)))
+      (save-restriction
+       (c-narrow-to-comment-innards range) ; This may move point back.
+       (let* ((here (point))
+              last
+              (here-filler        ; matches WS and comment-prefices at point.
+               (concat "\\=\\(^[ \t]*\\(" c-current-comment-prefix "\\)"
+                       "\\|[ \t\n\r\f]\\)*"))
+              (prefix-at-bol-here ; matches WS and prefix at BOL, just before point
+               (concat "^[ \t]*\\(" c-current-comment-prefix "\\)[ \t\n\r\f]*\\="))
+              ;; First, find the previous paragraph start, if any.
+              (par-beg ; point where non-WS/non-prefix text of paragraph starts.
+               (save-excursion
+                 (forward-paragraph -1) ; uses cc-mode values of
+                                       ; paragraph-\(start\|separate\)
+                 (if (> (re-search-forward here-filler nil t) here)
+                     (goto-char here))
+                 (when (>= (point) here)
+                   (forward-paragraph -2)
+                   (if (> (re-search-forward here-filler nil t) here)
+                       (goto-char here)))
+                 (point))))
+
+         ;; Now seek successively earlier sentence ends between PAR-BEG and
+         ;; HERE, until the "start of sentence" following it is earlier than
+         ;; HERE, or we hit PAR-BEG.  Beware of comment prefices!
+         (while (and (re-search-backward (c-sentence-end) par-beg 'limit)
+                     (setq last (point))
+                     (goto-char (match-end 0)) ; tentative beginning of sentence
+                     (or (>= (point) here)
+                         (and (not (bolp)) ; Found a non-blank comment-prefix?
+                              (save-excursion
+                                (if (re-search-backward prefix-at-bol-here nil t)
+                                    (/= (match-beginning 1) (match-end 1)))))
+                         (progn        ; Skip the crud to find a real b-o-s.
+                           (if (c-in-comment-line-prefix-p)
+                               (beginning-of-line))
+                           (re-search-forward here-filler) ; always succeeds.
+                           (>= (point) here))))
+           (goto-char last))
+         (re-search-forward here-filler)))
+
+      (if (< (point) start-point)
+         nil
+       (goto-char (car range))
+       t))))
+
+(defun c-end-of-sentence-in-comment (range)
+  ;; Move forward to the "end of a sentence" within the comment defined by
+  ;; RANGE, a cons of its starting and ending positions (enclosing the opening
+  ;; comment delimiter and the terminating */ or newline).  If we find an EOS,
+  ;; return NIL.  Otherwise, move point to just after the end of the comment
+  ;; and return T.
+  ;;
+  ;; The EOS is just after the non-WS part of the next match of the regexp
+  ;; sentence-end.  Typically, this is just after one of [.!?].  If there is
+  ;; no sentence-end match following point, any WS before the end of the
+  ;; comment will count as EOS, providing we're not already in it.
+  ;;
+  ;; This code was adapted from GNU Emacs's forward-sentence in paragraphs.el.
+  ;; It is not a general function, but is intended only for calling from
+  ;; c-move-over-sentence.
+  ;;
+  ;; This function might do hidden buffer changes.
+  (save-match-data
+    (let ((start-point (point))
+         ;; (lit-type (c-literal-type range))  ; Commented out, 2005/11/23, ACM
+         )
+      (save-restriction
+       (c-narrow-to-comment-innards range) ; This might move point forwards.
+       (let* ((here (point))
+              (par-end ; EOL position of last text in current/next paragraph.
+               (save-excursion
+                 ;; The cc-mode values of paragraph-\(start\|separate\), set
+                 ;; in c-setup-paragraph-variables, are used in the
+                 ;; following.
+                 (forward-paragraph 1)
+                 (if (eq (preceding-char) ?\n) (forward-char -1))
+                 (when (<= (point) here) ; can happen, e.g., when HERE is at EOL.
+                   (goto-char here)
+                   (forward-paragraph 2)
+                   (if (eq (preceding-char) ?\n) (forward-char -1)))
+                 (point)))
+
+              last
+              (prefix-at-bol-here
+               (concat "^[ \t]*\\(" c-current-comment-prefix "\\)\\=")))
+         ;; Go forward one "comment-prefix which looks like sentence-end"
+         ;; each time round the following:
+         (while (and (re-search-forward (c-sentence-end) par-end 'limit)
+                     (progn
+                       (setq last (point))
+                       (skip-chars-backward " \t\n")
+                       (or (and (not (bolp))
+                                (re-search-backward prefix-at-bol-here nil t)
+                                (/= (match-beginning 1) (match-end 1)))
+                           (<= (point) here))))
+           (goto-char last))
+
+         ;; Take special action if we're up against the end of a comment (of
+         ;; either sort): Leave point just after the last non-ws text.
+         (if (eq (point) (point-max))
+             (while (or (/= (skip-chars-backward " \t\n") 0)
+                        (and (re-search-backward prefix-at-bol-here nil t)
+                             (/= (match-beginning 1) (match-end 1))))))))
+
+      (if (> (point) start-point)
+             nil
+           (goto-char (cdr range))
+           t))))
+
+(defun c-beginning-of-sentence-in-string (range)
+  ;; Move backwards to the "beginning of a sentence" within the string defined
+  ;; by RANGE, a cons of its starting and ending positions (enclosing the
+  ;; string quotes).  If we find a BOS, return NIL.  Otherwise, move point to
+  ;; just before the start of the string and return T.
+  ;;
+  ;; The BOS is either the text which follows a regexp match of sentence-end
+  ;; or text which is a beginning of "paragraph".  For the purposes of
+  ;; determining paragraph boundaries, escaped newlines are treated as
+  ;; ordinary newlines.
+  ;;
+  ;; This code was adapted from GNU Emacs's forward-sentence in paragraphs.el.
+  ;; It is not a general function, but is intended only for calling from
+  ;; c-move-over-sentence.
+  ;;
+  ;; This function might do hidden buffer changes.
+  (save-match-data
+    (let* ((here (point)) last
+          (end (1- (cdr range)))
+          (here-filler            ; matches WS and escaped newlines at point.
+           "\\=\\([ \t\n\r\f]\\|\\\\[\n\r]\\)*")
+          ;; Enhance paragraph-start and paragraph-separate also to recognise
+          ;; blank lines terminated by escaped EOLs.  IT MAY WELL BE that
+          ;; these values should be customizable user options, or something.
+          (paragraph-start c-string-par-start)
+          (paragraph-separate c-string-par-separate)
+
+          (par-beg            ; beginning of current (or previous) paragraph.
+           (save-excursion
+             (save-restriction
+               (narrow-to-region (1+ (car range)) end)
+               (forward-paragraph -1)  ; uses above values of
+                                       ; paragraph-\(start\|separate\)
+               (if (> (re-search-forward here-filler nil t) here)
+                   (goto-char here))
+               (when (>= (point) here)
+                 (forward-paragraph -2)
+                 (if (> (re-search-forward here-filler nil t) here)
+                     (goto-char here)))
+               (point)))))
+      ;; Now see if we can find a sentence end after PAR-BEG.
+      (while (and (re-search-backward c-sentence-end-with-esc-eol par-beg 'limit)
+                 (setq last (point))
+                 (goto-char (match-end 0))
+                 (or (> (point) end)
+                     (progn
+                       (re-search-forward
+                        here-filler end t) ; always succeeds.  Use end rather
+                                       ; than here, in case point starts
+                                       ; beyond the closing quote.
+                       (>= (point) here))))
+       (goto-char last))
+      (re-search-forward here-filler here t)
+      (if (< (point) here)
+         nil
+       (goto-char (car range))
+       t))))
+
+(defun c-end-of-sentence-in-string (range)
+  ;; Move forward to the "end of a sentence" within the string defined by
+  ;; RANGE, a cons of its starting and ending positions.  If we find an EOS,
+  ;; return NIL.  Otherwise, move point to just after the end of the string
+  ;; and return T.
+  ;;
+  ;; The EOS is just after the non-WS part of the next match of the regexp
+  ;; sentence-end.  Typically, this is just after one of [.!?].  If there is
+  ;; no sentence-end match following point, any WS before the end of the
+  ;; string will count as EOS, providing we're not already in it.
+  ;;
+  ;; This code was adapted from GNU Emacs's forward-sentence in paragraphs.el.
+  ;; It is not a general function, but is intended only for calling from
+  ;; c-move-over-sentence.
+  ;;
+  ;; This function might do hidden buffer changes.
+  (save-match-data
+    (let* ((here (point))
+          last
+          ;; Enhance paragraph-start and paragraph-separate to recognise
+          ;; blank lines terminated by escaped EOLs.
+          (paragraph-start c-string-par-start)
+          (paragraph-separate c-string-par-separate)
+
+          (par-end     ; EOL position of last text in current/next paragraph.
+           (save-excursion
+             (save-restriction
+               (narrow-to-region (car range) (1- (cdr range)))
+               ;; The above values of paragraph-\(start\|separate\) are used
+               ;; in the following.
+               (forward-paragraph 1)
+               (setq last (point))
+               ;; (re-search-backward filler-here nil t) would find an empty
+               ;; string.  Therefore we simulate it by the following:
+               (while (or (/= (skip-chars-backward " \t\n\r\f") 0)
+                          (re-search-backward "\\\\\\($\\)\\=" nil t)))
+               (unless (> (point) here)
+                 (goto-char last)
+                 (forward-paragraph 1)
+                 (while (or (/= (skip-chars-backward " \t\n\r\f") 0)
+                            (re-search-backward "\\\\\\($\\)\\=" nil t))))
+               (point)))))
+      ;; Try to go forward a sentence.
+      (when (re-search-forward c-sentence-end-with-esc-eol par-end 'limit)
+       (setq last (point))
+       (while (or (/= (skip-chars-backward " \t\n") 0)
+                  (re-search-backward "\\\\\\($\\)\\=" nil t))))
+      ;; Did we move a sentence, or did we hit the end of the string?
+      (if (> (point) here)
+         nil
+       (goto-char (cdr range))
+       t))))
+
+(defun c-ascertain-preceding-literal ()
+  ;; Point is not in a literal (i.e. comment or string (include AWK regexp)).
+  ;; If a literal is the next thing (aside from whitespace) to be found before
+  ;; point, return a cons of its start.end positions (enclosing the
+  ;; delimiters).  Otherwise return NIL.
+  ;;
+  ;; This function might do hidden buffer changes.
+  (save-excursion
+    (c-collect-line-comments
+     (let ((here (point))
+          pos)
+       (if (c-backward-single-comment)
+          (cons (point) (progn (c-forward-single-comment) (point)))
+        (save-restriction
+          ;; to prevent `looking-at' seeing a " at point.
+          (narrow-to-region (point-min) here)
+          (when
+              (or
+               ;; An EOL can act as an "open string" terminator in AWK.
+               (looking-at c-ws*-string-limit-regexp)
+               (and (not (bobp))
+                    (progn (backward-char)
+                           (looking-at c-string-limit-regexp))))
+            (goto-char (match-end 0))  ; just after the string terminator.
+            (setq pos (point))
+            (c-safe (c-backward-sexp 1) ; move back over the string.
+                    (cons (point) pos)))))))))
+
+(defun c-ascertain-following-literal ()
+  ;; Point is not in a literal (i.e. comment or string (include AWK regexp)).
+  ;; If a literal is the next thing (aside from whitespace) following point,
+  ;; return a cons of its start.end positions (enclosing the delimiters).
+  ;; Otherwise return NIL.
+  ;;
+  ;; This function might do hidden buffer changes.
+  (save-excursion
+    (c-collect-line-comments
+     (let (pos)
+       (c-skip-ws-forward)
+       (if (looking-at c-string-limit-regexp) ; string-delimiter.
+          (cons (point) (or (c-safe (progn (c-forward-sexp 1) (point)))
+                            (point-max)))
+        (setq pos (point))
+        (if (c-forward-single-comment)
+            (cons pos (point))))))))
+
+(defun c-after-statement-terminator-p () ; Should we pass in LIM here?
+  ;; Does point immediately follow a statement "terminator"?  A virtual
+  ;; semicolon is regarded here as such.  So is a an opening brace ;-)
+  ;;
+  ;; This function might do hidden buffer changes.
+  (or (save-excursion
+       (backward-char)
+       (and (looking-at "[;{}]")
+            (not (and c-special-brace-lists ; Pike special brace lists.
+                      (eq (char-after) ?{)
+                      (c-looking-at-special-brace-list)))))
+      (c-at-vsemi-p)
+      ;; The following (for macros) is not strict about exactly where we are
+      ;; wrt white space at the end of the macro.  Doesn't seem to matter too
+      ;; much.  ACM 2004/3/29.
+      (let (eom)
+       (save-excursion
+         (if (c-beginning-of-macro)
+             (setq eom (progn (c-end-of-macro)
+                              (point)))))
+       (when eom
+         (save-excursion
+           (c-forward-comments)
+           (>= (point) eom))))))
+
+(defun c-back-over-illiterals (macro-start)
+  ;; Move backwards over code which isn't a literal (i.e. comment or string),
+  ;; stopping before reaching BOB or a literal or the boundary of a
+  ;; preprocessor statement or the "beginning of a statement".  MACRO-START is
+  ;; the position of the '#' beginning the current preprocessor directive, or
+  ;; NIL if we're not in such.
+  ;;
+  ;; Return a cons (A.B), where
+  ;;   A is NIL if we moved back to a BOS (and know it), T otherwise (we
+  ;;     didn't move, or we hit a literal, or we're not sure about BOS).
+  ;;   B is MACRO-BOUNDARY if we are about to cross the boundary out of or
+  ;;     into a macro, otherwise LITERAL if we've hit a literal, otherwise NIL
+  ;;
+  ;;   The total collection of returned values is as follows:
+  ;;     (nil . nil): Found a BOS whilst remaining inside the illiterals.
+  ;;     (t . literal): No BOS found: only a comment/string.  We _might_ be at
+  ;;                    a BOS - the caller must check this.
+  ;;     (nil . macro-boundary): only happens with non-nil macro-start.  We've
+  ;;                             moved and reached the opening # of the macro.
+  ;;     (t . macro-boundary): Every other circumstance in which we're at a
+  ;;                           macro-boundary.  We might be at a BOS.
+  ;;
+  ;; Point is left either at the beginning-of-statement, or at the last non-ws
+  ;; code before encountering the literal/BOB or macro-boundary.
+  ;;
+  ;; Note that this function moves within either preprocessor commands
+  ;; (macros) or normal code, but will not cross a boundary between the two,
+  ;; or between two distinct preprocessor commands.
+  ;;
+  ;; 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 at boi on a line.
+  ;;
+  ;; This function might do hidden buffer changes.
+  (save-match-data
+    (let ((here (point))
+         last) ; marks the position of non-ws code, what'll be BOS if, say, a
+                                       ; semicolon precedes it.
+      (catch 'done
+       (while t ;; We go back one "token" each iteration of the loop.
+         (setq last (point))
+         (cond
+         ;; Stop at the token after a comment.
+          ((c-backward-single-comment) ; Also functions as backwards-ws.
+           (goto-char last)
+           (throw 'done '(t . literal)))
+
+         ;; If we've gone back over a LF, we might have moved into or out of
+         ;; a preprocessor line.
+          ((and (save-excursion
+                  (beginning-of-line)
+                  (re-search-forward "\\(^\\|[^\\]\\)[\n\r]" last t))
+                (if macro-start
+                    (< (point) macro-start)
+                  (c-beginning-of-macro)))
+           (goto-char last)
+           ;; Return a car of NIL ONLY if we've hit the opening # of a macro.
+           (throw 'done (cons (or (eq (point) here)
+                                  (not macro-start))
+                              'macro-boundary)))
+
+          ;; Have we found a virtual semicolon?  If so, stop, unless the next
+          ;; statement is where we started from.
+          ((and (c-at-vsemi-p)
+                (< last here)
+                (not (memq (char-after last) '(?\) ?})))) ; we've moved back from ) or }
+           (goto-char last)
+           (throw 'done '(nil . nil)))
+
+          ;; Hit the beginning of the buffer/region?
+          ((bobp)
+           (if (/= here last)
+               (goto-char last))
+           (throw 'done '(nil . nil)))
+
+          ;; Move back a character.
+          ((progn (backward-char) nil))
+
+          ;; Stop at "{" (unless it's a PIKE special brace list.)
+          ((eq (char-after) ?\{)
+           (if (and c-special-brace-lists
+                    (c-looking-at-special-brace-list))
+               (skip-syntax-backward "w_") ; Speedup only.
+             (if (/= here last)
+                 (goto-char last))
+             (throw 'done '(nil . nil))))
+
+          ;; Have we reached the start of a macro?  This always counts as
+          ;; BOS.  (N.B. I don't think (eq (point) here) can ever be true
+          ;; here.  FIXME!!! ACM 2004/3/29)
+          ((and macro-start (eq (point) macro-start))
+           (throw 'done (cons (eq (point) here) 'macro-boundary)))
+
+          ;; Stop at token just after "}" or ";".
+          ((looking-at "[;}]")
+           ;; If we've gone back over ;, {, or }, we're done.
+           (if (or (= here last)
+                   (memq (char-after last) '(?\) ?}))) ; we've moved back from ) or }
+               (if (and (eq (char-before) ?}) ; If };, treat them as a unit.
+                        (eq (char-after) ?\;))
+                   (backward-char))
+             (goto-char last)   ; To the statement starting after the ; or }.
+             (throw 'done '(nil . nil))))
+
+          ;; Stop at the token after a string.
+          ((looking-at c-string-limit-regexp) ; Just gone back over a string terminator?
+           (goto-char last)
+           (throw 'done '(t . literal)))
+
+          ;; Nothing special: go back word characters.
+          (t (skip-syntax-backward "w_")) ; Speedup only.
+          ))))))
+
+(defun c-forward-over-illiterals (macro-end allow-early-stop)
+  ;; Move forwards over code, stopping before reaching EOB or a literal
+  ;; (i.e. a comment/string) or the boundary of a preprocessor statement or
+  ;; the "end of a statement".  MACRO-END is the position of the EOL/EOB which
+  ;; terminates the current preprocessor directive, or NIL if we're not in
+  ;; such.
+  ;;
+  ;; ALLOW-EARLY-STOP is non-nil if it is permissible to return without moving
+  ;; forward at all, should we encounter a `{'.  This is an ugly kludge, but
+  ;; seems unavoidable.  Depending on the context this function is called
+  ;; from, we _sometimes_ need to stop there.  Currently (2004/4/3),
+  ;; ALLOW-EARLY-STOP is applied only to open braces, not to virtual
+  ;; semicolons, or anything else.
+  ;;
+  ;; Return a cons (A.B), where
+  ;;   A is NIL if we moved forward to an EOS, or stay at one (when
+  ;;     ALLOW-EARLY-STOP is set), T otherwise (we hit a literal).
+  ;;   B is 'MACRO-BOUNDARY if we are about to cross the boundary out of or
+  ;;     into a macro, otherwise 'LITERAL if we've hit a literal, otherwise NIL
+  ;;
+  ;; Point is left either after the end-of-statement, or at the last non-ws
+  ;; code before encountering the literal, or the # of the preprocessor
+  ;; statement, or at EOB [or just after last non-WS stuff??].
+  ;;
+  ;; As a clarification of "after the end-of-statement", if a comment or
+  ;; whitespace follows a completed AWK statement, that statement is treated
+  ;; as ending just after the last non-ws character before the comment.
+  ;;
+  ;; Note that this function moves within either preprocessor commands
+  ;; (macros) or normal code, but not both within the same invocation.
+  ;;
+  ;; 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 with `#' at
+  ;; the boi.
+  ;;
+  ;; This function might do hidden buffer changes.
+  (let ((here (point))
+       last)
+    (catch 'done
+      (while t ;; We go one "token" forward each time round this loop.
+       (setq last (point))
+
+       ;; If we've moved forward to a virtual semicolon, we're done.
+       (if (and (> last here) ; Should we check ALLOW-EARLY-STOP, here? 2004/4/3
+                (c-at-vsemi-p))
+           (throw 'done '(nil . nil)))
+
+       (c-skip-ws-forward)
+       (cond
+        ;; Gone past the end of a macro?
+        ((and macro-end (> (point) macro-end))
+         (goto-char last)
+         (throw 'done (cons (eq (point) here) 'macro-boundary)))
+
+        ;; About to hit a comment?
+        ((save-excursion (c-forward-single-comment))
+         (goto-char last)
+         (throw 'done '(t . literal)))
+
+        ;; End of buffer?
+        ((eobp)
+         (if (/= here last)
+             (goto-char last))
+         (throw 'done '(nil . nil)))
+
+        ;; If we encounter a '{', stop just after the previous token.
+        ((and (eq (char-after) ?{)
+              (not (and c-special-brace-lists
+                        (c-looking-at-special-brace-list)))
+              (or allow-early-stop (/= here last))
+              (save-excursion  ; Is this a check that we're NOT at top level?
+;;;; NO!  This seems to check that (i) EITHER we're at the top level; OR (ii) The next enclosing
+;;;; level of bracketing is a '{'.  HMM.  Doesn't seem to make sense.
+;;;; 2003/8/8 This might have something to do with the GCC extension "Statement Expressions", e.g.
+;;;; while ({stmt1 ; stmt2 ; exp ;}).  This form excludes such Statement Expressions.
+                (or (not (c-safe (up-list -1) t))
+                    (= (char-after) ?{))))
+         (goto-char last)
+         (throw 'done '(nil . nil)))
+
+        ;; End of a PIKE special brace list?  If so, step over it and continue.
+        ((and c-special-brace-lists
+              (eq (char-after) ?})
+              (save-excursion
+                (and (c-safe (up-list -1) t)
+                     (c-looking-at-special-brace-list))))
+         (forward-char)
+         (skip-syntax-forward "w_"))   ; Speedup only.
+
+        ;; Have we got a '}' after having moved?  If so, stop after the
+        ;; previous token.
+        ((and (eq (char-after) ?})
+              (/= here last))
+         (goto-char last)
+         (throw 'done '(nil . nil)))
+
+        ;; Stop if we encounter a preprocessor line.
+        ((and (not macro-end)
+              (eq (char-after) ?#)
+              (= (point) (c-point 'boi)))
+         (goto-char last)
+         ;(throw 'done (cons (eq (point) here) 'macro-boundary))) ; Changed 2003/3/26
+         (throw 'done '(t . macro-boundary)))
+
+        ;; Stop after a ';', '}', or "};"
+        ((looking-at ";\\|};?")
+         (goto-char (match-end 0))
+         (throw 'done '(nil . nil)))
+
+        ;; Found a string (this subsumes AWK regexps)?
+        ((looking-at c-string-limit-regexp)
+         (goto-char last)
+         (throw 'done '(t . literal)))
+
+        (t
+         (forward-char)          ; Can't fail - we checked (eobp) earlier on.
+         (skip-syntax-forward "w_")    ; Speedup only.
+         (when (and macro-end (> (point) macro-end))
+           (goto-char last)
+           (throw 'done (cons (eq (point) here) 'macro-boundary))))
+        )))))
+
+(defun c-one-line-string-p (range)
+  ;; Is the literal defined by RANGE a string contained in a single line?
+  ;;
+  ;; This function might do hidden buffer changes.
+  (save-excursion
+    (goto-char (car range))
+    (and (looking-at c-string-limit-regexp)
+        (progn (skip-chars-forward "^\n" (cdr range))
+               (eq (point) (cdr range))))))
+
 (defun c-beginning-of-statement (&optional count lim sentence-flag)
   "Go to the beginning of the innermost C statement.
 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 for the syntactic context, and a flag saying whether to do
+sentence motion in or near comments and multiline strings.
+
+Note that for use in programs, `c-beginning-of-statement-1' is
+usually better.  It has much better defined semantics than this one,
+which is intended for interactive use, and might therefore change to
+be more \"DWIM:ey\"."
+  (interactive (list (prefix-numeric-value current-prefix-arg)
+                    nil t))
+  (if (< count 0)
+      (c-end-of-statement (- count) lim sentence-flag)
+    (c-save-buffer-state
+       ((count (or count 1))
+        last ; start point for going back ONE chunk.  Updated each chunk movement.
+        (macro-fence
+         (save-excursion (and (not (bobp)) (c-beginning-of-macro) (point))))
+        res                            ; result from sub-function call
+        not-bos                        ; "not beginning-of-statement"
+        (range (c-collect-line-comments (c-literal-limits lim)))) ; (start.end) of current literal or NIL
+
+      ;; Go back one statement at each iteration of the following loop.
+      (while (and (/= count 0)
+                 (or (not lim) (> (point) lim)))
+       ;; Go back one "chunk" each time round the following loop, stopping
+       ;; when we reach a statement boundary, etc.
+       (setq last (point))
+       (while
+           (cond ; Each arm of this cond returns NIL on reaching a desired
+                 ; statement boundary, non-NIL otherwise.
+            ((bobp)
+             (setq count 0)
+             nil)
+
+            (range                ; point is within or approaching a literal.
+             (cond
+              ;; Single line string or sentence-flag is null => skip the
+              ;; entire literal.
+              ((or (null sentence-flag)
+                   (c-one-line-string-p range))
+               (goto-char (car range))
+               (setq range (c-ascertain-preceding-literal))
+               ;; N.B. The following is essentially testing for an AWK regexp
+               ;; at BOS:
+               ;; Was the previous non-ws thing an end of statement?
+               (save-excursion
+                 (if macro-fence
+                     (c-backward-comments)
+                   (c-backward-syntactic-ws))
+                 (not (or (bobp) (c-after-statement-terminator-p)))))
+
+              ;; Comment inside a statement or a multi-line string.
+              (t (when (setq res ; returns non-nil when we go out of the literal
+                             (if (eq (c-literal-type range) 'string)
+                                 (c-beginning-of-sentence-in-string range)
+                               (c-beginning-of-sentence-in-comment range)))
+                   (setq range (c-ascertain-preceding-literal)))
+                 res)))
+
+            ;; Non-literal code.
+            (t (setq res (c-back-over-illiterals macro-fence))
+               (setq not-bos          ; "not reached beginning-of-statement".
+                     (or (= (point) last)
+                         (memq (char-after) '(?\) ?\}))
+                         (and
+                          (car res)
+                          ;; We're at a tentative BOS.  The next form goes
+                          ;; back over WS looking for an end of previous
+                          ;; statement.
+                          (not (save-excursion
+                                 (if macro-fence
+                                     (c-backward-comments)
+                                   (c-backward-syntactic-ws))
+                                 (or (bobp) (c-after-statement-terminator-p)))))))
+               ;; Are we about to move backwards into or out of a
+               ;; preprocessor command?  If so, locate it's beginning.
+               (when (eq (cdr res) 'macro-boundary)
+                 (save-excursion
+                   (beginning-of-line)
+                   (setq macro-fence
+                         (and (not (bobp))
+                              (progn (c-skip-ws-backward) (c-beginning-of-macro))
+                              (point)))))
+               ;; Are we about to move backwards into a literal?
+               (when (memq (cdr res) '(macro-boundary literal))
+                 (setq range (c-ascertain-preceding-literal)))
+               not-bos))
+         (setq last (point)))
 
-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."
-  (interactive (list (prefix-numeric-value current-prefix-arg)
-                    nil t))
-  (let* ((count (or count 1))
-        here
-        (range (c-collect-line-comments (c-literal-limits lim))))
-    (while (and (/= count 0)
-               (or (not lim) (> (point) lim)))
-      (setq here (point))
-      (if (and (not range) sentence-flag)
-         (save-excursion
-           ;; Find the comment next to point if we're not in one.
-           (if (> count 0)
-               ;; Finding a comment backwards is a bit cumbersome
-               ;; because `forward-comment' regards every newline as
-               ;; a comment when searching backwards (Emacs 19.34).
-               (while (and (progn (skip-chars-backward " \t")
-                                  (setq range (point))
-                                  (setq range (if (forward-comment -1)
-                                                  (cons (point) range)
-                                                nil)))
-                           (= (char-after) ?\n)))
-             (skip-chars-forward " \t\n")
-             (setq range (point))
-             (setq range (if (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))) ?\"))
-             (progn
-               ;; move by sentence, but not past the limit of the literal
-               (save-restriction
-                 (narrow-to-region (save-excursion
-                                     (goto-char (car range))
-                                     (looking-at comment-start-skip)
-                                     (goto-char (match-end 0))
-                                     (point))
-                                   (save-excursion
-                                     (goto-char (cdr range))
-                                     (if (save-excursion
-                                           (goto-char (car range))
-                                           (looking-at "/\\*"))
-                                         (backward-char 2))
-                                     (skip-chars-backward " \t\n")
-                                     (point)))
-                 (c-safe (forward-sentence (if (> count 0) -1 1))))
-               ;; See if we should escape the literal.
-               (if (> count 0)
-                   (if (< (point) here)
-                       (setq count (1- count))
-                     (goto-char (car range))
-                     (setq range nil))
-                 (if (> (point) here)
-                     (setq count (1+ count))
-                   (goto-char (cdr range))
-                   (setq range nil))))
-           (goto-char (if (> count 0) (car range) (cdr range)))
-           (setq range nil))
-       ;; Below we do approximately the same as
-       ;; c-beginning-of-statement-1 and c-end-of-statement-1 and
-       ;; perhaps they should be changed, but that'd likely break a
-       ;; lot in cc-engine.
-       (goto-char here)
-       (if (> count 0)
-           (if (condition-case nil
-                   ;; Stop before `{' and after `;', `{', `}' and
-                   ;; `};' when not followed by `}' or `)', but on
-                   ;; the other side of the syntactic ws.  Also stop
-                   ;; before `}', but only to catch comments.  Move
-                   ;; by sexps and move into parens.
-                   (catch 'done
-                     (let (last)
-                       (while t
-                         (setq last (point))
-                         (if (and (looking-at "[{}]")
-                                  (/= here last))
-                             (throw 'done (= (char-after) ?{)))
-                         (c-backward-syntactic-ws)
-                         (cond ((bobp) ; Must handle bob specially.
-                                (if (= here last)
-                                    (if (= last (point-min))
-                                        (throw 'done t)
-                                      (goto-char last)
-                                      (throw 'done nil))
-                                  (goto-char last)
-                                  (throw 'done t)))
-                               ((progn (backward-char)
-                                       (looking-at "[;{}]"))
-                                (if (or (= here last)
-                                        (memq (char-after last) '(?\) ?})))
-                                    (if (and (= (char-before) ?})
-                                             (= (char-after) ?\;))
-                                        (backward-char))
-                                  (goto-char last)
-                                  (throw 'done t)))
-                               ((= (char-syntax (char-after)) ?\")
-                                (forward-char)
-                                (c-backward-sexp))
-                               ))))
-                 (error
-                  (goto-char (point-min))
-                  t))
-               (setq count (1- count)))
-         (if (condition-case nil
-                 ;; Stop before `{' and `}', but on the other side of
-                 ;; the syntactic ws, and after `;', `}' and `};'.
-                 ;; Only stop before `{' if at top level or inside
-                 ;; braces, though.  Also stop after `{', but only to
-                 ;; catch comments.  Move by sexps and move into
-                 ;; parens.
-                 (catch 'done
-                   (let (last)
-                     (while t
-                       (setq last (point))
-                       (c-forward-syntactic-ws)
-                       (cond ((= (char-after) ?{)
-                              (if (or (= here last)
-                                      (save-excursion
-                                        (and (c-safe (progn (up-list -1) t))
-                                             (/= (char-after) ?{))))
-                                  (progn (forward-char)
-                                         (throw 'done nil))
-                                (goto-char last)
-                                (throw 'done t)))
-                             ((and (= (char-after) ?})
-                                   (/= here last))
-                              (goto-char last)
-                              (throw 'done t))
-                             ((looking-at ";\\|};?")
-                              (goto-char (match-end 0))
-                              (throw 'done t))
-                             ((= (char-syntax (char-after)) ?\")
-                              (c-forward-sexp))
-                             (t
-                              (forward-char))
-                             ))))
-               (error
-                (goto-char (point-max))
-                t))
-             (setq count (1+ count)))))
-      ;; If we haven't moved we're near a buffer limit.
-      (when (= (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))))
-  (c-keep-region-active))
+       (if (/= count 0) (setq count (1- count))))
+      (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)
-  (c-keep-region-active))
+  (setq count (or count 1))
+  (if (< count 0) (c-beginning-of-statement (- count) lim sentence-flag)
+
+    (c-save-buffer-state
+       (here ; start point for going forward ONE statement.  Updated each statement.
+        (macro-fence
+         (save-excursion
+           (and (not (eobp)) (c-beginning-of-macro)
+                (progn (c-end-of-macro) (point)))))
+        res
+        (range (c-collect-line-comments (c-literal-limits lim)))) ; (start.end) of current literal or NIL
+
+      ;; Go back/forward one statement at each iteration of the following loop.
+      (while (and (/= count 0)
+                 (or (not lim) (< (point) lim)))
+       (setq here (point))             ; ONLY HERE is HERE updated
+
+       ;; Go forward one "chunk" each time round the following loop, stopping
+       ;; when we reach a statement boundary, etc.
+       (while
+           (cond    ; Each arm of this cond returns NIL on reaching a desired
+                    ; statement boundary, non-NIL otherwise.
+            ((eobp)
+             (setq count 0)
+             nil)
+
+            (range                     ; point is within a literal.
+             (cond
+              ;; sentence-flag is null => skip the entire literal.
+              ;; or a Single line string.
+              ((or (null sentence-flag)
+                   (c-one-line-string-p range))
+               (goto-char (cdr range))
+               (setq range (c-ascertain-following-literal))
+               ;; Is there a virtual semicolon here (e.g. for AWK)?
+               (not (c-at-vsemi-p)))
+
+              ;; Comment or multi-line string.
+              (t (when (setq res ; gets non-nil when we go out of the literal
+                             (if (eq (c-literal-type range) 'string)
+                                 (c-end-of-sentence-in-string range)
+                               (c-end-of-sentence-in-comment range)))
+                   (setq range (c-ascertain-following-literal)))
+                 ;; If we've just come forward out of a literal, check for
+                 ;; vsemi.  (N.B. AWK can't have a vsemi after a comment, but
+                 ;; some other language may do in the future)
+                 (and res
+                      (not (c-at-vsemi-p))))))
+
+            ;; Non-literal code.
+            (t (setq res (c-forward-over-illiterals macro-fence
+                                                    (> (point) here)))
+               ;; Are we about to move forward into or out of a
+               ;; preprocessor command?
+               (when (eq (cdr res) 'macro-boundary)
+                 (save-excursion
+                   (end-of-line)
+                   (setq macro-fence
+                         (and (not (eobp))
+                              (progn (c-skip-ws-forward)
+                                     (c-beginning-of-macro))
+                              (progn (c-end-of-macro)
+                                     (point))))))
+               ;; Are we about to move forward into a literal?
+               (when (memq (cdr res) '(macro-boundary literal))
+                 (setq range (c-ascertain-following-literal)))
+               (car res))))
+
+       (if (/= count 0) (setq count (1- count))))
+      (c-keep-region-active))))
 
 \f
 ;; set up electric character functions to work with pending-del,
@@ -937,38 +2612,78 @@ comment."
 (put 'c-electric-delete    'pending-delete   'supersede) ; pending-del
 (put 'c-electric-backspace 'delete-selection 'supersede) ; delsel
 (put 'c-electric-backspace 'pending-delete   'supersede) ; pending-del
+(put 'c-electric-delete-forward 'delete-selection 'supersede) ; delsel
+(put 'c-electric-delete-forward 'pending-delete   'supersede) ; pending-del
 
 \f
-;; This is used by indent-for-comment to decide how much to indent a
-;; comment in C code based on its context.
+;; Inserting/indenting comments
+(defun c-calc-comment-indent (entry)
+  ;; This function might do hidden buffer changes.
+  (if (symbolp entry)
+      (setq entry (or (assq entry c-indent-comment-alist)
+                     (assq 'other c-indent-comment-alist)
+                     '(default . (column . nil)))))
+  (let ((action (car (cdr entry)))
+       (value (cdr (cdr entry)))
+       (col (current-column)))
+    (cond ((eq action 'space)
+          (+ col value))
+         ((eq action 'column)
+          (unless value (setq value comment-column))
+          (if (bolp)
+              ;; Do not pad with one space if we're at bol.
+              value
+            (max (1+ col) value)))
+         ((eq action 'align)
+          (or (save-excursion
+                (beginning-of-line)
+                (unless (bobp)
+                  (backward-char)
+                  (let ((lim (c-literal-limits (c-point 'bol) t)))
+                    (when (consp lim)
+                      (goto-char (car lim))
+                      (when (looking-at "/[/*]") ; FIXME!!!  Adapt for AWK! (ACM, 2005/11/18)
+                        ;; Found comment to align with.
+                        (if (bolp)
+                            ;; Do not pad with one space if we're at bol.
+                            0
+                          (max (1+ col) (current-column))))))))
+              ;; Recurse to handle value as a new spec.
+              (c-calc-comment-indent (cdr entry)))))))
+
 (defun c-comment-indent ()
-  (if (looking-at (concat "^\\(" c-comment-start-regexp "\\)"))
-      0                                ;Existing comment at bol stays there.
-    (let ((opoint (point))
-         placeholder)
-      (save-excursion
-       (beginning-of-line)
-       (cond
-        ;; CASE 1: A comment following a solitary close-brace should
-        ;; have only one space.
-        ((looking-at (concat "[ \t]*}[ \t]*\\($\\|"
-                             c-comment-start-regexp
-                             "\\)"))
-         (search-forward "}")
-         (1+ (current-column)))
-        ;; CASE 2: 2 spaces after #endif
-        ((or (looking-at "^#[ \t]*endif[ \t]*")
-             (looking-at "^#[ \t]*else[ \t]*"))
-         7)
-        ;; CASE 3: when c-indent-comments-syntactically-p is t,
-        ;; calculate the offset according to c-offsets-alist.
-        ;; E.g. identical to hitting TAB.
-        ((and c-indent-comments-syntactically-p
-              (save-excursion
-                (skip-chars-forward " \t")
-                (or (looking-at c-comment-start-regexp)
-                    (eolp))))
-         (let ((syntax (c-guess-basic-syntax)))
+  "Used by `indent-for-comment' to create and indent comments.
+See `c-indent-comment-alist' for a description."
+  (save-excursion
+    (end-of-line)
+    (c-save-buffer-state
+         ((eot (let ((lim (c-literal-limits (c-point 'bol) t)))
+                 (or (when (consp lim)
+                       (goto-char (car lim))
+                       (when (looking-at "/[/*]")
+                         (skip-chars-backward " \t")
+                         (point)))
+                     (progn
+                       (skip-chars-backward " \t")
+                       (point)))))
+          (line-type
+           (cond ((looking-at "^/[/*]")
+                  'anchored-comment)
+                 ((progn (beginning-of-line)
+                         (eq (point) eot))
+                  'empty-line)
+                 ((progn (back-to-indentation)
+                         (and (eq (char-after) ?})
+                              (eq (point) (1- eot))))
+                  'end-block)
+                 ((and (looking-at "#[ \t]*\\(endif\\|else\\)")
+                       (eq (match-end 0) eot))
+                  'cpp-end-block)
+                 (t
+                  'other))))
+      (if (and (memq line-type '(anchored-comment empty-line))
+              c-indent-comments-syntactically-p)
+         (let ((c-syntactic-context (c-guess-basic-syntax)))
            ;; BOGOSITY ALERT: if we're looking at the eol, its
            ;; because indent-for-comment hasn't put the comment-start
            ;; in the buffer yet.  this will screw up the syntactic
@@ -976,130 +2691,106 @@ comment."
            ;; kludge is that if we're at the bol, then we really want
            ;; 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")
-                 (eolp))
+           (if (eolp)
                (c-add-syntax 'comment-intro))
            (let ((c-comment-only-line-offset
                   (if (consp c-comment-only-line-offset)
                       c-comment-only-line-offset
                     (cons c-comment-only-line-offset
                           c-comment-only-line-offset))))
-             (apply '+ (mapcar 'c-get-offset syntax)))))
-        ;; CASE 4: use comment-column if previous line is a
-        ;; comment-only line indented to the left of comment-column
-        ((save-excursion
-           (beginning-of-line)
-           (and (not (bobp))
-                (forward-line -1))
-           (skip-chars-forward " \t")
-           (prog1
-               (looking-at c-comment-start-regexp)
-             (setq placeholder (point))))
-         (goto-char placeholder)
-         (if (< (current-column) comment-column)
-             comment-column
-           (current-column)))
-        ;; CASE 5: If comment-column is 0, and nothing but space
-        ;; before the comment, align it at 0 rather than 1.
-        ((progn
-           (goto-char opoint)
-           (skip-chars-backward " \t")
-           (and (= comment-column 0) (bolp)))
-         0)
-        ;; CASE 6: indent at comment column except leave at least one
-        ;; space.
-        (t (max (1+ (current-column))
-                comment-column))
-        )))))
+             (c-get-syntactic-indentation c-syntactic-context)))
+       (goto-char eot)
+       (c-calc-comment-indent line-type)))))
 
 \f
-;; for proposed new variable comment-line-break-function
-(defun c-comment-line-break-function (&optional soft)
-  ;; we currently don't do anything with soft line breaks
-  (let ((literal (c-in-literal))
-       at-comment-col)
-    (cond
-     ((eq literal 'string)
-      (insert ?\n))
-     ((or (not c-comment-continuation-stars)
-         (not literal))
-      (indent-new-comment-line soft))
-     (t (let ((here (point))
-             (leader c-comment-continuation-stars))
-         (back-to-indentation)
-         ;; comment could be hanging
-         (if (not (c-in-literal))
-             (progn
-               (forward-line 1)
-               (forward-comment -1)
-               (setq at-comment-col (= (current-column) comment-column))))
-         ;; are we looking at a block or lines style comment?
-         (if (and (looking-at (concat "\\(" c-comment-start-regexp
-                                      "\\)[ \t]+"))
-                  (string-equal (match-string 1) "//"))
-             ;; line style
-             (setq leader (match-string 0)))
-         (goto-char here)
-         (delete-region (progn (skip-chars-backward " \t") (point))
-                        (progn (skip-chars-forward " \t") (point)))
-         (newline)
-         ;; to avoid having an anchored comment that c-indent-line will
-         ;; trip up on
-         (insert " " leader)
-         (if at-comment-col
-             (indent-for-comment))
-         (c-indent-line))))))
-
-;; advice for indent-new-comment-line for older Emacsen
-(or (boundp 'comment-line-break-function)
-    (defadvice indent-new-comment-line (around c-line-break-advice
-                                              activate preactivate)
-      "Calls c-comment-line-break-function if in a comment in CC Mode."
-      (if (or (not c-buffer-is-cc-mode)
-             (not (c-in-literal))
-             (not c-comment-continuation-stars))
-         ad-do-it
-       (c-comment-line-break-function (ad-get-arg 0)))))
-
 ;; used by outline-minor-mode
 (defun c-outline-level ()
-  (save-excursion
-    (skip-chars-forward "\t ")
-    (current-column)))
+  (let (buffer-invisibility-spec);; This so that `current-column' DTRT
+                                ;; in otherwise-hidden text.
+    (save-excursion
+      (skip-chars-forward "\t ")
+      (current-column))))
 
 \f
+;; Movement by CPP conditionals.
 (defun c-up-conditional (count)
   "Move back to the containing preprocessor conditional, leaving mark behind.
 A prefix argument acts as a repeat count.  With a negative argument,
 move forward to the end of the containing preprocessor conditional.
-When going backwards, `#elif' is treated like `#else' followed by
-`#if'.  When going forwards, `#elif' is ignored."
+
+\"#elif\" is treated like \"#else\" followed by \"#if\", so the
+function stops at them when going backward, but not when going
+forward."
+  (interactive "p")
+  (c-forward-conditional (- count) -1)
+  (c-keep-region-active))
+
+(defun c-up-conditional-with-else (count)
+  "Move back to the containing preprocessor conditional, including \"#else\".
+Just like `c-up-conditional', except it also stops at \"#else\"
+directives."
+  (interactive "p")
+  (c-forward-conditional (- count) -1 t)
+  (c-keep-region-active))
+
+(defun c-down-conditional (count)
+  "Move forward into the next preprocessor conditional, leaving mark behind.
+A prefix argument acts as a repeat count.  With a negative argument,
+move backward into the previous preprocessor conditional.
+
+\"#elif\" is treated like \"#else\" followed by \"#if\", so the
+function stops at them when going forward, but not when going
+backward."
+  (interactive "p")
+  (c-forward-conditional count 1)
+  (c-keep-region-active))
+
+(defun c-down-conditional-with-else (count)
+  "Move forward into the next preprocessor conditional, including \"#else\".
+Just like `c-down-conditional', except it also stops at \"#else\"
+directives."
   (interactive "p")
-  (c-forward-conditional (- count) t)
+  (c-forward-conditional count 1 t)
   (c-keep-region-active))
 
-(defun c-backward-conditional (count &optional up-flag)
+(defun c-backward-conditional (count &optional target-depth with-else)
   "Move back across a preprocessor conditional, leaving mark behind.
 A prefix argument acts as a repeat count.  With a negative argument,
 move forward across a preprocessor conditional."
   (interactive "p")
-  (c-forward-conditional (- count) up-flag)
+  (c-forward-conditional (- count) target-depth with-else)
   (c-keep-region-active))
 
-(defun c-forward-conditional (count &optional up-flag)
+(defun c-forward-conditional (count &optional target-depth with-else)
   "Move forward across a preprocessor conditional, leaving mark behind.
 A prefix argument acts as a repeat count.  With a negative argument,
-move backward across a preprocessor conditional."
+move backward across a preprocessor conditional.
+
+\"#elif\" is treated like \"#else\" followed by \"#if\", except that
+the nesting level isn't changed when tracking subconditionals.
+
+The optional argument TARGET-DEPTH specifies the wanted nesting depth
+after each scan.  I.e. if TARGET-DEPTH is -1, the function will move
+out of the enclosing conditional.  A non-integer non-nil TARGET-DEPTH
+counts as -1.
+
+If the optional argument WITH-ELSE is non-nil, \"#else\" directives
+are treated as conditional clause limits.  Normally they are ignored."
   (interactive "p")
   (let* ((forward (> count 0))
         (increment (if forward -1 1))
         (search-function (if forward 're-search-forward 're-search-backward))
         (new))
+    (unless (integerp target-depth)
+      (setq target-depth (if target-depth -1 0)))
     (save-excursion
       (while (/= count 0)
-       (let ((depth (if up-flag 0 -1)) found)
+       (let ((depth 0)
+             ;; subdepth is the depth in "uninteresting" subtrees,
+             ;; i.e. those that takes us farther from the target
+             ;; depth instead of closer.
+             (subdepth 0)
+             found)
          (save-excursion
            ;; Find the "next" significant line in the proper direction.
            (while (and (not found)
@@ -1110,36 +2801,50 @@ move backward across a preprocessor conditional."
                        ;; precedes it.  This is faster on account of
                        ;; the fastmap feature of the regexp matcher.
                        (funcall search-function
-                                "#[ \t]*\\(if\\|elif\\|endif\\)"
+                                "#[ \t]*\\(if\\|elif\\|endif\\|else\\)"
                                 nil t))
              (beginning-of-line)
              ;; Now verify it is really a preproc line.
-             (if (looking-at "^[ \t]*#[ \t]*\\(if\\|elif\\|endif\\)")
-                 (let ((prev depth))
-                   ;; Update depth according to what we found.
-                   (beginning-of-line)
-                   (cond ((looking-at "[ \t]*#[ \t]*endif")
-                          (setq depth (+ depth increment)))
-                         ((looking-at "[ \t]*#[ \t]*elif")
-                          (if (and forward (= depth 0))
-                              (setq found (point))))
-                         (t (setq depth (- depth increment))))
-                   ;; If we are trying to move across, and we find an
-                   ;; end before we find a beginning, get an error.
-                   (if (and (< prev 0) (< depth prev))
-                       (error (if forward
-                                  "No following conditional at this level"
-                                "No previous conditional at this level")))
+             (if (looking-at "^[ \t]*#[ \t]*\\(if\\|elif\\|endif\\|else\\)")
+                 (let (dchange (directive (match-string 1)))
+                   (cond ((string= directive "if")
+                          (setq dchange (- increment)))
+                         ((string= directive "endif")
+                          (setq dchange increment))
+                         ((= subdepth 0)
+                          ;; When we're not in an "uninteresting"
+                          ;; subtree, we might want to act on "elif"
+                          ;; and "else" too.
+                          (if (cond (with-else
+                                     ;; Always move toward the target depth.
+                                     (setq dchange
+                                           (if (> target-depth 0) 1 -1)))
+                                    ((string= directive "elif")
+                                     (setq dchange (- increment))))
+                              ;; Ignore the change if it'd take us
+                              ;; into an "uninteresting" subtree.
+                              (if (eq (> dchange 0) (<= target-depth 0))
+                                  (setq dchange nil)))))
+                   (when dchange
+                     (when (or (/= subdepth 0)
+                               (eq (> dchange 0) (<= target-depth 0)))
+                       (setq subdepth (+ subdepth dchange)))
+                     (setq depth (+ depth dchange))
+                     ;; If we are trying to move across, and we find an
+                     ;; end before we find a beginning, get an error.
+                     (if (and (< depth target-depth) (< dchange 0))
+                         (error (if forward
+                                    "No following conditional at this level"
+                                  "No previous conditional at this level"))))
                    ;; When searching forward, start from next line so
                    ;; that we don't find the same line again.
                    (if forward (forward-line 1))
-                   ;; If this line exits a level of conditional, exit
-                   ;; inner loop.
-                   (if (< depth 0)
+                   ;; We found something if we've arrived at the
+                   ;; target depth.
+                   (if (and dchange (= depth target-depth))
                        (setq found (point))))
                ;; else
-               (if forward (forward-line 1))
-               )))
+               (if forward (forward-line 1)))))
          (or found
              (error "No containing preprocessor conditional"))
          (goto-char (setq new found)))
@@ -1150,20 +2855,25 @@ move backward across a preprocessor conditional."
 
 \f
 ;; commands to indent lines, regions, defuns, and expressions
-(defun c-indent-command (&optional whole-exp)
+(defun c-indent-command (&optional arg)
   "Indent current line as C code, and/or insert some whitespace.
 
 If `c-tab-always-indent' is t, always just indent the current line.
 If nil, indent the current line only if point is at the left margin or
 in the line's indentation; otherwise insert some whitespace[*].  If
 other than nil or t, then some whitespace[*] is inserted only within
-literals (comments and strings) and inside preprocessor directives,
-but the line is always reindented.
+literals (comments and strings), but the line is always reindented.
+
+If `c-syntactic-indentation' is t, indentation is done according to
+the syntactic context.  A numeric argument, regardless of its value,
+means indent rigidly all the lines of the expression starting after
+point so that this line becomes properly indented.  The relative
+indentation among the lines of the expression is preserved.
 
-A numeric argument, regardless of its value, means indent rigidly all
-the lines of the expression starting after point so that this line
-becomes properly indented.  The relative indentation among the lines
-of the expression are preserved.
+If `c-syntactic-indentation' is nil, the line is just indented one
+step according to `c-basic-offset'.  In this mode, a numeric argument
+indents a number of such steps, positive or negative, and an empty
+prefix argument is equivalent to -1.
 
   [*] The amount and kind of whitespace inserted is controlled by the
   variable `c-insert-tab-function', which is called to do the actual
@@ -1172,15 +2882,39 @@ of the expression are preserved.
   depending on the variable `indent-tabs-mode'."
 
   (interactive "P")
-  (let ((bod (c-point 'bod)))
-    (if whole-exp
-       ;; If arg, always indent this line as C
-       ;; and shift remaining lines of expression the same amount.
-       (let ((shift-amt (c-indent-line))
+  (let ((indent-function
+        (if c-syntactic-indentation
+            (symbol-function 'indent-according-to-mode)
+          (lambda ()
+            (let ((c-macro-start c-macro-start)
+                  (steps (if (equal arg '(4))
+                             -1
+                           (prefix-numeric-value arg))))
+              (c-shift-line-indentation (* steps c-basic-offset))
+              (when (and c-auto-align-backslashes
+                         (save-excursion
+                           (end-of-line)
+                           (eq (char-before) ?\\))
+                         (c-query-and-set-macro-start))
+                ;; Realign the line continuation backslash if inside a macro.
+                (c-backslash-region (point) (point) nil t)))
+            ))))
+    (if (and c-syntactic-indentation arg)
+       ;; 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 (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))
+               (beginning-of-line))    ; FIXME!!! What is this here for?  ACM 2005/10/31
            (setq beg (point))
            (c-forward-sexp 1)
            (setq end (point))
@@ -1188,252 +2922,161 @@ of the expression are preserved.
            (forward-line 1)
            (setq beg (point)))
          (if (> end beg)
-             (indent-code-rigidly beg end (- shift-amt) "#")))
-      ;; No arg supplied, use c-tab-always-indent to determine
-      ;; behavior
+             (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,
+       ;; CASE 1: indent when at column zero or in line's indentation,
        ;; otherwise insert a tab
        ((not c-tab-always-indent)
        (if (save-excursion
              (skip-chars-backward " \t")
              (not (bolp)))
            (funcall c-insert-tab-function)
-         (c-indent-line)))
+         (funcall indent-function)))
        ;; CASE 2: just indent the line
        ((eq c-tab-always-indent t)
-       (c-indent-line))
+       (funcall indent-function))
        ;; CASE 3: if in a literal, insert a tab, but always indent the
        ;; line
        (t
-       (if (c-in-literal bod)
+       (if (c-save-buffer-state () (c-in-literal))
            (funcall c-insert-tab-function))
-       (c-indent-line)
+       (funcall indent-function)
        )))))
 
 (defun c-indent-exp (&optional shutup-p)
-  "Indent each line in balanced expression following point.
-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 signaled if no
+balanced expression is found."
   (interactive "*P")
-  (let ((here (point))
-       end progress-p)
+  (let ((here (point-marker))
+       end)
+    (set-marker-insertion-type here t)
     (unwind-protect
-       (let ((c-echo-syntactic-information-p nil) ;keep quiet for speed
-             (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
-                      (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)))))))
-         ;; find balanced expression end
-         (setq end (and (c-safe (progn (c-forward-sexp 1) t))
-                        (point-marker)))
+       (let ((start (save-restriction
+                      ;; Find the closest following open paren that
+                      ;; ends on another line.
+                      (narrow-to-region (point-min) (c-point 'eol))
+                      (let (beg (end (point)))
+                        (while (and (setq beg (c-down-list-forward end))
+                                    (setq end (c-up-list-forward beg))))
+                        (and beg
+                             (eq (char-syntax (char-before beg)) ?\()
+                             (1- beg))))))
          ;; 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))
-      (goto-char here))))
+         (if (not start)
+            (unless shutup-p
+              (error "Cannot find start of balanced expression to indent"))
+           (goto-char start)
+           (setq end (c-safe (scan-sexps (point) 1)))
+           (if (not end)
+               (unless shutup-p
+                 (error "Cannot find end of balanced expression to indent"))
+             (forward-line)
+             (if (< (point) end)
+                 (c-indent-region (point) 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 declaration or macro syntactically.
+In the macro case this also has the effect of realigning any line
+continuation backslashes, unless `c-auto-align-backslashes' is nil."
   (interactive "*")
-  (let ((here (point-marker))
-       (c-echo-syntactic-information-p nil)
-       (brace (c-least-enclosing-brace (c-parse-state))))
-    (goto-char (or brace (c-point 'bod)))
-    ;; if we're sitting at b-o-b, it might be because there was no
-    ;; least enclosing brace and we were sitting on the defun's open
-    ;; brace.
-    (if (and (bobp) (not (eq (char-after) ?\{)))
-       (goto-char here))
-    ;; if defun-prompt-regexp is non-nil, b-o-d might not leave us at
-    ;; the open brace. I consider this an Emacs bug.
-    (and (boundp 'defun-prompt-regexp)
-        defun-prompt-regexp
-        (looking-at defun-prompt-regexp)
-        (goto-char (match-end 0)))
-    ;; catch all errors in c-indent-exp so we can 1. give more
-    ;; meaningful error message, and 2. restore point
+  (let ((here (point-marker)) decl-limits)
     (unwind-protect
-       (c-indent-exp)
+       (progn
+         (c-save-buffer-state nil
+           ;; We try to be line oriented, unless there are several
+           ;; declarations on the same line.
+           (if (looking-at c-syntactic-eol)
+               (c-backward-token-2 1 nil (c-point 'bol))
+             (c-forward-token-2 0 nil (c-point 'eol)))
+           (setq decl-limits (c-declaration-limits nil)))
+         (if decl-limits
+             (c-indent-region (car decl-limits)
+                              (cdr decl-limits))))
       (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 syntactically every line whose first char is between START
+and END inclusive.  If the optional argument QUIET is non-nil then no
+syntactic errors are reported, even if `c-report-syntactic-errors' is
+non-nil."
   (save-excursion
+    (goto-char end)
+    (skip-chars-backward " \t\n\r\f\v")
+    (setq end (point))
     (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)))
-                 ;; check to see if the next line starts a
-                 ;; comment-only line
-                 (save-excursion
-                   (forward-line 1)
-                   (skip-chars-forward " \t")
-                   (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)
-       ))))
+    (skip-chars-forward " \t\n\r\f\v")
+    (setq start (point))
+    (beginning-of-line)
+    (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)
+                   (in-macro (and c-auto-align-backslashes
+                                  (c-save-buffer-state ()
+                                    (save-excursion (c-beginning-of-macro)))
+                                  start))
+                   (c-fix-backslashes nil)
+                   syntax)
+               (unwind-protect
+                   (progn
+                     (c-progress-init start end 'c-indent-region)
+                     (while (and (bolp)
+                                 (not (eobp))
+                                 (< (point) endmark))
+                       ;; update progress
+                       (c-progress-update)
+                       ;; skip empty lines
+                       (skip-chars-forward " \t\n")
+                       (beginning-of-line)
+                       ;; Get syntax and indent.
+                       (c-save-buffer-state nil
+                         (setq syntax (c-guess-basic-syntax)))
+                       (if (and c-auto-align-backslashes
+                                (assq 'cpp-macro syntax))
+                           ;; Record macro start.
+                           (setq in-macro (point)))
+                       (if in-macro
+                           (if (looking-at "\\s *\\\\$")
+                               (forward-line)
+                             (c-indent-line syntax t t)
+                             (if (progn (end-of-line)
+                                        (not (eq (char-before) ?\\)))
+                                 (progn
+                                   ;; Fixup macro backslashes.
+                                   (forward-line)
+                                   (c-backslash-region in-macro (point) nil)
+                                   (setq in-macro nil))
+                               (forward-line)))
+                         (c-indent-line syntax t t)
+                         (forward-line)))
+                     (if in-macro
+                         (c-backslash-region in-macro (c-point 'bopl) nil t)))
+                 (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."
-  (interactive)
-  (let ((here (point))
-       (eod (c-point 'eod))
-       (state (c-parse-state)))
-    ;; Are we sitting at the top level, someplace between either the
-    ;; beginning of buffer, or the nearest preceding defun?  If so,
-    ;; try first to figure out whether we're sitting on the
-    ;; introduction to a top-level defun, in which case we want to
-    ;; mark the entire defun we're sitting on.
-    ;;
-    ;; If we're sitting on anything else at the top-level, we want to
-    ;; just mark the statement that we're on
-    (if (or (and (consp (car state))
-                (= (length state) 1))
-           (null state))
-       ;; Are we in the whitespace after the nearest preceding defun?
-       (if (and state
-                (looking-at "[ \t]*$")
-                (= (save-excursion
-                     (c-backward-syntactic-ws)
-                     (skip-chars-backward ";")
-                     (point))
-                   (cdar state)))
-           (progn
-             (setq eod (point))
-             (goto-char (caar state))
-             (c-beginning-of-statement-1))
-         (if (= ?{ (save-excursion
-                     (c-end-of-statement-1)
-                     (char-before)))
-             ;; We must be in a defuns's introduction
-             (progn
-               (c-end-of-statement-1)
-               (skip-chars-backward "{")
-               (c-beginning-of-statement-1)
-               (c-forward-syntactic-ws))
-           ;; Just mark the statement
-           (c-end-of-statement-1)
-           (forward-line 1)
-           (setq eod (point))
-           (c-beginning-of-statement-1)))
-      ;; We are inside some enclosing brace structure, so we first
-      ;; need to find our way to the least enclosing brace.  Then, in
-      ;; both cases, we to mark the region from the beginning of the
-      ;; current statement, until the end of the next following defun
-      (while (and state)
-       (or (consp (car state))
-           (goto-char (car state)))
-       (setq state (cdr state)))
-      (c-beginning-of-statement-1))
-    (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."
+  "When the region is active, indent it syntactically.  Otherwise
+indent the current line syntactically."
   ;; 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)))
+    (c-indent-line)))
 
 \f
 ;; for progress reporting
@@ -1446,7 +3089,7 @@ Optional SHUTUP-P if non-nil, inhibits message printing and error checking."
    ;; 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]
@@ -1457,11 +3100,10 @@ Optional SHUTUP-P if non-nil, inhibits message printing and error checking."
                                      (point-marker))
                                    (nth 1 (current-time))
                                    context))
-      (message "indenting region..."))
+      (message "Indenting region..."))
    ))
 
 (defun c-progress-update ()
-  ;; update progress
   (if (not (and c-progress-info c-progress-interval))
       nil
     (let ((now (nth 1 (current-time)))
@@ -1472,13 +3114,12 @@ Optional SHUTUP-P if non-nil, inhibits message printing and error checking."
       ;; 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)))
       )))
 
 (defun c-progress-fini (context)
-  ;; finished
   (if (not c-progress-interval)
       nil
     (if (or (eq context (aref c-progress-info 3))
@@ -1486,84 +3127,1003 @@ Optional SHUTUP-P if non-nil, inhibits message printing and error checking."
        (progn
          (set-marker (aref c-progress-info 1) nil)
          (setq c-progress-info nil)
-         (message "indenting region...done")))))
+         (message "Indenting region... done")))))
 
 
 \f
 ;;; This page handles insertion and removal of backslashes for C macros.
 
-(defun c-backslash-region (from to delete-flag)
+(defun c-backslash-region (from to delete-flag &optional line-mode)
   "Insert, align, or delete end-of-line backslashes on the lines in the region.
 With no argument, inserts backslashes and aligns existing backslashes.
-With an argument, deletes the backslashes.
+With an argument, deletes the backslashes.  The backslash alignment is
+done according to the settings in `c-backslash-column',
+`c-backslash-max-column' and `c-auto-align-backslashes'.
 
 This function does not modify blank lines at the start of the region.
-If the region ends at the start of a line, it always deletes the
-backslash (if any) at the end of the previous line.
+If the region ends at the start of a line and the macro doesn't
+continue below it, the backslash (if any) at the end of the previous
+line is deleted.
 
 You can put the region around an entire macro definition and use this
 command to conveniently insert and align the necessary backslashes."
   (interactive "*r\nP")
-  (save-excursion
-    (goto-char from)
-    (let ((column c-backslash-column)
-          (endmark (make-marker)))
-      (move-marker endmark to)
-      ;; Compute the smallest column number past the ends of all the lines.
-      (if (not delete-flag)
-          (while (< (point) to)
-            (end-of-line)
-            (if (eq (char-before) ?\\)
-                (progn (forward-char -1)
-                       (skip-chars-backward " \t")))
-            (setq column (max column (1+ (current-column))))
-            (forward-line 1)))
-      ;; Adjust upward to a tab column, if that doesn't push past the margin.
-      (if (> (% column tab-width) 0)
-          (let ((adjusted (* (/ (+ column tab-width -1) tab-width) tab-width)))
-            (if (< adjusted (window-width))
-                (setq column adjusted))))
-      ;; Don't modify blank lines at start of region.
-      (goto-char from)
-      (while (and (< (point) endmark) (eolp))
-        (forward-line 1))
-      ;; Add or remove backslashes on all the lines.
-      (while (< (point) endmark)
-       (if (and (not delete-flag)
-                ;; Un-backslashify the last line
-                ;; if the region ends right at the start of the next line.
-                (save-excursion
-                  (forward-line 1)
-                  (< (point) endmark)))
-            (c-append-backslash column)
-          (c-delete-backslash))
-        (forward-line 1))
-      (move-marker endmark nil))))
-
-(defun c-append-backslash (column)
-  (end-of-line)
-  (if (eq (char-before) ?\\)
-      (progn (forward-char -1)
-             (delete-horizontal-space)
-             (indent-to column))
-    (indent-to column)
-    (insert "\\")))
-
-(defun c-delete-backslash ()
-  (end-of-line)
-  (or (bolp)
-      (progn
-       (forward-char -1)
-       (if (looking-at "\\\\")
-           (delete-region (1+ (point))
-                          (progn (skip-chars-backward " \t") (point)))))))
+  (let ((endmark (make-marker))
+       ;; Keep the backslash trimming functions from changing the
+       ;; whitespace around point, since in this case it's only the
+       ;; position of point that tells the indentation of the line.
+       (point-pos (if (save-excursion
+                        (skip-chars-backward " \t")
+                        (and (bolp) (looking-at "[ \t]*\\\\?$")))
+                      (point-marker)
+                    (point-min)))
+       column longest-line-col bs-col-after-end)
+    (save-excursion
+      (goto-char to)
+      (if (and (not line-mode) (bobp))
+         ;; Nothing to do if to is at bob, since we should back up
+         ;; and there's no line to back up to.
+         nil
+       (when (and (not line-mode) (bolp))
+         ;; Do not back up the to line if line-mode is set, to make
+         ;; e.g. c-newline-and-indent consistent regardless whether
+         ;; the (newline) call leaves point at bol or not.
+         (backward-char)
+         (setq to (point)))
+       (if delete-flag
+           (progn
+             (set-marker endmark (point))
+             (goto-char from)
+             (c-delete-backslashes-forward endmark point-pos))
+         ;; Set bs-col-after-end to the column of any backslash
+         ;; following the region, or nil if there is none.
+         (setq bs-col-after-end
+               (and (progn (end-of-line)
+                           (eq (char-before) ?\\))
+                    (= (forward-line 1) 0)
+                    (progn (end-of-line)
+                           (eq (char-before) ?\\))
+                    (1- (current-column))))
+         (when line-mode
+           ;; Back up the to line if line-mode is set, since the line
+           ;; after the newly inserted line break should not be
+           ;; touched in c-newline-and-indent.
+           (setq to (max from (or (c-safe (c-point 'eopl)) from)))
+           (unless bs-col-after-end
+             ;; Set bs-col-after-end to non-nil in any case, since we
+             ;; do not want to delete the backslash at the last line.
+             (setq bs-col-after-end t)))
+         (if (and line-mode
+                  (not c-auto-align-backslashes))
+             (goto-char from)
+           ;; Compute the smallest column number past the ends of all
+           ;; the lines.
+           (setq longest-line-col 0)
+           (goto-char to)
+           (if bs-col-after-end
+               ;; Include one more line in the max column
+               ;; calculation, since the to line will be backslashed
+               ;; too.
+               (forward-line 1))
+           (end-of-line)
+           (while (and (>= (point) from)
+                       (progn
+                         (if (eq (char-before) ?\\)
+                             (forward-char -1))
+                         (skip-chars-backward " \t")
+                         (setq longest-line-col (max longest-line-col
+                                                     (1+ (current-column))))
+                         (beginning-of-line)
+                         (not (bobp))))
+             (backward-char))
+           ;; Try to align with surrounding backslashes.
+           (goto-char from)
+           (beginning-of-line)
+           (if (and (not (bobp))
+                    (progn (backward-char)
+                           (eq (char-before) ?\\)))
+               (progn
+                 (setq column (1- (current-column)))
+                 (if (numberp bs-col-after-end)
+                     ;; Both a preceding and a following backslash.
+                     ;; Choose the greatest of them.
+                     (setq column (max column bs-col-after-end)))
+                 (goto-char from))
+             ;; No preceding backslash.  Try to align with one
+             ;; following the region.  Disregard the backslash at the
+             ;; to line since it's likely to be bogus (e.g. when
+             ;; called from c-newline-and-indent).
+             (if (numberp bs-col-after-end)
+                 (setq column bs-col-after-end))
+             ;; Don't modify blank lines at start of region.
+             (goto-char from)
+             (while (and (< (point) to) (bolp) (eolp))
+               (forward-line 1)))
+           (if (and column (< column longest-line-col))
+               ;; Don't try to align with surrounding backslashes if
+               ;; any line is too long.
+               (setq column nil))
+           (unless column
+             ;; Impose minimum limit and tab width alignment only if
+             ;; we can't align with surrounding backslashes.
+             (if (> (% longest-line-col tab-width) 0)
+                 (setq longest-line-col
+                       (* (/ (+ longest-line-col tab-width -1)
+                             tab-width)
+                          tab-width)))
+             (setq column (max c-backslash-column
+                               longest-line-col)))
+           ;; Always impose maximum limit.
+           (setq column (min column c-backslash-max-column)))
+         (if bs-col-after-end
+             ;; Add backslashes on all lines if the macro continues
+             ;; after the to line.
+             (progn
+               (set-marker endmark to)
+               (c-append-backslashes-forward endmark column point-pos))
+           ;; Add backslashes on all lines except the last, and
+           ;; remove any on the last line.
+           (if (save-excursion
+                 (goto-char to)
+                 (beginning-of-line)
+                 (if (not (bobp))
+                     (set-marker endmark (1- (point)))))
+               (progn
+                 (c-append-backslashes-forward endmark column point-pos)
+                 ;; The function above leaves point on the line
+                 ;; following endmark.
+                 (set-marker endmark (point)))
+             (set-marker endmark to))
+           (c-delete-backslashes-forward endmark point-pos)))))
+    (set-marker endmark nil)
+    (if (markerp point-pos)
+       (set-marker point-pos nil))))
+
+(defun c-append-backslashes-forward (to-mark column point-pos)
+  (let ((state (parse-partial-sexp (c-point 'bol) (point))))
+    (if column
+       (while
+           (and
+            (<= (point) to-mark)
+
+            (let ((start (point)) (inserted nil) end col)
+              (end-of-line)
+              (unless (eq (char-before) ?\\)
+                (insert ?\\)
+                (setq inserted t))
+              (setq state (parse-partial-sexp
+                           start (point) nil nil state))
+              (backward-char)
+              (setq col (current-column))
+
+              ;; Avoid unnecessary changes of the buffer.
+              (cond ((and (not inserted) (nth 3 state))
+                     ;; Don't realign backslashes in string literals
+                     ;; since that would change them.
+                     )
+
+                    ((< col column)
+                     (delete-region
+                      (point)
+                      (progn
+                        (skip-chars-backward
+                         " \t" (if (>= (point) point-pos) point-pos))
+                        (point)))
+                     (indent-to column))
+
+                    ((and (= col column)
+                          (memq (char-before) '(?\  ?\t))))
+
+                    ((progn
+                       (setq end (point))
+                       (or (/= (skip-chars-backward
+                                " \t" (if (>= (point) point-pos) point-pos))
+                               -1)
+                           (/= (char-after) ?\ )))
+                     (delete-region (point) end)
+                     (indent-to column 1)))
+
+              (zerop (forward-line 1)))
+            (bolp)))                   ; forward-line has funny behavior at eob.
+
+      ;; Make sure there are backslashes with at least one space in
+      ;; front of them.
+      (while
+         (and
+          (<= (point) to-mark)
+
+          (let ((start (point)))
+            (end-of-line)
+            (setq state (parse-partial-sexp
+                         start (point) nil nil state))
+
+            (if (eq (char-before) ?\\)
+                (unless (nth 3 state)
+                  (backward-char)
+                  (unless (and (memq (char-before) '(?\  ?\t))
+                               (/= (point) point-pos))
+                    (insert ?\ )))
+
+              (if (and (memq (char-before) '(?\  ?\t))
+                       (/= (point) point-pos))
+                  (insert ?\\)
+                (insert ?\  ?\\)))
+
+            (zerop (forward-line 1)))
+          (bolp))))))                  ; forward-line has funny behavior at eob.
+
+(defun c-delete-backslashes-forward (to-mark point-pos)
+  (while
+      (and (<= (point) to-mark)
+          (progn
+            (end-of-line)
+            (if (eq (char-before) ?\\)
+                (delete-region
+                 (point)
+                 (progn (backward-char)
+                        (skip-chars-backward " \t" (if (>= (point) point-pos)
+                                                       point-pos))
+                        (point))))
+            (zerop (forward-line 1)))
+          (bolp))))                    ; forward-line has funny behavior at eob.
+
 
 \f
+;;; 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
+;; possible to make them work correctly wrt the comment and string
+;; separators, one-line paragraphs etc.  Unfortunately, when it comes
+;; to it, there's quite a lot of special cases to handle which makes
+;; the code anything but simple.  The intention is that it will work
+;; with any well-written text filling package that preserves a fill
+;; prefix.
+;;
+;; We temporarily mask comment starters and enders as necessary for
+;; the filling code to do its job on a seemingly normal text block.
+;; We do _not_ mask the fill prefix, so it's up to the filling code to
+;; preserve it correctly (especially important when filling C++ style
+;; line comments).  By default, we set up and use adaptive-fill-mode,
+;; which is standard in all supported Emacs flavors.
+
+(defun c-guess-fill-prefix (lit-limits lit-type)
+  ;; Determine the appropriate comment fill prefix for a block or line
+  ;; comment.  Return a cons of the prefix string and the column where
+  ;; it ends.  If fill-prefix is set, it'll override.  Note that this
+  ;; function also uses the value of point in some heuristics.
+  ;;
+  ;; This function might do hidden buffer changes.
+
+  (let* ((here (point))
+        (prefix-regexp (concat "[ \t]*\\("
+                               c-current-comment-prefix
+                               "\\)[ \t]*"))
+        (comment-start-regexp (if (eq lit-type 'c++)
+                                  prefix-regexp
+                                comment-start-skip))
+        prefix-line comment-prefix res comment-text-end)
+
+    (cond
+     (fill-prefix
+      (setq res (cons fill-prefix
+                     ;; Ugly way of getting the column after the fill
+                     ;; prefix; it'd be nice with a current-column
+                     ;; that works on strings..
+                     (let ((start (point)))
+                       (unwind-protect
+                           (progn
+                             (insert-and-inherit "\n" fill-prefix)
+                             (current-column))
+                         (delete-region start (point)))))))
+
+     ((eq lit-type 'c++)
+      (save-excursion
+       ;; Set fallback for comment-prefix if none is found.
+       (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
+           ;; comment has more than one line, and it can therefore be
+           ;; used to find the comment fill prefix.
+           (setq prefix-line (point))
+
+         (goto-char (car lit-limits))
+         (if (and (= (forward-line 1) 0)
+                  (< (point) (cdr lit-limits)))
+             ;; The line after the comment starter is inside the
+             ;; comment, so we can use it.
+             (setq prefix-line (point))
+
+           ;; The comment is only one line.  Take the comment prefix
+           ;; from it and keep the indentation.
+           (goto-char (car lit-limits))
+           (if (looking-at prefix-regexp)
+               (goto-char (match-end 0))
+             (forward-char 2)
+             (skip-chars-forward " \t"))
+
+           (let (str col)
+             (if (eq (c-point 'boi) (car lit-limits))
+                 ;; There is only whitespace before the comment
+                 ;; starter; take the prefix straight from this line.
+                 (setq str (buffer-substring-no-properties
+                            (c-point 'bol) (point))
+                       col (current-column))
+
+               ;; There is code before the comment starter, so we
+               ;; have to temporarily insert and indent a new line to
+               ;; get the right space/tab mix in the indentation.
+               (let ((prefix-len (- (point) (car lit-limits)))
+                     tmp)
+                 (unwind-protect
+                     (progn
+                       (goto-char (car lit-limits))
+                       (indent-to (prog1 (current-column)
+                                    (insert ?\n)))
+                       (setq tmp (point))
+                       (forward-char prefix-len)
+                       (setq str (buffer-substring-no-properties
+                                  (c-point 'bol) (point))
+                             col (current-column)))
+                   (delete-region (car lit-limits) tmp))))
+
+             (setq res
+                   (if (or (string-match "\\s \\'" str) (not (eolp)))
+                       (cons str col)
+                     ;; The prefix ends the line with no whitespace
+                     ;; after it.  Default to a single space.
+                     (cons (concat str " ") (1+ col))))
+             )))))
+
+     (t
+      (setq comment-text-end
+           (save-excursion
+             (goto-char (- (cdr lit-limits) 2))
+             (if (looking-at "\\*/") (point) (cdr lit-limits))))
+
+      (save-excursion
+       (beginning-of-line)
+       (if (and (> (point) (car lit-limits))
+                (not (and (looking-at "[ \t]*\\*/")
+                          (eq (cdr lit-limits) (match-end 0)))))
+           ;; The current line is not the comment starter and
+           ;; contains more than just the ender, so it's good enough
+           ;; to be used for the comment fill prefix.
+           (setq prefix-line (point))
+         (goto-char (car lit-limits))
+
+         (cond ((or (/= (forward-line 1) 0)
+                    (>= (point) (cdr lit-limits))
+                    (and (looking-at "[ \t]*\\*/")
+                         (eq (cdr lit-limits) (match-end 0)))
+                    (and (looking-at prefix-regexp)
+                         (<= (1- (cdr lit-limits)) (match-end 0))))
+                ;; The comment is either one line or the next line contains
+                ;; just the comment ender.  In this case we have no
+                ;; information about a suitable comment prefix, so we resort
+                ;; to c-block-comment-prefix.
+                (setq comment-prefix (or c-block-comment-prefix "")))
+
+               ((< here (point))
+                ;; The point was on the comment opener line, so we might want
+                ;; to treat this as a not yet closed comment.
+
+                (if (and (match-beginning 1)
+                         (/= (match-beginning 1) (match-end 1)))
+                    ;; Above `prefix-regexp' matched a nonempty prefix on the
+                    ;; second line, so let's use it.  Normally it should do
+                    ;; to set `prefix-line' and let the code below pick up
+                    ;; the whole prefix, but if there's no text after the
+                    ;; match then it will probably fall back to no prefix at
+                    ;; all if the comment isn't closed yet, so in that case
+                    ;; it's better to force use of the prefix matched now.
+                    (if (= (match-end 0) (c-point 'eol))
+                        (setq comment-prefix (match-string 1))
+                      (setq prefix-line (point)))
+
+                  ;; There's no nonempty prefix on the line after the
+                  ;; comment opener.  If the line is empty, or if the
+                  ;; text on it has less or equal indentation than the
+                  ;; comment starter we assume it's an unclosed
+                  ;; comment starter, i.e. that
+                  ;; `c-block-comment-prefix' should be used.
+                  ;; Otherwise we assume it's a closed comment where
+                  ;; the prefix really is the empty string.
+                  ;; E.g. this is an unclosed comment:
+                  ;;
+                  ;;     /*
+                  ;;     foo
+                  ;;
+                  ;; But this is not:
+                  ;;
+                  ;;     /*
+                  ;;       foo
+                  ;;     */
+                  ;;
+                  ;; (Looking for the presence of the comment closer
+                  ;; rarely works since it's probably the closer of
+                  ;; some comment further down when the comment
+                  ;; really is unclosed.)
+                  (if (<= (save-excursion (back-to-indentation)
+                                          (current-column))
+                          (save-excursion (goto-char (car lit-limits))
+                                          (current-column)))
+                      (setq comment-prefix (or c-block-comment-prefix ""))
+                    (setq prefix-line (point)))))
+
+               (t
+                ;; Otherwise the line after the comment starter is good
+                ;; enough to find the prefix in.
+                (setq prefix-line (point))))
+
+         (when comment-prefix
+           ;; Haven't got the comment prefix on any real line that we
+           ;; can take it from, so we have to temporarily insert
+           ;; `comment-prefix' on a line and indent it to find the
+           ;; correct column and the correct mix of tabs and spaces.
+           (setq res
+                 (let (tmp-pre tmp-post)
+                   (unwind-protect
+                       (progn
+
+                         (goto-char (car lit-limits))
+                         (if (looking-at comment-start-regexp)
+                             (goto-char (min (match-end 0)
+                                             comment-text-end))
+                           (forward-char 2)
+                           (skip-chars-forward " \t"))
+
+                         (when (eq (char-syntax (char-before)) ?\ )
+                           ;; If there's ws on the current line, we'll use it
+                           ;; instead of what's ending comment-prefix.
+                           (setq comment-prefix
+                                 (concat (substring comment-prefix
+                                                    0 (string-match
+                                                       "\\s *\\'"
+                                                       comment-prefix))
+                                         (buffer-substring-no-properties
+                                          (save-excursion
+                                            (skip-chars-backward " \t")
+                                            (point))
+                                          (point)))))
+
+                         (setq tmp-pre (point-marker))
+
+                         ;; We insert an extra non-whitespace character
+                         ;; before the line break and after comment-prefix in
+                         ;; case it's "" or ends with whitespace.
+                         (insert-and-inherit "x\n" comment-prefix "x")
+                         (setq tmp-post (point-marker))
+
+                         (indent-according-to-mode)
+
+                         (goto-char (1- tmp-post))
+                         (cons (buffer-substring-no-properties
+                                (c-point 'bol) (point))
+                               (current-column)))
+
+                     (when tmp-post
+                       (delete-region tmp-pre tmp-post)
+                       (set-marker tmp-pre nil)
+                       (set-marker tmp-post nil))))))))))
+
+    (or res                            ; Found a good prefix above.
+
+       (save-excursion
+         ;; prefix-line is the bol of a line on which we should try
+         ;; to find the prefix.
+         (let* (fb-string fb-endpos    ; Contains any fallback prefix found.
+                (test-line
+                 (lambda ()
+                   (when (and (looking-at prefix-regexp)
+                              (<= (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)))
+                     t))))
+
+           (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)
+                            (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 (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)
+
+               (when fb-string
+                 ;; A good line wasn't found, but at least we have a
+                 ;; fallback that matches the comment prefix regexp.
+                 (cond ((or (string-match "\\s \\'" fb-string)
+                            (progn
+                              (goto-char fb-endpos)
+                              (not (eolp))))
+                        ;; There are ws or text after the prefix, so
+                        ;; let's use it.
+                        (cons fb-string (current-column)))
+
+                       ((progn
+                          ;; Check if there's any whitespace padding
+                          ;; on the comment start line that we can
+                          ;; use after the prefix.
+                          (goto-char (car lit-limits))
+                          (if (looking-at comment-start-regexp)
+                              (goto-char (match-end 0))
+                            (forward-char 2)
+                            (skip-chars-forward " \t"))
+                          (or (not (eolp))
+                              (eq (char-syntax (char-before)) ?\ )))
+
+                        (setq fb-string (buffer-substring-no-properties
+                                         (save-excursion
+                                           (skip-chars-backward " \t")
+                                           (point))
+                                         (point)))
+                        (goto-char fb-endpos)
+                        (skip-chars-backward " \t")
+
+                        (let ((tmp (point)))
+                          ;; Got to mess in the buffer once again to
+                          ;; ensure the column gets correct.  :P
+                          (unwind-protect
+                              (progn
+                                (insert-and-inherit fb-string)
+                                (cons (buffer-substring-no-properties
+                                       (c-point 'bol)
+                                       (point))
+                                      (current-column)))
+                            (delete-region tmp (point)))))
+
+                       (t
+                        ;; Last resort: Just add a single space after
+                        ;; the prefix.
+                        (cons (concat fb-string " ")
+                              (progn (goto-char fb-endpos)
+                                     (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.
+                   (cons (concat (buffer-substring-no-properties
+                                  prefix-line (c-point 'boi))
+                                 comment-prefix)
+                         (progn (back-to-indentation)
+                                (+ (current-column) (length comment-prefix))))
+
+                 ;; Assume we are dealing with a "free text" block
+                 ;; comment where the lines doesn't have any comment
+                 ;; prefix at all and we should just fill it as
+                 ;; normal text.
+                 '("" . 0))))))
+    ))
+
+(defun c-mask-paragraph (fill-paragraph apply-outside-literal fun &rest args)
+  ;; Calls FUN with ARGS ar arguments while the current paragraph is
+  ;; masked to allow adaptive filling to work correctly.  That
+  ;; includes narrowing the buffer and, if point is inside a comment,
+  ;; masking the comment starter and ender appropriately.
+  ;;
+  ;; FILL-PARAGRAPH is non-nil if called for whole paragraph filling.
+  ;; The position of point is then less significant when doing masking
+  ;; and narrowing.
+  ;;
+  ;; If APPLY-OUTSIDE-LITERAL is nil then the function will be called
+  ;; only if the point turns out to be inside a comment or a string.
+  ;;
+  ;; Note that this function does not do any hidden buffer changes.
+
+  (let (fill
+       ;; beg and end limit the region to narrow.  end is a marker.
+       beg end
+       ;; 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
+       ;; 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
+       ;; auto-fill-spaces is the exact sequence of whitespace between a
+       ;; comment's last word and the comment ender, temporarily replaced
+       ;; with 'x's before calling FUN when FILL-PARAGRAPH is nil.
+       auto-fill-spaces
+       (here (point))
+       (c-lit-limits c-lit-limits)
+       (c-lit-type c-lit-type))
+
+    ;; 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)))
+
+    ;; Determine the limits and type of the containing literal (if any):
+    ;; C-LIT-LIMITS, C-LIT-TYPE;  and the limits of the current paragraph:
+    ;; BEG and END.
+    (c-save-buffer-state ()
+      (save-restriction
+       ;; Widen to catch comment limits correctly.
+       (widen)
+       (unless c-lit-limits
+         (setq c-lit-limits (c-literal-limits nil fill-paragraph)))
+       (setq c-lit-limits (c-collect-line-comments c-lit-limits))
+       (unless c-lit-type
+         (setq c-lit-type (c-literal-type c-lit-limits))))
+
+      (save-excursion
+       (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))))
+
+    (unwind-protect
+       (progn
+         ;; For each of the possible types of text (string, C comment ...)
+         ;; determine BEG and END, the region we will narrow to.  If we're in
+         ;; a literal, constrain BEG and END to the limits of this literal.
+         ;;
+         ;; For some of these text types, particularly a block comment, we
+         ;; may need to massage whitespace near literal delimiters, so that
+         ;; these don't get filled inappropriately.
+         (cond
+
+          ((eq c-lit-type 'c++)        ; Line comment.
+           (save-excursion
+             ;; Limit to the comment or paragraph end, whichever
+             ;; comes first.
+             (set-marker end (min end (cdr c-lit-limits)))
+
+             (when (<= beg (car c-lit-limits))
+               ;; The region includes the comment starter, so we must
+               ;; check it.
+               (goto-char (car c-lit-limits))
+               (back-to-indentation)
+               (if (eq (point) (car c-lit-limits))
+                   ;; Include the first line in the region.
+                   (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))))
+
+           (setq apply-outside-literal t))
+
+          ((eq c-lit-type 'c)          ; Block comment.
+           (when
+               (or (> end (cdr c-lit-limits))
+                   (and (= end (cdr c-lit-limits))
+                        (eq (char-before end) ?/)
+                        (eq (char-before (1- end)) ?*)
+                        ;; disallow "/*/"
+                        (> (- (cdr c-lit-limits) (car c-lit-limits)) 3)))
+             ;; There is a comment ender, and the region includes it.  If
+             ;; it's on its own line, it stays on its own line.  If it's got
+             ;; company on the line, it keeps (at least one word of) it.
+             ;; "=====*/" counts as a comment ender here, but "===== */"
+             ;; doesn't and "foo*/" doesn't.
+             (unless
+                 (save-excursion
+                   (goto-char (cdr c-lit-limits))
+                   (beginning-of-line)
+                   (and (search-forward-regexp
+                         (concat "\\=[ \t]*\\(" c-current-comment-prefix "\\)")
+                         (- (cdr c-lit-limits) 2) t)
+                        (not (search-forward-regexp
+                              "\\(\\s \\|\\sw\\)"
+                              (- (cdr c-lit-limits) 2) 'limit))
+                            ;; The comment ender IS on its own line.  Exclude
+                            ;; this line from the filling.
+                        (set-marker end (c-point 'bol))))
+
+               ;; The comment ender is hanging.  Replace all space between it
+               ;; and the last word either by one or two 'x's (when
+               ;; FILL-PARAGRAPH is non-nil), or a row of x's the same width
+               ;; as the whitespace (when auto filling), and include it in
+               ;; the region.  We'll change them back to whitespace
+               ;; afterwards.  The effect of this is to glue the comment
+               ;; ender to the last word in the comment during filling.
+               (let* ((ender-start (save-excursion
+                                     (goto-char (cdr c-lit-limits))
+                                     (skip-syntax-backward "^w ")
+                                     (point)))
+                      (ender-column (save-excursion
+                                      (goto-char ender-start)
+                                      (current-column)))
+                      (point-rel (- ender-start here))
+                      spaces)
+
+                 (save-excursion
+                   ;; Insert a CR after the "*/", adjust END
+                   (goto-char (cdr c-lit-limits))
+                   (setq tmp-post (point-marker))
+                   (insert ?\n)
+                   (set-marker end (point))
+
+                   (forward-line -1)   ; last line of the comment
+                   (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.  IS THIS POSSIBLE?  (ACM,
+                       ;; 2006/4/28).  Remove it along with surrounding ws.
+                       (setq spaces (- (match-end 1) (match-end 2)))
+                     (goto-char ender-start))
+                   (skip-chars-backward " \t\r\n") ; Surely this can be
+                                       ; " \t"? "*/" is NOT alone on the line (ACM, 2005/8/18)
+
+                   ;; What's being tested here?  2006/4/20.  FIXME!!!
+                   (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-column (current-column))))
+                         (setq auto-fill-spaces (c-delete-and-extract-region
+                                                 (point) ender-start))
+                         ;; paragraph filling condenses multiple spaces to
+                         ;; single or double spaces.  auto-fill doesn't.
+                         (if fill-paragraph
+                             (setq spaces
+                                   (max
+                                    (min spaces
+                                         (if sentence-end-double-space 2 1))
+                                    1)))
+                         ;; Insert the filler first to keep marks right.
+                         (insert-char ?x spaces t)
+                         (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 c-lit-limits))
+             ;; The region includes the comment starter.
+             (save-excursion
+               (goto-char (car c-lit-limits))
+               (if (looking-at (concat "\\(" comment-start-skip "\\)$"))
+                   ;; Begin with the next line.
+                   (setq beg (c-point 'bonl))
+                 ;; Fake the fill prefix in the first line.
+                 (setq tmp-pre t))))
+
+           (setq apply-outside-literal t))
+
+          ((eq c-lit-type 'string)     ; String.
+           (save-excursion
+             (when (>= end (cdr c-lit-limits))
+               (goto-char (1- (cdr c-lit-limits)))
+               (setq tmp-post (point-marker))
+               (insert ?\n)
+               (set-marker end (point)))
+             (when (<= beg (car c-lit-limits))
+               (goto-char (1+ (car c-lit-limits)))
+               (setq beg (if (looking-at "\\\\$")
+                             ;; Leave the start line if it's
+                             ;; nothing but an escaped newline.
+                             (1+ (match-end 0))
+                           (point)))))
+           (setq apply-outside-literal t))
+
+          ((eq c-lit-type 'pound)      ; Macro
+           ;; Narrow to the macro limits if they are nearer than the
+           ;; paragraph limits.  Don't know if this is necessary but
+           ;; do it for completeness sake (doing auto filling at all
+           ;; inside macros is bogus to begin with since the line
+           ;; continuation backslashes aren't handled).
+           (save-excursion
+             (c-save-buffer-state ()
+               (c-beginning-of-macro)
+               (beginning-of-line)
+               (if (> (point) beg)
+                   (setq beg (point)))
+               (c-end-of-macro)
+               (forward-line)
+               (if (< (point) end)
+                   (set-marker end (point))))))
+
+          (t                           ; Other code.
+           ;; Try to avoid comments and macros in the paragraph to
+           ;; avoid that the adaptive fill mode gets the prefix from
+           ;; them.
+           (c-save-buffer-state nil
+             (save-excursion
+               (goto-char beg)
+               (c-forward-syntactic-ws end)
+               (beginning-of-line)
+               (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))
+         (if (or fill-paragraph (not auto-fill-spaces))
+             (insert-char ?\  hang-ender-stuck t)
+           (insert auto-fill-spaces)
+           (setq here (- here (- hang-ender-stuck (length auto-fill-spaces)))))
+         (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.
+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
@@ -1578,275 +4138,312 @@ 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* ((point-save (point-marker))
-        limits
-        comment-start-place
-        (first-line
-         ;; Check for obvious entry to comment.
-         (save-excursion
-           (beginning-of-line)
-           (skip-chars-forward " \t")
-           (and (looking-at comment-start-skip)
-                (setq comment-start-place (point)))))
-        (re1 "\\|\\([ \t]*/\\*[ \t]*\\|[ \t]*\\*/[ \t]*\\|[ \t/*]*\\)"))
-    (if (save-excursion
-         (beginning-of-line)
-         (looking-at ".*//"))
-       (let ((fill-prefix fill-prefix)
-              ;; Lines containing just a comment start or just an end
-              ;; should not be filled into paragraphs they are next
-              ;; to.
-             (paragraph-start (concat paragraph-start re1 "$"))
-             (paragraph-separate (concat paragraph-separate re1 "$")))
-         (save-excursion
-           (beginning-of-line)
-           ;; Move up to first line of this comment.
-           (while (and (not (bobp))
-                       (looking-at "[ \t]*//[ \t]*[^ \t\n]"))
-             (forward-line -1))
-           (if (not (looking-at ".*//[ \t]*[^ \t\n]"))
-               (forward-line 1))
-           ;; Find the comment start in this line.
-           (re-search-forward "[ \t]*//[ \t]*")
-           ;; Set the fill-prefix to be what all lines except the first
-           ;; should start with.  But do not alter a user set fill-prefix.
-           (if (null fill-prefix)
-               (setq fill-prefix (buffer-substring (match-beginning 0)
-                                                   (match-end 0))))
-           (save-restriction
-             ;; Narrow down to just the lines of this comment.
-             (narrow-to-region (c-point 'bol)
-                               (save-excursion
-                                 (forward-line 1)
-                                 (while
-                                     (looking-at (regexp-quote fill-prefix))
-                                   (forward-line 1))
-                                 (point)))
-             (or (c-safe
-                  ;; fill-paragraph sometimes fails to detect when we
-                  ;; are between paragraphs.
-                  (beginning-of-line)
-                  (search-forward fill-prefix (c-point 'eol))
-                  (looking-at paragraph-separate))
-                 ;; Avoids recursion
-                 (let (fill-paragraph-function)
-                   (fill-paragraph arg))))))
-      ;; else C style comments
-      (if (or first-line
-             ;; t if we enter a comment between start of function and
-             ;; this line.
-             (save-excursion
-               (setq limits (c-literal-limits))
-               (and (consp limits)
-                    (save-excursion
-                      (goto-char (car limits))
-                      (looking-at c-comment-start-regexp))))
-             ;; t if this line contains a comment starter.
-             (setq first-line
-                   (save-excursion
-                     (beginning-of-line)
-                     (prog1
-                         (re-search-forward comment-start-skip
-                                            (save-excursion (end-of-line)
-                                                            (point))
-                                            t)
-                       (setq comment-start-place (point)))))
-             ;; t if we're in the whitespace after a comment ender
-             ;; which ends its line.
-             (and (not limits)
-                  (when (and (looking-at "[ \t]*$")
-                             (save-excursion
-                               (beginning-of-line)
-                               (looking-at ".*\\*/[ \t]*$")))
-                    (save-excursion
-                      (forward-comment -1)
-                      (setq comment-start-place (point)))
-                    t)))
-         ;; Inside a comment: fill one comment paragraph.
-         (let ((fill-prefix
-                (or
-                 ;; Keep user set fill prefix if any.
-                 fill-prefix
-                 ;; The prefix for each line of this paragraph
-                 ;; is the appropriate part of the start of this line,
-                 ;; up to the column at which text should be indented.
-                 (save-excursion
-                   (beginning-of-line)
-                   (if (looking-at ".*/\\*.*\\*/")
-                       (progn (re-search-forward comment-start-skip)
-                              (make-string (current-column) ?\ ))
-                     (if first-line
-                         (forward-line 1)
-                       (if (and (looking-at "[ \t]*\\*/")
-                                (not (save-excursion
-                                       (forward-line -1)
-                                       (looking-at ".*/\\*"))))
-                           (forward-line -1)))
-
-                     (let ((line-width (progn (end-of-line)
-                                              (current-column))))
-                       (beginning-of-line)
-                       (prog1
-                           (buffer-substring
-                            (point)
+  (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)
 
-                            ;; How shall we decide where the end of the
-                            ;; fill-prefix is?
-                            (progn
-                              (skip-chars-forward " \t*" (c-point 'eol))
-                              ;; kludge alert, watch out for */, in
-                              ;; which case fill-prefix should *not*
-                              ;; be "*"!
-                              (if (and (eq (char-after) ?/)
-                                       (eq (char-before) ?*))
-                                  (forward-char -1))
-                              (point)))
-
-                         ;; If the comment is only one line followed
-                         ;; by a blank line, calling move-to-column
-                         ;; above may have added some spaces and tabs
-                         ;; to the end of the line; the fill-paragraph
-                         ;; function will then delete it and the
-                         ;; newline following it, so we'll lose a
-                         ;; blank line when we shouldn't.  So delete
-                         ;; anything move-to-column added to the end
-                         ;; of the line.  We record the line width
-                         ;; instead of the position of the old line
-                         ;; end because move-to-column might break a
-                         ;; tab into spaces, and the new characters
-                         ;; introduced there shouldn't be deleted.
-
-                         ;; If you can see a better way to do this,
-                         ;; please make the change.  This seems very
-                         ;; messy to me.
-                         (delete-region (progn (move-to-column line-width)
-                                               (point))
-                                        (progn (end-of-line) (point)))))))))
-
-               ;; Lines containing just a comment start or just an end
-               ;; should not be filled into paragraphs they are next
-               ;; to.
-               (paragraph-start (if (c-major-mode-is 'java-mode)
-                                    (concat paragraph-start
-                                            re1 "\\("
-                                            c-Java-javadoc-paragraph-start
-                                            "\\|$\\)")
-                                  (concat paragraph-start re1 "$")))
-               (paragraph-separate (concat paragraph-separate re1 "$"))
-               (chars-to-delete 0)
-               )
-           (save-restriction
-             ;; Don't fill the comment together with the code
-             ;; following it.  So temporarily exclude everything
-             ;; before the comment start, and everything after the
-             ;; line where the comment ends.  If comment-start-place
-             ;; is non-nil, the comment starter is there.  Otherwise,
-             ;; point is inside the comment.
-             (narrow-to-region (save-excursion
-                                 (if comment-start-place
-                                     (goto-char comment-start-place)
-                                   (search-backward "/*"))
-                                 (if (and (not c-hanging-comment-starter-p)
-                                          (looking-at
-                                           (concat c-comment-start-regexp
-                                                   "[ \t]*$")))
-                                     (forward-line 1))
-                                 ;; Protect text before the comment
-                                 ;; start by excluding it.  Add
-                                 ;; spaces to bring back proper
-                                 ;; indentation of that point.
-                                 (let ((column (current-column)))
-                                   (prog1 (point)
-                                     (setq chars-to-delete column)
-                                     (insert-char ?\  column))))
-                               (save-excursion
-                                 (if comment-start-place
-                                     (goto-char (+ comment-start-place 2)))
-                                 (search-forward "*/" nil 'move)
-                                 (if (and (not c-hanging-comment-ender-p)
-                                          (save-excursion
-                                            (beginning-of-line)
-                                            (looking-at "[ \t]*\\*/")))
-                                     (beginning-of-line)
-                                   (forward-line 1))
-                                 (point)))
-             (or (c-safe
-                  ;; fill-paragraph sometimes fails to detect when we
-                  ;; are between paragraphs.
-                  (beginning-of-line)
-                  (search-forward fill-prefix (c-point 'eol))
-                  (looking-at paragraph-separate))
-                 ;; Avoids recursion
-                 (let (fill-paragraph-function)
-                   (fill-paragraph arg)))
-             (save-excursion
-               ;; Delete the chars we inserted to avoid clobbering
-               ;; the stuff before the comment start.
-               (goto-char (point-min))
-               (if (> chars-to-delete 0)
-                   (delete-region (point) (+ (point) chars-to-delete)))
-               ;; Find the comment ender (should be on last line of
-               ;; buffer, given the narrowing) and don't leave it on
-               ;; its own line, unless that's the style that's desired.
-               (goto-char (point-max))
-               (forward-line -1)
-               (search-forward "*/" nil 'move)
-               (beginning-of-line)
-               (if (and c-hanging-comment-ender-p
-                        (looking-at "[ \t]*\\*/"))
-                   ;(delete-indentation)))))
-                   (let ((fill-column (+ fill-column 9999)))
-                     (forward-line -1)
-                     (fill-region-as-paragraph (point) (point-max))
-                     ;; If fill-prefix ended with a `*', it may be
-                     ;; taken away from the comment ender.  We got to
-                     ;; check this and put it back if that is the
-                     ;; case.
-                     (goto-char (- (point-max) 2))
-                     (if (not (= (char-before) ?*))
-                         (insert ?*))
-                     )))))
-       ;; Else maybe a string.  Fill it if it's a multiline string.
-       ;; FIXME: This currently doesn't handle escaped newlines.
-       ;; Doing that correctly is a bit tricky.
-       (if (and limits
-                (eq (char-syntax (char-after (car limits))) ?\")
-                (save-excursion
-                  (goto-char (car limits))
-                  (end-of-line)
-                  (< (point) (cdr limits))))
-           (let (fill-paragraph-function)
-             (save-restriction
-               (narrow-to-region (save-excursion
-                                   (goto-char (1+ (car limits)))
-                                   (if (looking-at "\\\\$")
-                                       ;; Some DWIM: Leave the start
-                                       ;; line if it's nothing but an
-                                       ;; escaped newline.
-                                       (1+ (match-end 0))
-                                     (point)))
-                                 (save-excursion
-                                   (goto-char (1- (cdr limits)))
-                                   ;; Inserting a newline and
-                                   ;; removing it again after
-                                   ;; fill-paragraph makes it more
-                                   ;; predictable.
-                                   (insert ?\n)
-                                   (point)))
-               ;; Do not compensate for the narrowed column.  This
-               ;; way the literal will always be filled at the same
-               ;; column internally.
-               (fill-paragraph arg)
-               (goto-char (1- (point-max)))
-               (delete-char 1)))
+(defun c-do-auto-fill ()
+  ;; Do automatic filling if not inside a context where it should be
+  ;; ignored.
+  (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))
+
+    (c-save-buffer-state ()
+      (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 (concat "\\`[ \t]*"
+                                                 c-line-comment-starter)
+                                         (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)))
          )))
-    (goto-char (marker-position point-save))
-    (set-marker point-save 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.
-    t))
+
+    (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))
+         ((c-save-buffer-state ()
+            (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))
+                    (start-col (current-column))
+                    (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".
+                ;;
+                ;; If we have an empty comment, /*   */, the next
+                ;; lot of code pushes point to the */.  We fix
+                ;; this by never allowing point to end up to the
+                ;; right of where it started.
+                (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))
+                  (if (> (current-column) start-col)
+                      (move-to-column start-col)))) ; can this hit the
+                                                    ; middle of a TAB?
+            ;; 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.
+
+When point is inside a string, only insert a backslash when it is also
+inside a preprocessor directive."
+
+  (interactive "*")
+  (let* (c-lit-limits c-lit-type
+        (c-macro-start c-macro-start))
+
+    (c-save-buffer-state ()
+      (setq c-lit-limits (c-literal-limits nil nil t)
+           c-lit-type (c-literal-type c-lit-limits))
+      (when (eq c-lit-type 'c++)
+       (setq c-lit-limits (c-collect-line-comments c-lit-limits)))
+      (c-query-and-set-macro-start))
+
+    (cond
+     ((or (eq c-lit-type 'c)
+         (and (eq c-lit-type 'c++) ; C++ comment, but not at the very end of it.
+              (< (save-excursion
+                   (skip-chars-forward " \t")
+                   (point))
+                 (1- (cdr c-lit-limits))))
+         (and (numberp c-macro-start)  ; Macro, but not at the very end of
+                                       ; it, not in a string, and not in the
+                                       ; cpp keyword.
+              (not (eq c-lit-type 'string))
+              (or (not (looking-at "\\s *$"))
+                  (eq (char-before) ?\\))
+              (<= (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)))
+
+     ((eq c-lit-type 'string)
+      (if (and (numberp c-macro-start)
+              (not (eq (char-before) ?\\)))
+         (insert ?\\))
+      (newline))
+
+     (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
+                    (backward-char)
+                    (forward-line 0)
+                    (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))))
 
 \f
-(provide 'cc-cmds)
+(cc-provide 'cc-cmds)
+
+;;; arch-tag: bf0611dc-d1f4-449e-9e45-4ec7c6936677
 ;;; cc-cmds.el ends here