+(defun cperl-calculate-indent (&optional parse-start symbol)
+ "Return appropriate indentation for current line as Perl code.
+In usual case returns an integer: the column to indent to.
+Returns nil if line starts inside a string, t if in a comment."
+ (save-excursion
+ (if (memq (get-text-property (point) 'syntax-type) '(pod here-doc)) nil
+ (beginning-of-line)
+ (let* ((indent-point (point))
+ (case-fold-search nil)
+ (s-s (cperl-get-state))
+ (start (nth 0 s-s))
+ (state (nth 1 s-s))
+ (containing-sexp (car (cdr state)))
+ (char-after (save-excursion
+ (skip-chars-forward " \t")
+ (following-char)))
+ (start-indent (save-excursion
+ (goto-char start)
+ (- (current-indentation)
+ (if (nth 2 s-s) cperl-indent-level 0))))
+ old-indent)
+ ;; (or parse-start (null symbol)
+ ;; (setq parse-start (symbol-value symbol)
+ ;; start-indent (nth 2 parse-start)
+ ;; parse-start (car parse-start)))
+ ;; (if parse-start
+ ;; (goto-char parse-start)
+ ;; (beginning-of-defun))
+ ;; ;; Try to go out
+ ;; (while (< (point) indent-point)
+ ;; (setq start (point) parse-start start moved nil
+ ;; state (parse-partial-sexp start indent-point -1))
+ ;; (if (> (car state) -1) nil
+ ;; ;; The current line could start like }}}, so the indentation
+ ;; ;; corresponds to a different level than what we reached
+ ;; (setq moved t)
+ ;; (beginning-of-line 2))) ; Go to the next line.
+ ;; (if start ; Not at the start of file
+ ;; (progn
+ ;; (goto-char start)
+ ;; (setq start-indent (current-indentation))
+ ;; (if moved ; Should correct...
+ ;; (setq start-indent (- start-indent cperl-indent-level))))
+ ;; (setq start-indent 0))
+ ;; (if (< (point) indent-point) (setq parse-start (point)))
+ ;; (or state (setq state (parse-partial-sexp
+ ;; (point) indent-point -1 nil start-state)))
+ ;; (setq containing-sexp
+ ;; (or (car (cdr state))
+ ;; (and (>= (nth 6 state) 0) old-containing-sexp))
+ ;; old-containing-sexp nil start-state nil)
+;;;; (while (< (point) indent-point)
+;;;; (setq parse-start (point))
+;;;; (setq state (parse-partial-sexp (point) indent-point -1 nil start-state))
+;;;; (setq containing-sexp
+;;;; (or (car (cdr state))
+;;;; (and (>= (nth 6 state) 0) old-containing-sexp))
+;;;; old-containing-sexp nil start-state nil))
+ ;; (if symbol (set symbol (list indent-point state start-indent)))
+ ;; (goto-char indent-point)
+ (cond ((or (nth 3 state) (nth 4 state))
+ ;; return nil or t if should not change this line
+ (nth 4 state))
+ ((null containing-sexp)
+ ;; Line is at top level. May be data or function definition,
+ ;; or may be function argument declaration.
+ ;; Indent like the previous top level line
+ ;; unless that ends in a closeparen without semicolon,
+ ;; in which case this line is the first argument decl.
+ (skip-chars-forward " \t")
+ (+ start-indent
+ (if (= (following-char) ?{) cperl-continued-brace-offset 0)
+ (progn
+ (cperl-backward-to-noncomment (or parse-start (point-min)))
+ ;;(skip-chars-backward " \t\f\n")
+ ;; Look at previous line that's at column 0
+ ;; to determine whether we are in top-level decls
+ ;; or function's arg decls. Set basic-indent accordingly.
+ ;; Now add a little if this is a continuation line.
+ (if (or (bobp)
+ (memq (preceding-char) (append " ;}" nil)) ; Was ?\)
+ (memq char-after (append ")]}" nil)))
+ 0
+ cperl-continued-statement-offset))))
+ ((/= (char-after containing-sexp) ?{)
+ ;; line is expression, not statement:
+ ;; indent to just after the surrounding open,
+ ;; skip blanks if we do not close the expression.
+ (goto-char (1+ containing-sexp))
+ (or (memq char-after (append ")]}" nil))
+ (looking-at "[ \t]*\\(#\\|$\\)")
+ (skip-chars-forward " \t"))
+ (current-column))
+ ((progn
+ ;; Containing-expr starts with \{. Check whether it is a hash.
+ (goto-char containing-sexp)
+ (not (cperl-block-p)))
+ (goto-char (1+ containing-sexp))
+ (or (eq char-after ?\})
+ (looking-at "[ \t]*\\(#\\|$\\)")
+ (skip-chars-forward " \t"))
+ (+ (current-column) ; Correct indentation of trailing ?\}
+ (if (eq char-after ?\}) (+ cperl-indent-level
+ cperl-close-paren-offset)
+ 0)))
+ (t
+ ;; Statement level. Is it a continuation or a new statement?
+ ;; Find previous non-comment character.
+ (goto-char indent-point)
+ (cperl-backward-to-noncomment containing-sexp)
+ ;; Back up over label lines, since they don't
+ ;; affect whether our line is a continuation.
+ (while (or (eq (preceding-char) ?\,)
+ (and (eq (preceding-char) ?:)
+ (or;;(eq (char-after (- (point) 2)) ?\') ; ????
+ (memq (char-syntax (char-after (- (point) 2)))
+ '(?w ?_)))))
+ (if (eq (preceding-char) ?\,)
+ ;; Will go to beginning of line, essentially.
+ ;; Will ignore embedded sexpr XXXX.
+ (cperl-backward-to-start-of-continued-exp containing-sexp))
+ (beginning-of-line)
+ (cperl-backward-to-noncomment containing-sexp))
+ ;; Now we get the answer.
+ (if (not (memq (preceding-char) (append ", ;}{" '(nil)))) ; Was ?\,
+ ;; This line is continuation of preceding line's statement;
+ ;; indent `cperl-continued-statement-offset' more than the
+ ;; previous line of the statement.