Function: c-backward-sws

c-backward-sws is a byte-compiled function defined in cc-engine.el.gz.

Signature

(c-backward-sws)

Documentation

This function has :around advice: No documentation

Source Code

;; Defined in /usr/src/emacs/lisp/progmodes/cc-engine.el.gz
(defun c-backward-sws ()
  ;; Used by `c-backward-syntactic-ws' to implement the unbounded search.
  ;;
  ;; This function might do hidden buffer changes.

  (let (;; `rung-pos' is set to a position as late as possible in the unmarked
	;; part of the simple ws region.
	(rung-pos (point)) next-rung-pos last-put-in-sws-pos
	rung-is-marked simple-ws-beg cmt-skip-pos
	(doc-line-join-here (concat c-doc-line-join-re "\\="))
	attr-end)

    ;; Skip simple horizontal ws and do a quick check on the preceding
    ;; character to see if it's anything that can't end syntactic ws, so we can
    ;; bail out early in the majority of cases when there just are a few ws
    ;; chars.  Newlines are complicated in the backward direction, so we can't
    ;; skip over them.
    (c-skip-ws-chars-backward " \t\f ")
    (when (and (not (bobp))
	       (save-excursion
		 (or (and
		      (memq (char-before) c-doc-line-join-end-ch) ; For speed.
		      (re-search-backward doc-line-join-here
					  (c-point 'bopl) t))
		     (and
		      (c-major-mode-is '(c-mode c++-mode))
		      (eq (char-before) ?\])
		      (eq (char-before (1- (point))) ?\])
		      (save-excursion
			(and (c-go-list-backward)
			     (looking-at "\\[\\[")))
		      (setq attr-end (point)))
		     (progn
		       (backward-char)
		       (or (looking-at c-syntactic-ws-end)
			   (and c-opt-cpp-prefix
				(looking-at c-symbol-char-key)
				(progn (c-beginning-of-current-token)
				       (looking-at c-noise-macro-name-re))))))))
      ;; Try to find a rung position in the simple ws preceding point, so that
      ;; we can get a cache hit even if the last bit of the simple ws has
      ;; changed recently.
      (setq simple-ws-beg (or attr-end	      ; After attribute.
			      (match-end 1) ; Noise macro, etc.
			      (match-end 0))) ; c-syntactic-ws-end
      (c-skip-ws-chars-backward " \t\n\r\f\v ")
      (if (setq rung-is-marked (text-property-any
				(point) (min (1+ rung-pos) (point-max))
				'c-is-sws t))
	  ;; `rung-pos' will be the earliest marked position, which means that
	  ;; there might be later unmarked parts in the simple ws region.
	  ;; It's not worth the effort to fix that; the last part of the
	  ;; simple ws is also typically edited often, so it could be wasted.
	  (goto-char (setq rung-pos rung-is-marked))
	(goto-char simple-ws-beg))

      (with-silent-modifications
      (while
	  (progn
	    ;; Each time round the next while form, we move back over a ladder
	    ;; and append any simple WS preceding it, if possible joining with
	    ;; the previous ladder.
	    (while
		(when (and rung-is-marked
			   (not (bobp))
			   (get-text-property (1- (point)) 'c-in-sws))

		  ;; The following search is the main reason that `c-in-sws'
		  ;; and `c-is-sws' aren't combined to one property.
		  (goto-char (c-previous-single-property-change
			      (point) 'c-in-sws nil (point-min)))
		  (unless (get-text-property (point) 'c-is-sws)
		    ;; If the `c-in-sws' region extended past the first
		    ;; `c-is-sws' char we have to go forward a bit.
		    (goto-char (c-next-single-property-change
				(point) 'c-is-sws)))

		  (c-debug-sws-msg
		   "c-backward-sws cached move %s <- %s (min %s)"
		   (point) rung-pos (point-min))

		  (setq rung-pos (point))
		  (if (and (< (min (c-skip-ws-chars-backward " \t\f\v ")
				   (progn
				     (setq simple-ws-beg (point))
				     (c-skip-ws-chars-backward " \t\n\r\f\v ")))
			      0)
			   (setq rung-is-marked
				 (text-property-any (point) rung-pos
						    'c-is-sws t)))
		      t
		    (goto-char simple-ws-beg)
		    nil))

	      ;; We'll loop here if there is simple ws before the first rung.
	      ;; That means that there's been some change in it and it's
	      ;; possible that we've stepped into another ladder, so extend
	      ;; the previous one to join with it if there is one, and try to
	      ;; use the cache again.
	      (c-debug-sws-msg
	       "c-backward-sws extending rung with [%s..%s] (min %s)"
	       rung-is-marked rung-pos (point-min))
	      (unless (get-text-property (1- rung-pos) 'c-is-sws)
		;; Remove any `c-in-sws' property from the last char of
		;; the rung before we mark it with `c-is-sws', so that we
		;; won't connect with the remains of a broken "ladder".
		(c-remove-in-sws (1- rung-pos) rung-pos))
	      (c-put-is-sws rung-is-marked
			    rung-pos)
	      (c-put-in-sws rung-is-marked
			    (1- rung-pos))
	      (setq rung-pos rung-is-marked
		    last-put-in-sws-pos rung-pos))

	    (c-backward-comments)
	    (setq cmt-skip-pos (point))

	    (cond
	     ((and c-opt-cpp-prefix
		   (/= cmt-skip-pos simple-ws-beg)
		   (c-beginning-of-macro))
	      ;; Inside a cpp directive.  See if it should be skipped over.
	      (let ((cpp-beg (point))
		    pause pos)

		;; Move back over all line continuations and block comments in
		;; the region skipped over by `c-backward-comments'.  If we go
		;; past it then we started inside the cpp directive.
		(goto-char simple-ws-beg)
		(beginning-of-line)
		;; Note the similarity of the code here to some in
		;; `c-beginning-of-macro'.
		(setq pause (point))
		(while
		    (progn
		      (while (and (> (point) cmt-skip-pos)
				  (progn (backward-char)
					 (eq (char-before) ?\\)))
			(beginning-of-line))
		      (setq pos (point))
		      (when (and c-last-c-comment-end-on-line-re
				 (re-search-forward
				  c-last-c-comment-end-on-line-re pause t))
			(goto-char (match-end 1))
			(if (c-backward-single-comment)
			    (progn
			      (beginning-of-line)
			      (setq pause (point)))
			  (goto-char pos)
			  nil))))

		(if (< (point) cmt-skip-pos)
		    ;; Don't move past the cpp directive if we began inside
		    ;; it.  Note that the position at the end of the last line
		    ;; of the macro is also considered to be within it.
		    (progn (goto-char cmt-skip-pos)
			   nil)

		  ;; It's worthwhile to spend a little bit of effort on finding
		  ;; the end of the macro, to get a good `simple-ws-beg'
		  ;; position for the cache.  Note that `c-backward-comments'
		  ;; could have stepped over some comments before going into
		  ;; the macro, and then `simple-ws-beg' must be kept on the
		  ;; same side of those comments.
		  (goto-char simple-ws-beg)
		  (c-skip-ws-chars-backward " \t\n\r\f\v ")
		  (if (eq (char-before) ?\\)
		      (forward-char))
		  (forward-line 1)
		  (if (< (point) simple-ws-beg)
		      ;; Might happen if comments after the macro were skipped
		      ;; over.
		      (setq simple-ws-beg (point)))

		  (goto-char cpp-beg)
		  t)))

	     ((/= (save-excursion
		    (c-skip-ws-chars-forward " \t\n\r\f\v " simple-ws-beg)
		    (setq next-rung-pos (point)))
		  simple-ws-beg)
	      ;; Skipped over comments.  Must put point at the end of
	      ;; the simple ws at point since we might be after a line
	      ;; comment or cpp directive that's been partially
	      ;; narrowed out, and we can't risk marking the simple ws
	      ;; at the end of it.
	      (goto-char next-rung-pos)
	      t)

	     ((and c-opt-cpp-prefix
		   (save-excursion
		     (and (< (skip-syntax-backward "w_") 0)
			  (progn (setq next-rung-pos (point))
				 (looking-at c-noise-macro-name-re)))))
	      ;; Skipped over a noise macro
	      (goto-char next-rung-pos)
	      t)

	     ((and (c-major-mode-is '(c-mode c++-mode))
		   (eq (char-before) ?\])
		   (eq (char-before (1- (point))) ?\])
		   (save-excursion
		     (and (c-go-list-backward)
			  (setq next-rung-pos (point))
			  (looking-at "\\[\\["))))
	      (goto-char next-rung-pos)
	      t)

	     ((and
	       (memq (char-before) c-doc-line-join-end-ch) ; For speed.
	       (re-search-backward doc-line-join-here (c-point 'bopl) t)))))

	;; We've searched over a piece of non-white syntactic ws.  See if this
	;; can be cached.
	(setq next-rung-pos (point))
	(c-skip-ws-chars-backward " \t\f\v ")

	(if (or
	     ;; Cache if we started either from a marked rung or from a
	     ;; completely uncached position.
	     rung-is-marked
	     (not (get-text-property (1- simple-ws-beg) 'c-in-sws))

	     ;; Cache if there's a marked rung in the encountered simple ws.
	     (save-excursion
	       (c-skip-ws-chars-backward " \t\n\r\f\v ")
	       (text-property-any (point) (min (1+ next-rung-pos) (point-max))
				  'c-is-sws t)))

	    (progn
	      (c-debug-sws-msg
	       "c-backward-sws caching [%s..%s] - [%s..%s] (min %s)"
	       (point) (1+ next-rung-pos)
	       simple-ws-beg (min (1+ rung-pos) (point-max))
	       (point-min))

	      ;; Remove the properties for any nested ws that might be cached.
	      ;; Only necessary for `c-is-sws' since `c-in-sws' will be set
	      ;; anyway.
	      (c-remove-is-sws (1+ next-rung-pos) simple-ws-beg)
	      (unless (and rung-is-marked (= simple-ws-beg rung-pos))
		(let ((rung-end-pos (min (1+ rung-pos) (point-max))))
		  (unless (get-text-property (1- rung-end-pos) 'c-is-sws)
		    ;; Remove any `c-in-sws' property from the last char of
		    ;; the rung before we mark it with `c-is-sws', so that we
		    ;; won't connect with the remains of a broken "ladder".
		    (c-remove-in-sws (1- rung-end-pos) rung-end-pos))
		  (c-put-is-sws simple-ws-beg
				rung-end-pos)
		  (setq rung-is-marked t)))
	      (c-put-in-sws (setq simple-ws-beg (point)
				  last-put-in-sws-pos simple-ws-beg)
			    rung-pos)
	      (c-put-is-sws (setq rung-pos simple-ws-beg)
			    (1+ next-rung-pos)))

	  (c-debug-sws-msg
	   "c-backward-sws not caching [%s..%s] - [%s..%s] (min %s)"
	   (point) (1+ next-rung-pos)
	   simple-ws-beg (min (1+ rung-pos) (point-max))
	   (point-min))
	  (setq rung-pos next-rung-pos
		simple-ws-beg (point))
	  ))

      ;; Make sure that the newly marked `c-in-sws' region doesn't connect to
      ;; another one before the point (which might occur when editing inside a
      ;; comment or macro).
      (when (eq last-put-in-sws-pos (point))
	(cond ((< (point-min) last-put-in-sws-pos)
	       (c-debug-sws-msg
		"c-backward-sws clearing at %s for cache separation"
		(1- last-put-in-sws-pos))
	       (c-remove-in-sws (1- last-put-in-sws-pos)
				last-put-in-sws-pos))
	      ((> (point-min) 1)
	       ;; If at bob and the buffer is narrowed, we have to clear the
	       ;; character we're standing on instead since there might be a
	       ;; `c-in-sws' before (point-min).  In this case it's necessary
	       ;; to clear both properties.
	       (c-debug-sws-msg
		"c-backward-sws clearing thoroughly at %s for cache separation"
		last-put-in-sws-pos)
	       (c-remove-is-and-in-sws last-put-in-sws-pos
				       (1+ last-put-in-sws-pos)))))
      ))))