+(defsubst c-determine-limit-get-base (start try-size)
+ ;; Get a "safe place" approximately TRY-SIZE characters before START.
+ ;; This doesn't preserve point.
+ (let* ((pos (max (- start try-size) (point-min)))
+ (base (c-state-semi-safe-place pos))
+ (s (parse-partial-sexp base pos)))
+ (if (or (nth 4 s) (nth 3 s)) ; comment or string
+ (nth 8 s)
+ (point))))
+
+(defun c-determine-limit (how-far-back &optional start try-size)
+ ;; Return a buffer position HOW-FAR-BACK non-literal characters from START
+ ;; (default point). This is done by going back further in the buffer then
+ ;; searching forward for literals. The position found won't be in a
+ ;; literal. We start searching for the sought position TRY-SIZE (default
+ ;; twice HOW-FAR-BACK) bytes back from START. This function must be fast.
+ ;; :-)
+ (save-excursion
+ (let* ((start (or start (point)))
+ (try-size (or try-size (* 2 how-far-back)))
+ (base (c-determine-limit-get-base start try-size))
+ (pos base)
+
+ (s (parse-partial-sexp pos pos)) ; null state.
+ stack elt size
+ (count 0))
+ (while (< pos start)
+ ;; Move forward one literal each time round this loop.
+ ;; Move forward to the start of a comment or string.
+ (setq s (parse-partial-sexp
+ pos
+ start
+ nil ; target-depth
+ nil ; stop-before
+ s ; state
+ 'syntax-table)) ; stop-comment
+
+ ;; Gather details of the non-literal-bit - starting pos and size.
+ (setq size (- (if (or (nth 4 s) (nth 3 s))
+ (nth 8 s)
+ (point))
+ pos))
+ (if (> size 0)
+ (setq stack (cons (cons pos size) stack)))
+
+ ;; Move forward to the end of the comment/string.
+ (if (or (nth 4 s) (nth 3 s))
+ (setq s (parse-partial-sexp
+ (point)
+ start
+ nil ; target-depth
+ nil ; stop-before
+ s ; state
+ 'syntax-table))) ; stop-comment
+ (setq pos (point)))
+
+ ;; Now try and find enough non-literal characters recorded on the stack.
+ ;; Go back one recorded literal each time round this loop.
+ (while (and (< count how-far-back)
+ stack)
+ (setq elt (car stack)
+ stack (cdr stack))
+ (setq count (+ count (cdr elt))))
+
+ ;; Have we found enough yet?
+ (cond
+ ((>= count how-far-back)
+ (+ (car elt) (- count how-far-back)))
+ ((eq base (point-min))
+ (point-min))
+ (t
+ (c-determine-limit (- how-far-back count) base try-size))))))
+
+(defun c-determine-+ve-limit (how-far &optional start-pos)
+ ;; Return a buffer position about HOW-FAR non-literal characters forward
+ ;; from START-POS (default point), which must not be inside a literal.
+ (save-excursion
+ (let ((pos (or start-pos (point)))
+ (count how-far)
+ (s (parse-partial-sexp (point) (point)))) ; null state
+ (while (and (not (eobp))
+ (> count 0))
+ ;; Scan over counted characters.
+ (setq s (parse-partial-sexp
+ pos
+ (min (+ pos count) (point-max))
+ nil ; target-depth
+ nil ; stop-before
+ s ; state
+ 'syntax-table)) ; stop-comment
+ (setq count (- count (- (point) pos) 1)
+ pos (point))
+ ;; Scan over literal characters.
+ (if (nth 8 s)
+ (setq s (parse-partial-sexp
+ pos
+ (point-max)
+ nil ; target-depth
+ nil ; stop-before
+ s ; state
+ 'syntax-table) ; stop-comment
+ pos (point))))
+ (point))))
+