diff lisp/progmodes/cc-cmds.el @ 90261:7beb78bc1f8e

Revision: miles@gnu.org--gnu-2005/emacs--unicode--0--patch-97 Merge from emacs--cvs-trunk--0 Patches applied: * emacs--cvs-trunk--0 (patch 616-696) - Add lisp/mh-e/.arch-inventory - Update from CVS - Merge from gnus--rel--5.10 - Update from CVS: lisp/smerge-mode.el: Add 'tools' to file keywords. - lisp/gnus/ChangeLog: Remove duplicate entry * gnus--rel--5.10 (patch 147-181) - Update from CVS - Merge from emacs--cvs-trunk--0 - Update from CVS: lisp/mml.el (mml-preview): Doc fix. - Update from CVS: texi/message.texi: Fix default values. - Update from CVS: texi/gnus.texi (RSS): Addition.
author Miles Bader <miles@gnu.org>
date Mon, 16 Jan 2006 08:37:27 +0000
parents b1c1fc853d2f 04d2abb755d9
children 4b3d39451150
line wrap: on
line diff
--- a/lisp/progmodes/cc-cmds.el	Mon Jan 16 06:59:21 2006 +0000
+++ b/lisp/progmodes/cc-cmds.el	Mon Jan 16 08:37:27 2006 +0000
@@ -1,6 +1,7 @@
 ;;; cc-cmds.el --- user level commands for CC Mode
 
-;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software Foundation, Inc.
+;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software Foundation,
+;; Inc.
 
 ;; Authors:    1998- Martin Stjernholm
 ;;             1992-1999 Barry A. Warsaw
@@ -24,7 +25,7 @@
 ;; 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
+;; 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.
 
@@ -45,12 +46,11 @@
 (cc-require 'cc-engine)
 
 ;; Silence the compiler.
-(cc-bytecomp-defvar delete-key-deletes-forward) ; XEmacs 20+
-(cc-bytecomp-defun delete-forward-p)	; XEmacs 21+
-(cc-bytecomp-obsolete-fun insert-and-inherit) ; Marked obsolete in XEmacs 19
+(cc-bytecomp-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)
 
 (defvar c-fix-backslashes t)
 
@@ -64,8 +64,6 @@
 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)."
-  ;;
-  ;; This function does not do any hidden buffer changes.
 
   (let ((line-cont-backslash (save-excursion
 			       (end-of-line)
@@ -134,13 +132,11 @@
     shift-amt))
 
 (defun c-newline-and-indent (&optional newline-arg)
-  "Inserts a newline and indents the new line.
+  "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."
-  ;;
-  ;; This function does not do any hidden buffer changes.
 
   ;; TODO: Backslashes before eol in comments and literals aren't
   ;; kept intact.
@@ -221,14 +217,30 @@
 		   (c-save-buffer-state nil
 		     (c-guess-basic-syntax)))))
     (if (not (consp arg))
-	(message "syntactic analysis: %s" syntax)
+	(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)
-  "Inserts a comment with the syntactic analysis on every line in the region."
+  "Insert a comment with the syntactic analysis on every line in the region."
   (interactive "*r")
   (save-excursion
     (save-restriction
@@ -239,6 +251,23 @@
 	(forward-line)))))
 
 
+(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"
+		       ""))))
+    (setq c-submode-indicators
+	  (if (> (length fmt) 1)
+	      fmt))
+    (force-mode-line-update)))
+
 (defun c-toggle-syntactic-indentation (&optional arg)
   "Toggle syntactic indentation.
 Optional numeric ARG, if supplied, turns on syntactic indentation when
@@ -249,12 +278,12 @@
 functions and the electric keys indent according to the syntactic
 context keys, when applicable.
 
-When it's turned off, the electric keys does no reindentation, the
-indentation functions indents every new line to the same level as the
-previous nonempty line, and \\[c-indent-command] adjusts the
-indentation in seps specified `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'.
+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")
@@ -262,30 +291,36 @@
 	(c-calculate-state arg c-syntactic-indentation))
   (c-keep-region-active))
 
-(defun c-toggle-auto-state (&optional arg)
+(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 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))
 
+(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 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)
@@ -297,27 +332,38 @@
 hungry-delete when positive, turns them off when negative, and just
 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))
+
 
 ;; Electric keys
 
 (defun c-electric-backspace (arg)
   "Delete the 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 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."
+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))
     (c-hungry-backspace)))
 
@@ -334,15 +380,16 @@
 
 (defun c-electric-delete-forward (arg)
   "Delete the following 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 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."
+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 (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-delete-function (prefix-numeric-value arg))
     (c-hungry-delete-forward)))
 
@@ -361,43 +408,54 @@
 (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 (XEmacs 21) and returns
-non-nil, it deletes forward.  Else, if the variable
-`delete-key-deletes-forward' is defined (XEmacs 20) and is set to
-non-nil, it deletes forward.  Otherwise it deletes backward.
-
-Note: This is the way in XEmacs 20 and later to choose the correct
-action for the [delete] key, whichever key that means.  In other
-flavors this function isn't used, instead it's left to the user to
-bind [delete] to either \\[c-electric-delete-forward] or \\[c-electric-backspace] as appropriate
-\(the keymap `function-key-map' is useful for that).  Emacs 21 handles
-that automatically, though."
+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.
+
+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 (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-backspace)))
+
 (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 or a macro, 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)))
-	  (save-excursion
-	    (and (= (forward-line -1) 0)
-		 (progn (end-of-line)
-			(eq (char-before) ?\\))))
-	  (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
@@ -410,243 +468,332 @@
 	   (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'.
-
-Also, the line is re-indented unless a numeric ARG is supplied, the
-brace is inserted inside a literal, or `c-syntactic-indentation' is
-nil.
-
-This function does various newline cleanups based on the value of
-`c-cleanup-list'."
+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:
+
+\(a) If the auto-newline feature is turned on (indicated by \"/ln\" 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."
+
   (interactive "*P")
-  (let* ((safepos (c-safe-position (point) (c-parse-state)))
-	 (literal (c-in-literal safepos))
-	 ;; 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)
-    (cond
-     ((or literal arg)
-      (self-insert-command (prefix-numeric-value arg)))
-     ((not (looking-at "[ \t]*\\\\?$"))
-      (self-insert-command (prefix-numeric-value arg))
-      (if c-syntactic-indentation
-	  (indent-according-to-mode)))
-     (t
-      (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
-		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))
-	     (insertion-point (point))
-	     (preserve-p (and (not (bobp))
-			      (eq ?\  (char-syntax (char-before)))))
-	     ;; shut this up too
-	     (c-echo-syntactic-information-p nil)
-	     delete-temp-newline syntax newlines)
-	;; only insert a newline if there is non-whitespace behind us
-	(when (save-excursion
-		(skip-chars-backward " \t")
-		(not (bolp)))
-	  (c-newline-and-indent)
-	  ;; Set markers around the newline and indention inserted
-	  ;; above.  We insert the start marker here and not before
-	  ;; the call to kludge around a misfeature in expand-abbrev:
-	  ;; If the line contains e.g. "else" then expand-abbrev will
-	  ;; be called when c-newline-and-indent inserts the newline.
-	  ;; That function first removes the abbrev "else" and then
-	  ;; inserts the expansion, which is an identical "else" in
-	  ;; this case.  So the marker that we put after "else" would
-	  ;; end up before it.
-	  (setq delete-temp-newline
-		(cons (save-excursion
-			(end-of-line 0)
-			(if (eq (char-before) ?\\)
-			    ;; Ignore a line continuation.
-			    (backward-char))
-			(skip-chars-backward " \t")
-			(copy-marker (point) t))
-		      (point-marker))))
-	(unwind-protect
-	    (progn
-	      (if (eq last-command-char ?{)
-		  (setq c-state-cache (cons (point) c-state-cache)))
-	      (self-insert-command (prefix-numeric-value arg))
-	      (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.
-		(setq syntax (c-guess-basic-syntax)))
-	      (setq 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
-		       (save-excursion
-			 (c-save-buffer-state nil
-			   (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?
-	      (when (memq 'before newlines)
-		;; we leave the newline we've put in there before,
-		;; but we need to re-indent the line above
-		(when delete-temp-newline
-		  (set-marker (car delete-temp-newline) nil)
-		  (set-marker (cdr delete-temp-newline) nil)
-		  (setq delete-temp-newline nil))
-		(when c-syntactic-indentation
-		  (let ((pos (- (point-max) (point)))
-			(here (point)))
-		    (forward-line -1)
-		    (indent-according-to-mode)
-		    (goto-char (- (point-max) pos))
-		    ;; if the buffer has changed due to the
-		    ;; indentation, we need to recalculate syntax for
-		    ;; the current line.
-		    (if (/= (point) here)
-			(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.
-			  (setq syntax (c-guess-basic-syntax))))))))
-	  ;; must remove the newline we just stuck in (if we really did it)
-	  (when delete-temp-newline
-	    (save-excursion
-	      (delete-region (car delete-temp-newline)
-			     (cdr delete-temp-newline))
-	      (goto-char (car delete-temp-newline))
-	      (set-marker (car delete-temp-newline) nil)
-	      (set-marker (cdr delete-temp-newline) nil)
-	      ;; if there is whitespace before point, then preserve
-	      ;; at least one space.
-	      (just-one-space)
-	      (if (not preserve-p)
-		  (delete-char -1)))))
-	(if (not (memq 'before newlines))
-	    ;; since we're hanging the brace, we need to recalculate
-	    ;; syntax.
-	    (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.
-	      (setq syntax (c-guess-basic-syntax))))
-	(when c-syntactic-indentation
-	  ;; Now adjust the line's indentation.  Don't update the state
-	  ;; cache since c-guess-basic-syntax isn't called when
-	  ;; c-syntactic-context is set.
-	  (let* ((c-syntactic-context syntax))
-	    (indent-according-to-mode)))
-	;; Do all appropriate clean ups
-	(let ((here (point))
-	      (pos (- (point-max) (point)))
-	      mbeg mend tmp)
-	  ;; 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)
-		     (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)))
-	  ;; clean up brace-else-brace and brace-elseif-brace
-	  (when (and c-auto-newline
-		     (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)
-		   (progn
-		     (setq mbeg (match-beginning 0)
-			   mend (match-end 0))
-		     (eq (match-end 0) here)))
-	      (delete-region mbeg mend)
-	      (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))
-	  )
-	;; does a newline go after the brace?
-	(if (memq 'after newlines)
-	    (c-newline-and-indent))
-	)))
+  (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 mbeg mend)
+		  (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))
+
+	      ;; 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)
@@ -659,332 +806,465 @@
 (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 a numeric ARG is supplied, point is inside a literal, or
-`c-syntactic-indentation' is nil, indentation is inhibited."
+`c-syntactic-indentation' is nil or `c-electric-flag' is nil, indentation
+is inhibited."
   (interactive "*P")
-  (let* ((ch (char-before))
-	 (literal (c-in-literal))
-	 (indentp (and c-syntactic-indentation
-		       (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 ?/)
+	; (eq c-block-comment-ender "*/") ; C-style comments ALWAYS end in */
+	       (save-excursion
+		 (back-to-indentation)
+		 (looking-at (concat c-current-comment-prefix "[ \t]*$"))))
+      (end-of-line)
+      (delete-horizontal-space)
+      (or (eq (char-before) ?*) (insert-char ?* 1))) ; 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 literal))
-			   (and (eq ch ?*)
-				literal))
-		       ))
-	 ;; shut this up
-	 (c-echo-syntactic-information-p nil))
+		       (eq (char-before) (if literal ?* ?/))))
     (self-insert-command (prefix-numeric-value arg))
     (if indentp
 	(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 a numeric ARG is supplied, point is inside a literal, or
-`c-syntactic-indentation' is nil, 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 c-syntactic-indentation
-	   (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)))
+  (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 a semicolon is inserted, the line is re-indented unless a numeric
-arg is supplied, point is inside a literal, or
-`c-syntactic-indentation' is nil.
-
-Based on the value of `c-cleanup-list', this function cleans up commas
-following brace lists and semicolons following defuns."
+
+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 \"/ln\" on
+the mode line) a newline might be inserted.  See the variable
+`c-hanging-semi&comma-criteria' for how newline insertion is determined.
+
+\(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)
-	(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 (or (not c-auto-newline)
-	      (not (looking-at "[ \t]*\\\\?$")))
-	  (if c-syntactic-indentation
-	      (indent-according-to-mode))
-	;; 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)
-		     (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)))
-	;; re-indent line
-	(if c-syntactic-indentation
-	    (indent-according-to-mode))
-	;; 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))
-	  )))))
+
+    (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'.
-
-Also, the line is re-indented unless a numeric ARG is supplied, the
-colon is inserted inside a literal, or `c-syntactic-indentation' is
-nil.
-
-This function cleans up double colon scope operators based on the
-value of `c-cleanup-list'."
+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 \"/ln\" on
+the mode line) newlines are inserted before and after the colon based on
+the settings in `c-hanging-colons-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, whitespace between two colons will be
+\"cleaned up\" leaving a scope operator, if this action is set in
+`c-cleanup-list'."
+
   (interactive "*P")
   (let* ((bod (c-point 'bod))
-	 (literal (c-in-literal bod))
+	 (literal (c-save-buffer-state () (c-in-literal bod)))
 	 newlines is-scope-op
 	 ;; shut this up
 	 (c-echo-syntactic-information-p nil))
-    (cond
-     ((or literal arg)
-      (self-insert-command (prefix-numeric-value arg)))
-     ((not (looking-at "[ \t]*\\\\?$"))
-      (self-insert-command (prefix-numeric-value arg))
-      (if c-syntactic-indentation
-	  (indent-according-to-mode)))
-     (t
-      ;; 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)
-		   (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))
-      (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))
-      ))))
+    (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, point is inside a
-literal, or `c-syntactic-indentation' is nil, 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 c-syntactic-indentation
-		      (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
-	(indent-according-to-mode))))
+    (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.
 
-Some newline cleanups are done if appropriate; see the variable
-`c-cleanup-list'.
-
-Also, the line is re-indented unless a numeric ARG is supplied, the
-parenthesis is inserted inside a literal, or `c-syntactic-indentation'
-is nil."
+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, 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 ((literal (c-in-literal (c-point 'bod)))
+  (let ((literal (c-save-buffer-state () (c-in-literal)))
 	;; shut this up
 	(c-echo-syntactic-information-p nil))
-    (if (or arg literal)
-	(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
-	     (noblink (eq last-input-event ?\()))
-	(self-insert-command (prefix-numeric-value arg))
-	(if c-syntactic-indentation
-	    (indent-according-to-mode))
-	(when (looking-at "[ \t]*\\\\?$")
-	  (when c-auto-newline
-	    ;; Do all appropriate clean ups
-	    (let ((here (point))
-		  (pos (- (point-max) (point)))
-		  mbeg mend)
-	      ;; clean up brace-elseif-brace
-	      (if (and (memq 'brace-elseif-brace c-cleanup-list)
-		       (eq last-command-char ?\()
-		       (re-search-backward
-			(concat "}"
-				"\\([ \t\n]\\|\\\\\n\\)*"
-				"else"
-				"\\([ \t\n]\\|\\\\\n\\)+"
-				"if"
-				"\\([ \t\n]\\|\\\\\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-and-inherit "} else if ("))
-		;; clean up brace-catch-brace
-		(goto-char here)
-		(if (and (memq 'brace-catch-brace c-cleanup-list)
-			 (eq last-command-char ?\()
-			 (re-search-backward
-			  (concat "}"
-				  "\\([ \t\n]\\|\\\\\n\\)*"
-				  "catch"
-				  "\\([ \t\n]\\|\\\\\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-and-inherit "} catch ("))))
-	      (goto-char (- (point-max) pos))
-	      )))
-	(let (beg (end (1- (point))))
-	  (cond ((and (memq 'space-before-funcall c-cleanup-list)
-		      (eq last-command-char ?\()
-		      (save-excursion
-			(backward-char)
-			(skip-chars-backward " \t")
-			(setq beg (point))
-			(c-on-identifier)))
-		 (save-excursion
-		   (delete-region beg end)
-		   (goto-char beg)
-		   (insert ?\ )))
-		((and (memq 'compact-empty-funcall c-cleanup-list)
-		      (eq last-command-char ?\))
-		      (save-excursion
-			(c-safe (backward-char 2))
-			(when (looking-at "()")
-			  (setq end (point))
-			  (skip-chars-backward " \t")
-			  (setq beg (point))
-			  (c-on-identifier))))
-		 (delete-region beg end))))
-	(and (not executing-kbd-macro)
-	     old-blink-paren
-	     (not noblink)
-	     (funcall old-blink-paren))))))
+    (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
+	    (when
+		(and (memq 'brace-elseif-brace c-cleanup-list)
+		     (eq last-command-char ?\()
+		     (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
+	    (when
+		(and (memq 'brace-catch-brace c-cleanup-list)
+		     (eq last-command-char ?\()
+		     (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))
+		     (c-save-buffer-state () (c-on-identifier))))
+	      (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.
@@ -995,16 +1275,18 @@
 
 The line is reindented if there is nothing but whitespace before the
 keyword on the line, the keyword is not inserted inside a literal, and
-`c-syntactic-indentation' is non-nil."
+`c-electric-flag' and `c-syntactic-indentation' are both non-nil."
   (let (;; shut this up
 	(c-echo-syntactic-information-p nil))
-    (when (and c-syntactic-indentation
-	       (not (eq last-command-char ?_))
-	       (= (save-excursion
-		    (skip-syntax-backward "w")
-		    (point))
-		  (c-point 'boi))
-	       (not (c-in-literal (c-point 'bod))))
+    (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
@@ -1016,36 +1298,19 @@
 	(delete-char -2)))))
 
 
-;; better movement routines for ThisStyleOfVariablesCommonInCPlusPlus
-;; originally contributed by Terry_Glanfield.Southern@rxuk.xerox.com
 (defun c-forward-into-nomenclature (&optional arg)
-  "Move forward to end of a nomenclature section or word.
-With arg, do it arg times."
+  "Compatibility alias for `c-forward-subword'."
   (interactive "p")
-  (let ((case-fold-search nil))
-    (if (> arg 0)
-	(re-search-forward
-	 (cc-eval-when-compile
-	   (concat "\\W*\\([" c-upper "]*[" c-lower c-digit "]*\\)"))
-	 (point-max) t arg)
-      (while (and (< arg 0)
-		  (re-search-backward
-		   (cc-eval-when-compile
-		     (concat
-		      "\\(\\(\\W\\|[" c-lower c-digit "]\\)[" c-upper "]+"
-		      "\\|\\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.
@@ -1246,6 +1511,8 @@
   ;; 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
@@ -1369,6 +1636,604 @@
       (push-mark (cdr decl-limits) nil t))))
 
 
+(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
@@ -1382,318 +2247,93 @@
 to search for the syntactic context, and a flag saying whether to do
 sentence motion in or near comments and multiline strings.
 
-Note that `c-beginning-of-statement-1' is usually better to use from
-programs.  It has much more well defined semantics than this one,
-which is intended for interactive use and might therefore change to be
-more \"DWIM:ey\"."
+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))
-  (c-save-buffer-state
-      ((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)
-		(if (c-backward-single-comment)
-		    (setq range (cons (point)
-				      (progn (c-forward-single-comment)
-					     (point))))
-		  (c-skip-ws-backward)
-		  (setq range (point))
-		  (setq range
-			(if (eq (char-before) ?\")
-			    (c-safe (c-backward-sexp 1)
-				    (cons (point) range)))))
-	      (c-skip-ws-forward)
-	      (if (eq (char-after) ?\")
-		  (setq range (cons (point)
-				    (progn
-				      (c-forward-sexp 1)
-				      (point))))
-		(setq range (point))
-		(setq range (if (c-forward-single-comment)
-				(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
-		   (or (/= (char-syntax (char-after (car range))) ?\")
-		       ;; Only visit a string if it spans more than one line.
-		       (save-excursion
-			 (goto-char (car range))
-			 (skip-chars-forward "^\n" (cdr range))
-			 (< (point) (cdr range)))))
-	      (let* ((lit-type (c-literal-type range))
-		     (line-prefix (concat "[ \t]*\\("
-					  c-current-comment-prefix
-					  "\\)[ \t]*"))
-		     (beg (if (eq lit-type 'string)
-			      (1+ (car range))
-			    (save-excursion
-			      (goto-char (car range))
-			      (max (progn
-				     (looking-at comment-start-skip)
-				     (match-end 0))
-				   (progn
-				     (looking-at line-prefix)
-				     (match-end 0))))))
-		     (end (- (cdr range) (if (eq lit-type 'c) 2 1)))
-		     (beg-of-para (if (eq lit-type 'string)
-				      (lambda ())
-				    (lambda ()
-				      (beginning-of-line)
-				      (if (looking-at line-prefix)
-					  (goto-char (match-end 0)))))))
-		(save-restriction
-		  ;; Move by sentence, but not past the limit of the
-		  ;; literal, narrowed to the appropriate
-		  ;; paragraph(s).
-		  (narrow-to-region (save-excursion
-				      (let ((pos (min here end)))
-					(goto-char pos)
-					(forward-paragraph -1)
-					(if (looking-at paragraph-separate)
-					    (forward-line))
-					(when (> (point) beg)
-					  (funcall beg-of-para)
-					  (when (>= (point) pos)
-					    (forward-paragraph -2)
-					    (funcall beg-of-para)))
-					(max (point) beg)))
-				    end)
-		  (c-safe (forward-sentence (if (< count 0) 1 -1)))
-		  (if (and (memq lit-type '(c c++))
-			   ;; Check if we stopped due to a comment
-			   ;; prefix and not a sentence end.
-			   (/= (point) (point-min))
-			   (/= (point) (point-max))
-			   (save-excursion
-			     (beginning-of-line)
-			     (looking-at line-prefix))
-			   (>= (point) (match-beginning 0))
-			   (/= (match-beginning 1) (match-end 1))
-			   (or (< (point) (match-end 0))
-			       (and
-				(= (point) (match-end 0))
-				;; The comment prefix may contain
-				;; characters that is regarded as end
-				;; of sentence.
-				(or (eolp)
-				    (and
-				     (save-excursion
-				       (forward-paragraph -1)
-				       (< (point) (match-beginning 0)))
-				     (save-excursion
-				       (beginning-of-line)
-				       (or (not (re-search-backward
-						 (sentence-end)
-						 (c-point 'bopl)
-						 t))
-					   (< (match-end 0)
-					      (c-point 'eol)))))))))
-		      (setq count (+ count (if (< count 0) -1 1)))
-		    (if (< count 0)
-			(progn
-			  ;; In block comments, if there's only
-			  ;; horizontal ws between the text and the
-			  ;; comment ender, stop before it.  Stop after
-			  ;; the ender if there's either nothing or
-			  ;; newlines between.
-			  (when (and (eq lit-type 'c)
-				     (eq (point) (point-max)))
-			    (widen)
-			    (when (or (= (skip-chars-backward " \t") 0)
-				      (eq (point) (point-max))
-				      (bolp))
-			      (goto-char (cdr range)))))
-		      (when (and (eq (point) (point-min))
-				 (looking-at "[ \t]*\\\\?$"))
-			;; Stop before instead of after the comment
-			;; starter if nothing follows it.
-			(widen)
-			(goto-char (car range))
-			(if (and (eq lit-type 'string) (/= (point) here))
-			    (setq count (1+ count)
-				  range nil))))))
-		;; See if we should escape the literal.
-		(if (> count 0)
-		    (if (< (point) here)
-			(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))
-	(goto-char here)
-	(if (> count 0)
-	    (condition-case nil
-		;; 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.
-		(let ((literal-pos (not sentence-flag))
-		      last last-below-line)
-		  (catch 'done
-		    (while t
-		      (setq last (point))
-		      (when (and (or (eq (char-after) ?\{)
-				     (and (eq (char-after) ?#)
-					  (eq (point) (c-point 'boi)))
-				     )
-				 (/= here last))
-			(unless (and c-special-brace-lists
-				     (eq (char-after) ?{)
-				     (c-looking-at-special-brace-list))
-			  (if (and (eq (char-after) ?#)
-				   (numberp last-below-line)
-				   (not (eq last-below-line here)))
-			      (goto-char last-below-line))
-			  (throw 'done t)))
-		      ;; Don't know why I added the following, but it
-		      ;; doesn't work when point is preceded by a line
-		      ;; style comment. /mast
-		      ;;(c-skip-ws-backward)
-		      (if literal-pos
-			  (c-backward-comments)
-			(when (c-backward-single-comment)
-			  ;; Record position of first comment.
-			  (save-excursion
-			    (c-forward-single-comment)
-			    (setq literal-pos (point)))
-			  (c-backward-comments)))
-		      (unless last-below-line
-			(if (save-excursion
-			      (re-search-forward "\\(^\\|[^\\]\\)$" last t))
-			    (setq last-below-line last)))
-		      (cond ((bobp)	; Must handle bob specially.
-			     (if (= here last)
-				 (throw 'done t)
-			       (goto-char last)
-			       (throw 'done t)))
-			    ((progn (backward-char)
-				    (looking-at "[;{}]"))
-			     (if (and c-special-brace-lists
-				      (eq (char-after) ?{)
-				      (c-looking-at-special-brace-list))
-				 (skip-syntax-backward "w_") ; Speedup only.
-			       (if (or (= here last)
-				       (memq (char-after last) '(?\) ?})))
-				   (if (and (eq (char-before) ?})
-					    (eq (char-after) ?\;))
-				       (backward-char))
-				 (goto-char last)
-				 (throw 'done t))))
-			    ((= (char-syntax (char-after)) ?\")
-			     (let ((end (point)))
-			       (forward-char)
-			       (c-backward-sexp)
-			       (save-excursion
-				 (skip-chars-forward "^\n" end)
-				 (when (< (point) end)
-				   ;; Break at multiline string.
-				   (setq literal-pos (1+ end))
-				   (throw 'done t)))))
-			    (t (skip-syntax-backward "w_")) ; Speedup only.
-			    )))
-		  (if (and (numberp literal-pos)
-			   (< (point) literal-pos))
-		      ;; We jumped over a comment or string that
-		      ;; should be investigated.
-		      (goto-char literal-pos)
-		    (setq count (1- count))))
-	      (error
-	       (goto-char (point-min))
-	       (setq count 0)))
-	  (condition-case nil
-	      ;; Stop before `{', `}', and `#' when it's 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.
-	      (let ((literal-pos (not sentence-flag))
-		    last)
-		(catch 'done
-		  (while t
-		    (setq last (point))
-		    (if literal-pos
-			(c-forward-comments)
-		      (if (progn
-			    (c-skip-ws-forward)
-			    ;; Record position of first comment.
-			    (setq literal-pos (point))
-			    (c-forward-single-comment))
-			  (c-forward-comments)
-			(setq literal-pos nil)))
-		    (cond ((and (eq (char-after) ?{)
-				(not (and c-special-brace-lists
-					  (c-looking-at-special-brace-list)))
-				(/= here last)
-				(save-excursion
-				  (or (not (c-safe (up-list -1) t))
-				      (= (char-after) ?{))))
-			   (goto-char last)
-			   (throw 'done t))
-			  ((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 1)
-			   (skip-syntax-forward "w_")) ; Speedup only.
-			  ((and (eq (char-after) ?})
-				(/= here last))
-			   (goto-char last)
-			   (throw 'done t))
-; 			  ((and (eq (char-after) ?#)
-; 				(= (point) (c-point 'boi)))
-; 			   (if (= here last)
-; 			       (or (re-search-forward "\\(^\\|[^\\]\\)$" nil t)
-; 				   (goto-char (point-max)))
-; 			     (goto-char last))
-; 			   (throw 'done t))
-			  ((looking-at ";\\|};?")
-			   (goto-char (match-end 0))
-			   (throw 'done t))
-			  ((= (char-syntax (char-after)) ?\")
-			   (let ((beg (point)))
-			     (c-forward-sexp)
-			     (save-excursion
-			       (skip-chars-backward "^\n" beg)
-			       (when (> (point) beg)
-				 ;; Break at multiline string.
-				 (setq literal-pos beg)
-				 (throw 'done t)))))
-			  (t
-			   (forward-char 1)
-			   (skip-syntax-forward "w_")) ; Speedup only.
-			  )))
-		(if (and (numberp literal-pos)
-			 (> (point) literal-pos))
-		    ;; We jumped over a comment that should be investigated.
-		    (goto-char literal-pos)
-		  (setq count (1+ count))))
-	    (error
-	     (goto-char (point-max))
-	     (setq count 0)))
-	  ))
-      ;; If we haven't moved we're near a buffer limit.
-      (when (and (not (zerop count)) (= (point) here))
-	(goto-char (if (> count 0) (point-min) (point-max)))
-	(setq count 0))))
-  (c-keep-region-active))
+  (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)))
+
+	(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.
@@ -1708,8 +2348,77 @@
 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))))
+			       
 
 
 ;; set up electric character functions to work with pending-del,
@@ -1737,6 +2446,7 @@
 
 
 (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)
@@ -1760,7 +2470,7 @@
 		   (let ((lim (c-literal-limits (c-point 'bol) t)))
 		     (when (consp lim)
 		       (goto-char (car lim))
-		       (when (looking-at "/[/*]")
+		       (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.
@@ -1835,15 +2545,16 @@
 A prefix argument acts as a repeat count.  With a negative argument,
 move forward to the end of the containing preprocessor conditional.
 
-`#elif' is treated like `#else' followed by `#if', so the function
-stops at them when going backward, but not when going forward."
+\"#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'
+  "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)
@@ -1854,15 +2565,16 @@
 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."
+\"#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'
+  "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 1 t)
@@ -1881,16 +2593,16 @@
 A prefix argument acts as a repeat count.  With a negative argument,
 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.
+\"#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."
+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))
@@ -1996,15 +2708,15 @@
   just inserts a tab character, or the equivalent number of spaces,
   depending on the variable `indent-tabs-mode'."
 
-  (interactive "p")
+  (interactive "P")
   (let ((indent-function
 	 (if c-syntactic-indentation
 	     (symbol-function 'indent-according-to-mode)
 	   (lambda ()
 	     (let ((c-macro-start c-macro-start)
-		   (steps (cond ((not current-prefix-arg) 1)
-				((equal current-prefix-arg '(4)) -1)
-				(t arg))))
+		   (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
@@ -2014,7 +2726,7 @@
 		 ;; Realign the line continuation backslash if inside a macro.
 		 (c-backslash-region (point) (point) nil t)))
 	     ))))
-    (if (and c-syntactic-indentation current-prefix-arg)
+    (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.
@@ -2029,7 +2741,7 @@
 			     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))
@@ -2040,7 +2752,7 @@
 	      (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
@@ -2054,7 +2766,7 @@
        ;; CASE 3: if in a literal, insert a tab, but always indent the
        ;; line
        (t
-	(if (c-in-literal)
+	(if (c-save-buffer-state () (c-in-literal))
 	    (funcall c-insert-tab-function))
 	(funcall indent-function)
 	)))))
@@ -2135,7 +2847,8 @@
 		    ;; shut up any echo msgs on indiv lines
 		    (c-echo-syntactic-information-p nil)
 		    (in-macro (and c-auto-align-backslashes
-				   (save-excursion (c-beginning-of-macro))
+				   (c-save-buffer-state ()
+				     (save-excursion (c-beginning-of-macro)))
 				   start))
 		    (c-fix-backslashes nil)
 		    syntax)
@@ -2181,8 +2894,6 @@
 (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.
-  ;;
-  ;; This function does not do any hidden buffer changes.
   (c-region-is-active-p))
 
 (defun c-indent-line-or-region ()
@@ -2199,7 +2910,6 @@
 (defvar c-progress-info nil)
 
 (defun c-progress-init (start end context)
-  ;; This function does not do any hidden buffer changes.
   (cond
    ;; Be silent
    ((not c-progress-interval))
@@ -2221,7 +2931,6 @@
    ))
 
 (defun c-progress-update ()
-  ;; This function does not do any hidden buffer changes.
   (if (not (and c-progress-info c-progress-interval))
       nil
     (let ((now (nth 1 (current-time)))
@@ -2238,7 +2947,6 @@
       )))
 
 (defun c-progress-fini (context)
-  ;; This function does not do any hidden buffer changes.
   (if (not c-progress-interval)
       nil
     (if (or (eq context (aref c-progress-info 3))
@@ -2399,7 +3107,6 @@
 	(set-marker point-pos nil))))
 
 (defun c-append-backslashes-forward (to-mark column point-pos)
-  ;; This function does not do any hidden buffer changes.
   (let ((state (parse-partial-sexp (c-point 'bol) (point))))
     (if column
 	(while
@@ -2473,7 +3180,6 @@
 	   (bolp))))))			; forward-line has funny behavior at eob.
 
 (defun c-delete-backslashes-forward (to-mark point-pos)
-  ;; This function does not do any hidden buffer changes.
   (while
       (and (<= (point) to-mark)
 	   (progn
@@ -2518,6 +3224,8 @@
   ;; 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]*\\("
@@ -2877,7 +3585,7 @@
   ;; 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.
   ;;
-  ;; This function does not do any hidden buffer changes.
+  ;; Note that this function does not do any hidden buffer changes.
 
   (let (fill
 	;; beg and end limits the region to narrow.  end is a marker.
@@ -2892,6 +3600,10 @@
 	;; 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))
@@ -2902,29 +3614,30 @@
     (if (and buffer-undo-list (not (eq buffer-undo-list t)))
 	(setq buffer-undo-list (cons (point) buffer-undo-list)))
 
-    (save-restriction
-      ;; Widen to catch comment limits correctly.
-      (widen)
-      (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)))
+    (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
@@ -2965,73 +3678,76 @@
 			     ;; own.  Keep it that way.
 			     (set-marker end (point))))
 
-		(if fill-paragraph
-		    ;; The comment ender should hang.  Replace all
-		    ;; cruft between it and the last word with one or
-		    ;; two 'x' and include it in the region.  We'll
-		    ;; change them back to spaces afterwards.  This
-		    ;; isn't done when auto filling, since that'd
-		    ;; effectively make it impossible to insert extra
-		    ;; spaces before the comment ender.
-		    (let* ((ender-start (save-excursion
-					  (goto-char (cdr c-lit-limits))
-					  (skip-syntax-backward "^w ")
-					  (point)))
-			   (point-rel (- ender-start here))
-			   spaces)
-
-		      (save-excursion
-			(goto-char (cdr c-lit-limits))
-			(setq tmp-post (point-marker))
-			(insert ?\n)
-			(set-marker end (point))
-			(forward-line -1)
-			(if (and (looking-at (concat "[ \t]*\\(\\("
-						     c-current-comment-prefix
-						     "\\)[ \t]*\\)"))
-				 (eq ender-start (match-end 0)))
-			    ;; The comment ender is prefixed by nothing
-			    ;; but a comment line prefix.  Remove it
-			    ;; along with surrounding ws.
-			    (setq spaces (- (match-end 1) (match-end 2)))
-			  (goto-char ender-start))
-			(skip-chars-backward " \t\r\n")
-
-			(if (/= (point) ender-start)
-			    (progn
-			      (if (<= here (point))
-				  ;; Don't adjust point below if it's
-				  ;; before the string we replace.
-				  (setq point-rel -1))
-			      ;; Keep one or two spaces between the
-			      ;; text and the ender, depending on how
-			      ;; many there are now.
-			      (unless spaces
-				(setq spaces (- ender-start (point))))
+		;; The comment ender should hang.  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
+		    (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.  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)
+
+		    (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)
-			      (delete-region (point) (+ ender-start spaces))
-			      (setq hang-ender-stuck spaces)
-			      (setq point-rel
-				    (and (>= point-rel 0)
-					 (- (point) (min point-rel spaces)))))
-			  (setq point-rel nil)))
-
-		      (if point-rel
-			  ;; Point was in the middle of the string we
-			  ;; replaced above, so put it back in the same
-			  ;; relative position, counting from the end.
-			  (goto-char point-rel)))
-
-		  ;; We're doing auto filling.  Just move the marker
-		  ;; to the comment end to ignore any code after the
-		  ;; comment.
-		  (move-marker end (cdr c-lit-limits)))))
+				     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.
@@ -3068,14 +3784,15 @@
 	    ;; inside macros is bogus to begin with since the line
 	    ;; continuation backslashes aren't handled).
 	    (save-excursion
-	      (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)))))
+	      (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
@@ -3192,7 +3909,10 @@
 	  (goto-char tmp-post)
 	  (skip-syntax-backward "^w ")
 	  (forward-char (- hang-ender-stuck))
-	  (insert-char ?\  hang-ender-stuck t)
+	  (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))
@@ -3233,8 +3953,6 @@
 (defun c-do-auto-fill ()
   ;; Do automatic filling if not inside a context where it should be
   ;; ignored.
-  ;;
-  ;; This function does not do any hidden buffer changes.
   (let ((c-auto-fill-prefix
 	 ;; The decision whether the line should be broken is actually
 	 ;; done in c-indent-new-comment-line, which do-auto-fill
@@ -3274,31 +3992,36 @@
 	(c-lit-limits c-lit-limits)
 	(c-lit-type c-lit-type)
 	(c-macro-start c-macro-start))
-    (when (not (eq c-auto-fill-prefix t))
-      ;; Called from do-auto-fill.
-      (unless c-lit-limits
-	(setq c-lit-limits (c-literal-limits nil nil t)))
-      (unless c-lit-type
-	(setq c-lit-type (c-literal-type c-lit-limits)))
-      (if (memq (cond ((c-query-and-set-macro-start) 'cpp)
-		      ((null c-lit-type) 'code)
-		      (t c-lit-type))
-		c-ignore-auto-fill)
-	  (setq fill-prefix t)		; Used as flag in the cond.
-	(if (and (null c-auto-fill-prefix)
-		 (eq c-lit-type 'c)
-		 (<= (c-point 'bol) (car c-lit-limits)))
-	    ;; The adaptive fill function has generated a prefix, but
-	    ;; we're on the first line in a block comment so it'll be
-	    ;; wrong.  Ignore it to guess a better one below.
-	    (setq fill-prefix nil)
-	  (when (and (eq c-lit-type 'c++)
-		     (not (string-match "\\`[ \t]*//" (or fill-prefix ""))))
-	    ;; Kludge: If the function that adapted the fill prefix
-	    ;; doesn't produce the required comment starter for line
-	    ;; comments, then we ignore it.
-	    (setq fill-prefix nil)))
-	))
+
+    (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)))
+	  )))
+
     (cond ((eq fill-prefix t)
 	   ;; A call from do-auto-fill which should be ignored.
 	   )
@@ -3306,7 +4029,7 @@
 	   ;; A fill-prefix overrides anything.
 	   (funcall do-line-break)
 	   (insert-and-inherit fill-prefix))
-	  ((progn
+	  ((c-save-buffer-state ()
 	     (unless c-lit-limits
 	       (setq c-lit-limits (c-literal-limits)))
 	     (unless c-lit-type
@@ -3440,31 +4163,38 @@
 comment prefix (see the `c-comment-prefix-regexp' and
 `c-block-comment-prefix' variables for details).  The end of a
 C++-style line comment doesn't count as inside it."
+
   (interactive "*")
-  (let* ((c-lit-limits (c-literal-limits nil nil t))
-	 (c-lit-type (c-literal-type c-lit-limits))
+  (let* (c-lit-limits c-lit-type
 	 (c-macro-start c-macro-start))
-    (if (or (eq c-lit-type 'c)
-	    (and (eq c-lit-type 'c++)
-		 (< (save-excursion
-		      (skip-chars-forward " \t")
-		      (point))
-		    (1- (cdr (setq c-lit-limits
-				   (c-collect-line-comments c-lit-limits))))))
-	    (and (or (not (looking-at "\\s *$"))
-		     (eq (char-before) ?\\))
-		 (c-query-and-set-macro-start)
-		 (<= (save-excursion
-		       (goto-char c-macro-start)
-		       (if (looking-at c-opt-cpp-start)
-			   (goto-char (match-end 0)))
-		       (point))
-		    (point))))
+
+    (if (c-save-buffer-state ()
+	  (setq c-lit-limits (c-literal-limits nil nil t)
+		c-lit-type (c-literal-type c-lit-limits))
+	  (or (eq c-lit-type 'c)
+	      (and (eq c-lit-type 'c++)
+		   (< (save-excursion
+			(skip-chars-forward " \t")
+			(point))
+		      (1- (cdr (setq c-lit-limits (c-collect-line-comments
+						   c-lit-limits))))))
+	      (and (or (not (looking-at "\\s *$"))
+		       (eq (char-before) ?\\))
+		   (c-query-and-set-macro-start)
+		   (<= (save-excursion
+			 (goto-char c-macro-start)
+			 (if (looking-at c-opt-cpp-start)
+			     (goto-char (match-end 0)))
+			 (point))
+		       (point)))))
+
 	(let ((comment-multi-line t)
 	      (fill-prefix nil))
 	  (c-indent-new-comment-line nil t))
+
       (delete-horizontal-space)
       (newline)
+
       ;; c-indent-line may look at the current indentation, so let's
       ;; start out with the same indentation as the previous line.
       (let ((col (save-excursion
@@ -3473,6 +4203,7 @@
 			       (= (forward-line -1) 0)))
 		   (current-indentation))))
 	(indent-to col))
+
       (indent-according-to-mode))))
 
 (defun c-context-open-line ()