- ((memq major-mode add-log-c-like-modes)
- (beginning-of-line)
- ;; See if we are in the beginning part of a function,
- ;; before the open brace. If so, advance forward.
- (while (not (looking-at "{\\|\\(\\s *$\\)"))
- (forward-line 1))
- (or (eobp)
- (forward-char 1))
- (let (maybe-beg)
- ;; Try to find the containing defun.
- (beginning-of-defun)
- (end-of-defun)
- ;; If the defun we found ends before the desired position,
- ;; see if there's a DEFUN construct
- ;; between that end and the desired position.
- (when (save-excursion
- (and (> location (point))
- (re-search-forward "^DEFUN"
- (save-excursion
- (goto-char location)
- (line-end-position))
- t)
- (re-search-forward "^{" nil t)
- (setq maybe-beg (point))))
- ;; If so, go to the end of that instead.
- (goto-char maybe-beg)
- (end-of-defun)))
- ;; If the desired position is within the defun we found,
- ;; find the function name.
- (when (< location (point))
- ;; Move back over function body.
- (backward-sexp 1)
- (let (beg)
- ;; Skip back over typedefs and arglist.
- ;; Stop at the function definition itself
- ;; or at the line that follows end of function doc string.
- (forward-line -1)
- (while (and (not (bobp))
- (looking-at "[ \t\n]")
- (not (looking-back "[*]/)\n" (- (point) 4))))
- (forward-line -1))
- ;; If we found a doc string, this must be the DEFUN macro
- ;; used in Emacs. Move back to the DEFUN line.
- (when (looking-back "[*]/)\n" (- (point) 4))
- (backward-sexp 1)
- (beginning-of-line))
+ ((apply 'derived-mode-p add-log-c-like-modes)
+ ;; See whether the point is inside a defun.
+ (let (having-previous-defun
+ having-next-defun
+ previous-defun-end
+ next-defun-beginning)
+
+ (save-excursion
+ (setq having-previous-defun
+ (c-beginning-of-defun))
+ (c-end-of-defun)
+ ;; `c-end-of-defun' moves point to the line after
+ ;; the function close, but the position we prefer
+ ;; here is the position after the final }.
+ (backward-sexp 1)
+ (forward-sexp 1)
+ ;; Skip the semicolon ``;'' for
+ ;; enum/union/struct/class definition.
+ (if (= (char-after (point)) ?\;)
+ (forward-char 1))
+ (setq previous-defun-end (point)))
+
+ (save-excursion
+ (setq having-next-defun
+ (c-end-of-defun))
+ (c-beginning-of-defun)
+ (setq next-defun-beginning (point)))
+
+ (if (and having-next-defun
+ (< location next-defun-beginning))
+ (skip-syntax-forward " "))
+ (if (and having-previous-defun
+ (> location previous-defun-end))
+ (skip-syntax-backward " "))
+ (unless (or
+ ;; When there is no previous defun, the
+ ;; point is not in a defun if it is not at
+ ;; the beginning of the next defun.
+ (and (not having-previous-defun)
+ (not (= (point)
+ next-defun-beginning)))
+ ;; When there is no next defun, the point
+ ;; is not in a defun if it is not at the
+ ;; end of the previous defun.
+ (and (not having-next-defun)
+ (not (= (point)
+ previous-defun-end)))
+ ;; If the point is between two defuns, it
+ ;; is not in a defun.
+ (and (> (point) previous-defun-end)
+ (< (point) next-defun-beginning)))
+ ;; If the point is already at the beginning of a
+ ;; defun, there is no need to move point again.
+ (if (not (= (point) next-defun-beginning))
+ (c-beginning-of-defun))