;;; cc-cmds.el --- user level commands for CC Mode
-;; Copyright (C) 1985,1987,1992-2003, 2004, 2005, 2006
-;; Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+;; 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+;; Free Software Foundation, Inc.
-;; Authors: 1998- Martin Stjernholm
+;; Authors: 2003- Alan Mackenzie
+;; 1998- Martin Stjernholm
;; 1992-1999 Barry A. Warsaw
;; 1987 Dave Detlefs and Stewart Clamen
;; 1985 Richard M. Stallman
;; GNU Emacs is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
+;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
(cc-bytecomp-defun c-forward-subword)
(cc-bytecomp-defun c-backward-subword)
\f
+;; Indentation / Display syntax functions
(defvar c-fix-backslashes t)
(defun c-indent-line (&optional syntax quiet ignore-point-pos)
(save-excursion
(beginning-of-line)
(looking-at (if line-cont-backslash
- "\\(\\s *\\)\\\\$"
- "\\(\\s *\\)$")))
+ ;; Don't use "\\s " - ^L doesn't count as WS
+ ;; here
+ "\\([ \t]*\\)\\\\$"
+ "\\([ \t]*\\)$")))
(<= (point) (match-end 1)))
;; Delete all whitespace after point if there's only whitespace
;; on the line, so that any code that does back-to-indentation
(forward-line)))))
\f
+;; Minor mode functions.
(defun c-update-modeline ()
(let ((fmt (format "/%s%s%s%s"
(if c-electric-flag "l" "")
(boundp 'c-subword-mode)
(symbol-value 'c-subword-mode))
"w"
- ""))))
- (setq c-submode-indicators
+ "")))
+ (bare-mode-name (if (string-match "\\(^[^/]*\\)/" mode-name)
+ (substring mode-name (match-beginning 1) (match-end 1))
+ mode-name)))
+;; (setq c-submode-indicators
+;; (if (> (length fmt) 1)
+;; fmt))
+ (setq mode-name
(if (> (length fmt) 1)
- fmt))
+ (concat bare-mode-name fmt)
+ bare-mode-name))
(force-mode-line-update)))
(defun c-toggle-syntactic-indentation (&optional arg)
arg
(c-in-literal)))
(funcall c-backspace-function (prefix-numeric-value arg))
- (c-hungry-backspace)))
+ (c-hungry-delete-backwards)))
-(defun c-hungry-backspace ()
+(defun c-hungry-delete-backwards ()
"Delete the preceding character or all preceding whitespace
back to the previous non-whitespace character.
See also \\[c-hungry-delete-forward]."
(delete-region (point) here)
(funcall c-backspace-function 1))))
+(defalias 'c-hungry-backspace 'c-hungry-delete-backwards)
+
(defun c-electric-delete-forward (arg)
"Delete the following character or whitespace.
If `c-hungry-delete-key' is non-nil (indicated by \"/h\" on the mode
(defun c-hungry-delete-forward ()
"Delete the following character or all following whitespace
up to the next non-whitespace character.
-See also \\[c-hungry-backspace]."
+See also \\[c-hungry-delete-backwards]."
(interactive)
(let ((here (point)))
(c-skip-ws-forward)
(if (and (fboundp 'delete-forward-p)
(delete-forward-p))
(c-hungry-delete-forward)
- (c-hungry-backspace)))
+ (c-hungry-delete-backwards)))
(defun c-electric-pound (arg)
"Insert a \"#\".
;; 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.
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
+\(a) If the auto-newline feature is turned on (indicated by \"/la\" on
the mode line) newlines are inserted before and after the brace as
directed by the settings in `c-hanging-braces-alist'.
"{"
"\\=")
nil t))
- (delete-region mbeg mend)
+ (delete-region (match-beginning 0) (match-end 0))
(insert-and-inherit "} else {"))
((and (memq 'brace-elseif-brace c-cleanup-list)
(progn
(eq literal 'c)
(memq 'comment-close-slash c-cleanup-list)
(eq last-command-char ?/)
+ (looking-at (concat "[ \t]*\\("
+ (regexp-quote comment-end) "\\)?$"))
; (eq c-block-comment-ender "*/") ; C-style comments ALWAYS end in */
(save-excursion
- (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?
+ (save-restriction
+ (narrow-to-region (point-min) (point))
+ (back-to-indentation)
+ (looking-at (concat c-current-comment-prefix "[ \t]*$")))))
+ (delete-region (progn (forward-line 0) (point))
+ (progn (end-of-line) (point)))
+ (insert-char ?* 1)) ; the / comes later. ; Do I need a t (retain sticky properties) here?
(setq indentp (and (not arg)
c-syntactic-indentation
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
+\(a) When the auto-newline feature is turned on (indicated by \"/la\" on
the mode line) a newline might be inserted. See the variable
`c-hanging-semi&comma-criteria' for how newline insertion is determined.
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
+\(a) If the auto-newline feature is turned on (indicated by \"/la\" on
the mode line) newlines are inserted before and after the colon based on
the settings in `c-hanging-colons-alist'.
(backward-char)
(skip-chars-backward " \t")
(setq beg (point))
- (c-save-buffer-state () (c-on-identifier))))
+ (and (c-save-buffer-state () (c-on-identifier))
+ ;; Don't add a space into #define FOO()....
+ (not (and (c-beginning-of-macro)
+ (c-forward-over-cpp-define-id)
+ (eq (point) beg))))))
(save-excursion
(delete-region beg end)
(goto-char beg)
(delete-char -2)))))
\f
+;; "nomenclature" functions + c-scope-operator.
(defun c-forward-into-nomenclature (&optional arg)
"Compatibility alias for `c-forward-subword'."
(interactive "p")
(interactive "*")
(insert-and-inherit "::"))
+\f
+;; Movement (etc.) by defuns.
+(defun c-in-function-trailer-p (&optional lim)
+ ;; Return non-nil if point is between the closing brace and the semicolon of
+ ;; a brace construct which needs a semicolon, e.g. within the "variables"
+ ;; portion of a declaration like "struct foo {...} bar ;".
+ ;;
+ ;; Return the position of the main declaration. Otherwise, return nil.
+ ;; Point is assumed to be at the top level and outside of any macro or
+ ;; literal.
+ ;;
+ ;; If LIM is non-nil, it is the bound on a the backward search for the
+ ;; beginning of the declaration.
+ ;;
+ ;; This function might do hidden buffer changes.
+ (and c-opt-block-decls-with-vars-key
+ (save-excursion
+ (c-syntactic-skip-backward "^;}" lim)
+ (let ((eo-block (point))
+ bod)
+ (and (eq (char-before) ?\})
+ (eq (car (c-beginning-of-decl-1 lim)) 'previous)
+ (setq bod (point))
+ ;; Look for struct or union or ... If we find one, it might
+ ;; be the return type of a function, or the like. Exclude
+ ;; this case.
+ (c-syntactic-re-search-forward
+ (concat "[;=\(\[{]\\|\\("
+ c-opt-block-decls-with-vars-key
+ "\\)")
+ eo-block t t t)
+ (match-beginning 1) ; Is there a "struct" etc., somewhere?
+ (not (eq (char-before) ?_))
+ (c-syntactic-re-search-forward "[;=\(\[{]" eo-block t t t)
+ (eq (char-before) ?\{)
+ bod)))))
+
+(defun c-where-wrt-brace-construct ()
+ ;; Determine where we are with respect to functions (or other brace
+ ;; constructs, included in the term "function" in the rest of this comment).
+ ;; Point is assumed to be outside any macro or literal.
+ ;; This is used by c-\(begining\|end\)-of-defun.
+ ;;
+ ;; Return one of these symbols:
+ ;; at-header : we're at the start of a function's header.
+ ;; in-header : we're inside a function's header, this extending right
+ ;; up to the brace. This bit includes any k&r declarations.
+ ;; in-block : we're inside a function's brace block.
+ ;; in-trailer : we're in the area between the "}" and ";" of something
+ ;; like "struct foo {...} bar, baz;".
+ ;; at-function-end : we're just after the closing brace (or semicolon) that
+ ;; terminates the function.
+ ;; outwith-function: we're not at or in any function. Being inside a
+ ;; non-brace construct also counts as 'outwith-function'.
+ ;;
+ ;; This function might do hidden buffer changes.
+ (save-excursion
+ (let* (kluge-start
+ decl-result brace-decl-p
+ (start (point))
+ (paren-state (c-parse-state))
+ (least-enclosing (c-least-enclosing-brace paren-state)))
+
+ (cond
+ ((and least-enclosing
+ (eq (char-after least-enclosing) ?\{))
+ 'in-block)
+ ((c-in-function-trailer-p)
+ 'in-trailer)
+ ((and (not least-enclosing)
+ (consp paren-state)
+ (consp (car paren-state))
+ (eq start (cdar paren-state)))
+ 'at-function-end)
+ (t
+ ;; Find the start of the current declaration. NOTE: If we're in the
+ ;; variables after a "struct/eval" type block, we don't get to the
+ ;; real declaration here - we detect and correct for this later.
+
+ ;;If we're in the parameters' parens, move back out of them.
+ (if least-enclosing (goto-char least-enclosing))
+ ;; Kluge so that c-beginning-of-decl-1 won't go back if we're already
+ ;; at a declaration.
+ (if (or (and (eolp) (not (eobp))) ; EOL is matched by "\\s>"
+ (not (looking-at
+"\\([;#]\\|\\'\\|\\s(\\|\\s)\\|\\s\"\\|\\s\\\\|\\s$\\|\\s<\\|\\s>\\|\\s!\\)")))
+ (forward-char))
+ (setq kluge-start (point))
+ (setq decl-result
+ (car (c-beginning-of-decl-1
+ ;; NOTE: If we're in a K&R region, this might be the start
+ ;; of a parameter declaration, not the actual function.
+ (and least-enclosing ; LIMIT for c-b-of-decl-1
+ (c-safe-position least-enclosing paren-state)))))
+
+ ;; Has the declaration we've gone back to got braces?
+ (setq brace-decl-p
+ (save-excursion
+ (and (c-syntactic-re-search-forward "[;{]" nil t t)
+ (or (eq (char-before) ?\{)
+ (and c-recognize-knr-p
+ ;; Might have stopped on the
+ ;; ';' in a K&R argdecl. In
+ ;; that case the declaration
+ ;; should contain a block.
+ (c-in-knr-argdecl))))))
+
+ (cond
+ ((= (point) kluge-start) ; might be BOB or unbalanced parens.
+ 'outwith-function)
+ ((eq decl-result 'same)
+ (if brace-decl-p
+ (if (eq (point) start)
+ 'at-header
+ 'in-header)
+ 'outwith-function))
+ ((eq decl-result 'previous)
+ (if (and (not brace-decl-p)
+ (c-in-function-trailer-p))
+ 'at-function-end
+ 'outwith-function))
+ (t (error
+ "c-where-wrt-brace-construct: c-beginning-of-decl-1 returned %s"
+ decl-result))))))))
+
+(defun c-backward-to-nth-BOF-{ (n where)
+ ;; Skip to the opening brace of the Nth function before point. If
+ ;; point is inside a function, this counts as the first. Point must be
+ ;; outside any comment/string or macro.
+ ;;
+ ;; N must be strictly positive.
+ ;; WHERE describes the position of point, one of the symbols `at-header',
+ ;; `in-header', `in-block', `in-trailer', `at-function-end',
+ ;; `outwith-function' as returned by c-where-wrt-brace-construct.
+ ;;
+ ;; If we run out of functions, leave point at BOB. Return zero on success,
+ ;; otherwise the number of {s still to go.
+ ;;
+ ;; This function may do hidden buffer changes
+ (cond
+ ;; What we do to go back the first defun depends on where we start.
+ ((bobp))
+ ((eq where 'in-block)
+ (goto-char (c-least-enclosing-brace (c-parse-state)))
+ (setq n (1- n)))
+ ((eq where 'in-header)
+ (c-syntactic-re-search-forward "{")
+ (backward-char)
+ (setq n (1- n)))
+ ((memq where '(at-header outwith-function at-function-end in-trailer))
+ (c-syntactic-skip-backward "^}")
+ (when (eq (char-before) ?\})
+ (backward-sexp)
+ (setq n (1- n))))
+ (t (error "Unknown `where' %s in c-backward-to-nth-EOF-{" where)))
+
+ ;; Each time round the loop, go back to a "{" at the outermost level.
+ (while (and (> n 0) (not (bobp)))
+ (c-parse-state) ; This call speeds up the following one
+ ; by a factor of ~6. Hmmm. 2006/4/5.
+ (c-syntactic-skip-backward "^}")
+ (when (eq (char-before) ?\})
+ (backward-sexp)
+ (setq n (1- n))))
+ n)
+
(defun c-beginning-of-defun (&optional arg)
"Move backward to the beginning of a defun.
Every top level declaration that contains a brace paren block is
(interactive "p")
(or arg (setq arg 1))
- (if (< arg 0)
- (when (c-end-of-defun (- arg))
- (c-save-buffer-state nil (c-forward-syntactic-ws))
- t)
-
- (c-save-buffer-state (paren-state lim pos)
- (catch 'exit
- (while (> arg 0)
- ;; Note: Partial code duplication in `c-end-of-defun' and
- ;; `c-declaration-limits'.
-
- (setq paren-state (c-parse-state))
- (unless (c-safe
- (goto-char (c-least-enclosing-brace paren-state))
- ;; If we moved to the outermost enclosing paren
- ;; then we can use c-safe-position to set the
- ;; limit. Can't do that otherwise since the
- ;; earlier paren pair on paren-state might very
- ;; well be part of the declaration we should go
- ;; to.
- (setq lim (c-safe-position (point) paren-state))
- t)
- ;; At top level. Make sure we aren't inside a literal.
- (setq pos (c-literal-limits
- (c-safe-position (point) paren-state)))
- (if pos (goto-char (car pos))))
-
- (while (let ((start (point)))
- (c-beginning-of-decl-1 lim)
- (if (= (point) start)
- ;; Didn't move. Might be due to bob or unbalanced
- ;; parens. Try to continue if it's the latter.
- (unless (c-safe (goto-char
- (c-down-list-backward (point))))
- ;; Didn't work, so it's bob then.
- (goto-char (point-min))
- (throw 'exit nil)))
+ (c-save-buffer-state
+ (beginning-of-defun-function end-of-defun-function
+ (start (point))
+ where paren-state pos)
- (save-excursion
- ;; Check if the declaration contains a brace
- ;; block. If not, we try another one.
- (setq pos (point))
- (not (and (c-syntactic-re-search-forward "[;{]" nil t t)
- (or (eq (char-before) ?{)
- (and c-recognize-knr-p
- ;; Might have stopped on the
- ;; ';' in a K&R argdecl. In
- ;; that case the declaration
- ;; should contain a block.
- (c-in-knr-argdecl pos)))))))
- (setq lim nil))
-
- ;; Check if `c-beginning-of-decl-1' put us after the block
- ;; in a declaration that doesn't end there. We're searching
- ;; back and forth over the block here, which can be
- ;; expensive.
- (setq pos (point))
- (if (and c-opt-block-decls-with-vars-key
- (progn
- (c-backward-syntactic-ws)
- (eq (char-before) ?}))
- (eq (car (c-beginning-of-decl-1))
- 'previous)
- (save-excursion
- (c-end-of-decl-1)
- (> (point) pos)))
- nil
- (goto-char pos))
-
- (setq pos (point))
- ;; Try to be line oriented; position point at the closest
- ;; preceding boi that isn't inside a comment, but if we hit
- ;; the previous declaration then we use the current point
- ;; instead.
- (while (and (/= (point) (c-point 'boi))
- (c-backward-single-comment)))
- (if (/= (point) (c-point 'boi))
- (goto-char pos))
-
- (setq arg (1- arg)))))
- (c-keep-region-active)
- (= arg 0)))
+ ;; Move back out of any macro/comment/string we happen to be in.
+ (c-beginning-of-macro)
+ (setq pos (c-literal-limits))
+ (if pos (goto-char (car pos)))
+
+ (setq where (c-where-wrt-brace-construct))
+
+ (if (< arg 0)
+ ;; Move forward to the closing brace of a function.
+ (progn
+ (if (memq where '(at-function-end outwith-function))
+ (setq arg (1+ arg)))
+ (if (< arg 0)
+ (setq arg (c-forward-to-nth-EOF-} (- arg) where)))
+ ;; Move forward to the next opening brace....
+ (when (and (= arg 0)
+ (c-syntactic-re-search-forward "{" nil 'eob))
+ (backward-char)
+ ;; ... and backward to the function header.
+ (c-beginning-of-decl-1)
+ t))
+
+ ;; Move backward to the opening brace of a function.
+ (when (and (> arg 0)
+ (eq (setq arg (c-backward-to-nth-BOF-{ arg where)) 0))
+
+ ;; Go backward to this function's header.
+ (c-beginning-of-decl-1)
+
+ (setq pos (point))
+ ;; We're now there, modulo comments and whitespace.
+ ;; Try to be line oriented; position point at the closest
+ ;; preceding boi that isn't inside a comment, but if we hit
+ ;; the previous declaration then we use the current point
+ ;; instead.
+ (while (and (/= (point) (c-point 'boi))
+ (c-backward-single-comment)))
+ (if (/= (point) (c-point 'boi))
+ (goto-char pos)))
+
+ (c-keep-region-active)
+ (= arg 0))))
+
+(defun c-forward-to-nth-EOF-} (n where)
+ ;; Skip to the closing brace of the Nth function after point. If
+ ;; point is inside a function, this counts as the first. Point must be
+ ;; outside any comment/string or macro.
+ ;;
+ ;; N must be strictly positive.
+ ;; WHERE describes the position of point, one of the symbols `at-header',
+ ;; `in-header', `in-block', `in-trailer', `at-function-end',
+ ;; `outwith-function' as returned by c-where-wrt-brace-construct.
+ ;;
+ ;; If we run out of functions, leave point at EOB. Return zero on success,
+ ;; otherwise the number of }s still to go.
+ ;;
+ ;; This function may do hidden buffer changes.
+
+ (cond
+ ;; What we do to go forward over the first defun depends on where we
+ ;; start. We go to the closing brace of that defun, even when we go
+ ;; backwards to it (in a "struct foo {...} bar ;").
+ ((eobp))
+ ((eq where 'in-block)
+ (goto-char (c-least-enclosing-brace (c-parse-state)))
+ (forward-sexp)
+ (setq n (1- n)))
+ ((eq where 'in-trailer)
+ (c-syntactic-skip-backward "^}")
+ (setq n (1- n)))
+ ((memq where '(at-function-end outwith-function at-header in-header))
+ (when (c-syntactic-re-search-forward "{" nil 'eob)
+ (backward-char)
+ (forward-sexp)
+ (setq n (1- n))))
+ (t (error "c-forward-to-nth-EOF-}: `where' is %s" where)))
+
+ ;; Each time round the loop, go forward to a "}" at the outermost level.
+ (while (and (> n 0) (not (eobp)))
+ ;(c-parse-state) ; This call speeds up the following one by a factor
+ ; of ~6. Hmmm. 2006/4/5.
+ (when (c-syntactic-re-search-forward "{" nil 'eob)
+ (backward-char)
+ (forward-sexp))
+ (setq n (1- n)))
+ n)
(defun c-end-of-defun (&optional arg)
"Move forward to the end of a top level declaration.
An end of a defun occurs right after the close-parenthesis that matches
the open-parenthesis that starts a defun; see `beginning-of-defun'."
-
(interactive "p")
(or arg (setq arg 1))
- (if (< arg 0)
- (when (c-beginning-of-defun (- arg))
- (c-save-buffer-state nil (c-backward-syntactic-ws))
- t)
-
- (c-save-buffer-state (paren-state lim pos)
- (catch 'exit
- (while (> arg 0)
- ;; Note: Partial code duplication in `c-beginning-of-defun'
- ;; and `c-declaration-limits'.
-
- (setq paren-state (c-parse-state))
- (unless (c-safe
- (goto-char (c-least-enclosing-brace paren-state))
- ;; If we moved to the outermost enclosing paren
- ;; then we can use c-safe-position to set the
- ;; limit. Can't do that otherwise since the
- ;; earlier paren pair on paren-state might very
- ;; well be part of the declaration we should go
- ;; to.
- (setq lim (c-safe-position (point) paren-state))
- t)
- ;; At top level. Make sure we aren't inside a literal.
- (setq pos (car-safe (c-literal-limits
- (c-safe-position (point) paren-state))))
- (if pos (goto-char pos)))
-
- ;; Have to move to the start first so that `c-end-of-decl-1'
- ;; has the correct start position.
- (setq pos (point))
- (when (memq (car (c-beginning-of-decl-1 lim))
- '(previous macro))
- ;; We moved back over the previous defun or a macro. Move
- ;; to the next token; it's the start of the next
- ;; declaration. We can also be directly after the block
- ;; in a `c-opt-block-decls-with-vars-key' declaration, but
- ;; then we won't move significantly far here.
- (goto-char pos)
- (c-forward-token-2 0))
-
- (while (let ((start (point)))
- (c-end-of-decl-1)
- (if (= (point) start)
- ;; Didn't move. Might be due to eob or unbalanced
- ;; parens. Try to continue if it's the latter.
- (if (c-safe (goto-char (c-up-list-forward (point))))
- t
- ;; Didn't work, so it's eob then.
- (goto-char (point-max))
- (throw 'exit nil))
-
- (save-excursion
- ;; Check if the declaration contains a brace
- ;; block. If not, we try another one.
- (setq pos (point))
- (goto-char start)
- (not (c-syntactic-re-search-forward "{" pos t t))))))
-
- (setq pos (point))
- ;; Try to be line oriented; position point after the next
- ;; newline that isn't inside a comment, but if we hit the
- ;; next declaration then we use the current point instead.
- (while (and (not (bolp))
- (not (looking-at "\\s *$"))
- (c-forward-single-comment)))
- (cond ((bolp))
- ((looking-at "\\s *$")
- (forward-line 1))
- (t
- (goto-char pos)))
+ (c-save-buffer-state
+ (beginning-of-defun-function end-of-defun-function
+ (start (point))
+ where paren-state pos)
+
+ ;; Move back out of any macro/comment/string we happen to be in.
+ (c-beginning-of-macro)
+ (setq pos (c-literal-limits))
+ (if pos (goto-char (car pos)))
+
+ (setq where (c-where-wrt-brace-construct))
+
+ (if (< arg 0)
+ ;; Move backwards to the } of a function
+ (progn
+ (if (memq where '(at-header outwith-function))
+ (setq arg (1+ arg)))
+ (if (< arg 0)
+ (setq arg (c-backward-to-nth-BOF-{ (- arg) where)))
+ (if (= arg 0)
+ (c-syntactic-skip-backward "^}")))
+
+ ;; Move forward to the } of a function
+ (if (> arg 0)
+ (setq arg (c-forward-to-nth-EOF-} arg where))))
+
+ ;; Do we need to move forward from the brace to the semicolon?
+ (when (eq arg 0)
+ (if (c-in-function-trailer-p) ; after "}" of struct/enum, etc.
+ (c-syntactic-re-search-forward ";"))
+
+ (setq pos (point))
+ ;; We're there now, modulo comments and whitespace.
+ ;; Try to be line oriented; position point after the next
+ ;; newline that isn't inside a comment, but if we hit the
+ ;; next declaration then we use the current point instead.
+ (while (and (not (bolp))
+ (not (looking-at "\\s *$"))
+ (c-forward-single-comment)))
+ (cond ((bolp))
+ ((looking-at "\\s *$")
+ (forward-line 1))
+ (t
+ (goto-char pos))))
- (setq arg (1- arg)))))
(c-keep-region-active)
(= arg 0)))
(push-mark (cdr decl-limits) nil t))))
\f
+;; Movement by statements.
(defun c-in-comment-line-prefix-p ()
;; Point is within a comment. Is it also within a comment-prefix?
;; Space at BOL which precedes a comment-prefix counts as part of it.
(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).
;;
;; 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".
+ ;; 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.
((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.
))))))
;; 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.
;;
(if (/= count 0) (setq count (1- count))))
(c-keep-region-active))))
-
\f
;; set up electric character functions to work with pending-del,
(put 'c-electric-delete-forward 'pending-delete 'supersede) ; pending-del
\f
+;; Inserting/indenting comments
(defun c-calc-comment-indent (entry)
;; This function might do hidden buffer changes.
(if (symbolp entry)
(current-column))))
\f
+;; Movement by CPP conditionals.
(defun c-up-conditional (count)
"Move back to the containing preprocessor conditional, leaving mark behind.
A prefix argument acts as a repeat count. With a negative argument,
(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\"
(defun c-indent-exp (&optional shutup-p)
"Indent each line in the balanced expression following point syntactically.
-If optional SHUTUP-P is non-nil, no errors are signalled if no
+If optional SHUTUP-P is non-nil, no errors are signaled if no
balanced expression is found."
(interactive "*P")
(let ((here (point-marker))
;; 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.
+ ;; beg and end limit the region to narrow. end is a marker.
beg end
;; tmp-pre and tmp-post mark strings that are temporarily
;; inserted at the start and end of the region. tmp-pre is a
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.
+ ;; with 'x's before calling FUN when FILL-PARAGRAPH is nil.
auto-fill-spaces
(here (point))
(c-lit-limits c-lit-limits)
;; Restore point on undo. It's necessary since we do a lot of
;; hidden inserts and deletes below that should be as transparent
;; as possible.
- (if (and buffer-undo-list (not (eq buffer-undo-list t)))
+ (if (and buffer-undo-list (not (eq buffer-undo-list t)))
(setq buffer-undo-list (cons (point) buffer-undo-list)))
+ ;; Determine the limits and type of the containing literal (if any):
+ ;; C-LIT-LIMITS, C-LIT-TYPE; and the limits of the current paragraph:
+ ;; BEG and END.
(c-save-buffer-state ()
(save-restriction
;; Widen to catch comment limits correctly.
(unwind-protect
(progn
+ ;; For each of the possible types of text (string, C comment ...)
+ ;; determine BEG and END, the region we will narrow to. If we're in
+ ;; a literal, constrain BEG and END to the limits of this literal.
+ ;;
+ ;; For some of these text types, particularly a block comment, we
+ ;; may need to massage whitespace near literal delimiters, so that
+ ;; these don't get filled inappropriately.
(cond
((eq c-lit-type 'c++) ; Line comment.
(setq apply-outside-literal t))
((eq c-lit-type 'c) ; Block comment.
- (when (>= end (cdr c-lit-limits))
- ;; The region includes the comment ender which we might
- ;; want to keep together with the last word.
- (unless (save-excursion
- (goto-char (cdr c-lit-limits))
- (beginning-of-line)
- (and (looking-at (concat "[ \t]*\\("
- c-current-comment-prefix
- "\\)\\*/"))
- (eq (cdr c-lit-limits) (match-end 0))
- ;; The comment ender is on a line of its
- ;; own. Keep it that way.
- (set-marker end (point))))
-
- ;; The comment ender should hang. Replace all space between
- ;; it and the last word either by one or two 'x's (when
+ (when
+ (or (> end (cdr c-lit-limits))
+ (and (= end (cdr c-lit-limits))
+ (eq (char-before end) ?/)
+ (eq (char-before (1- end)) ?*)
+ ;; disallow "/*/"
+ (> (- (cdr c-lit-limits) (car c-lit-limits)) 3)))
+ ;; There is a comment ender, and the region includes it. If
+ ;; it's on its own line, it stays on its own line. If it's got
+ ;; company on the line, it keeps (at least one word of) it.
+ ;; "=====*/" counts as a comment ender here, but "===== */"
+ ;; doesn't and "foo*/" doesn't.
+ (unless
+ (save-excursion
+ (goto-char (cdr c-lit-limits))
+ (beginning-of-line)
+ (and (search-forward-regexp
+ (concat "\\=[ \t]*\\(" c-current-comment-prefix "\\)")
+ (- (cdr c-lit-limits) 2) t)
+ (not (search-forward-regexp
+ "\\(\\s \\|\\sw\\)"
+ (- (cdr c-lit-limits) 2) 'limit))
+ ;; The comment ender IS on its own line. Exclude
+ ;; this line from the filling.
+ (set-marker end (c-point 'bol))))
+
+ ;; The comment ender is hanging. Replace all space between it
+ ;; and the last word either by one or two 'x's (when
;; FILL-PARAGRAPH is non-nil), or a row of x's the same width
;; as the whitespace (when auto filling), and include it in
;; the region. We'll change them back to whitespace
spaces)
(save-excursion
+ ;; Insert a CR after the "*/", adjust END
(goto-char (cdr c-lit-limits))
(setq tmp-post (point-marker))
(insert ?\n)
(set-marker end (point))
+
(forward-line -1) ; last line of the comment
(if (and (looking-at (concat "[ \t]*\\(\\("
c-current-comment-prefix
"\\)[ \t]*\\)"))
(eq ender-start (match-end 0)))
- ;; The comment ender is prefixed by nothing
- ;; but a comment line prefix. Remove it
- ;; along with surrounding ws.
+ ;; The comment ender is prefixed by nothing but a
+ ;; comment line prefix. IS THIS POSSIBLE? (ACM,
+ ;; 2006/4/28). Remove it along with surrounding ws.
(setq spaces (- (match-end 1) (match-end 2)))
(goto-char ender-start))
(skip-chars-backward " \t\r\n") ; Surely this can be
; " \t"? "*/" is NOT alone on the line (ACM, 2005/8/18)
+ ;; What's being tested here? 2006/4/20. FIXME!!!
(if (/= (point) ender-start)
(progn
(if (<= here (point))
(c-collect-line-comments c-lit-limits))
c-lit-type)))
(pos (point))
+ (start-col (current-column))
(comment-text-end
(or (and (eq c-lit-type 'c)
(save-excursion
;;
;; If point is on the 'B' then the line will be
;; broken after "Bla b".
+ ;;
+ ;; If we have an empty comment, /* */, the next
+ ;; lot of code pushes point to the */. We fix
+ ;; this by never allowing point to end up to the
+ ;; right of where it started.
(while (and (< (current-column) (cdr fill))
(not (eolp)))
(forward-char 1))
((< (point) (+ (car c-lit-limits) 2))
(goto-char (+ (car c-lit-limits) 2))))
(funcall do-line-break)
- (insert-and-inherit (car fill))))
+ (insert-and-inherit (car fill))
+ (if (> (current-column) start-col)
+ (move-to-column start-col)))) ; can this hit the
+ ; middle of a TAB?
;; Inside a comment that should be broken.
(let ((comment-start comment-start)
(comment-end comment-end)
When point is inside a comment, continue it with the appropriate
comment prefix (see the `c-comment-prefix-regexp' and
`c-block-comment-prefix' variables for details). The end of a
-C++-style line comment doesn't count as inside it."
+C++-style line comment doesn't count as inside it.
+
+When point is inside a string, only insert a backslash when it is also
+inside a preprocessor directive."
(interactive "*")
(let* (c-lit-limits c-lit-type
(c-macro-start c-macro-start))
- (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-save-buffer-state ()
+ (setq c-lit-limits (c-literal-limits nil nil t)
+ c-lit-type (c-literal-type c-lit-limits))
+ (when (eq c-lit-type 'c++)
+ (setq c-lit-limits (c-collect-line-comments c-lit-limits)))
+ (c-query-and-set-macro-start))
+ (cond
+ ((or (eq c-lit-type 'c)
+ (and (eq c-lit-type 'c++) ; C++ comment, but not at the very end of it.
+ (< (save-excursion
+ (skip-chars-forward " \t")
+ (point))
+ (1- (cdr c-lit-limits))))
+ (and (numberp c-macro-start) ; Macro, but not at the very end of
+ ; it, not in a string, and not in the
+ ; cpp keyword.
+ (not (eq c-lit-type 'string))
+ (or (not (looking-at "\\s *$"))
+ (eq (char-before) ?\\))
+ (<= (save-excursion
+ (goto-char c-macro-start)
+ (if (looking-at c-opt-cpp-start)
+ (goto-char (match-end 0)))
+ (point))
+ (point))))
+ (let ((comment-multi-line t)
+ (fill-prefix nil))
+ (c-indent-new-comment-line nil t)))
+
+ ((eq c-lit-type 'string)
+ (if (and (numberp c-macro-start)
+ (not (eq (char-before) ?\\)))
+ (insert ?\\))
+ (newline))
+
+ (t (delete-horizontal-space)
+ (newline)
;; c-indent-line may look at the current indentation, so let's
;; start out with the same indentation as the previous line.
- (let ((col (save-excursion
- (forward-line -1)
- (while (and (looking-at "[ \t]*\\\\?$")
- (= (forward-line -1) 0)))
- (current-indentation))))
- (indent-to col))
-
- (indent-according-to-mode))))
+ (let ((col (save-excursion
+ (backward-char)
+ (forward-line 0)
+ (while (and (looking-at "[ \t]*\\\\?$")
+ (= (forward-line -1) 0)))
+ (current-indentation))))
+ (indent-to col))
+ (indent-according-to-mode)))))
(defun c-context-open-line ()
"Insert a line break suitable to the context and leave point before it.