+(defun gnus-pick-article-or-thread (&optional arg)
+ "If `gnus-thread-hide-subtree' is t, then pick the thread on the current line.
+Otherwise pick the article on the current line.
+If ARG, pick the article/thread on that line instead."
+ (interactive "P")
+ (when arg
+ (gnus-pick-goto-article arg))
+ (if gnus-thread-hide-subtree
+ (progn
+ (save-excursion
+ (gnus-uu-mark-thread))
+ (forward-line 1))
+ (gnus-summary-mark-as-processable 1)))
+
+(defun gnus-pick-unmark-article-or-thread (&optional arg)
+ "If `gnus-thread-hide-subtree' is t, then unmark the thread on current line.
+Otherwise unmark the article on current line.
+If ARG, unmark thread/article on that line instead."
+ (interactive "P")
+ (when arg
+ (gnus-pick-goto-article arg))
+ (if gnus-thread-hide-subtree
+ (save-excursion
+ (gnus-uu-unmark-thread))
+ (gnus-summary-unmark-as-processable 1)))
+
+(defun gnus-pick-mouse-pick (e)
+ (interactive "e")
+ (mouse-set-point e)
+ (save-excursion
+ (gnus-summary-mark-as-processable 1)))
+
+(defun gnus-pick-mouse-pick-region (start-event)
+ "Pick articles that the mouse is dragged over.
+This must be bound to a button-down mouse event."
+ (interactive "e")
+ (mouse-minibuffer-check start-event)
+ (let* ((echo-keystrokes 0)
+ (start-posn (event-start start-event))
+ (start-point (posn-point start-posn))
+ (start-line (1+ (count-lines 1 start-point)))
+ (start-window (posn-window start-posn))
+ (bounds (gnus-window-edges start-window))
+ (top (nth 1 bounds))
+ (bottom (if (window-minibuffer-p start-window)
+ (nth 3 bounds)
+ ;; Don't count the mode line.
+ (1- (nth 3 bounds))))
+ (click-count (1- (event-click-count start-event))))
+ (setq mouse-selection-click-count click-count)
+ (setq mouse-selection-click-count-buffer (current-buffer))
+ (mouse-set-point start-event)
+ ;; In case the down click is in the middle of some intangible text,
+ ;; use the end of that text, and put it in START-POINT.
+ (when (< (point) start-point)
+ (goto-char start-point))
+ (gnus-pick-article)
+ (setq start-point (point))
+ ;; end-of-range is used only in the single-click case.
+ ;; It is the place where the drag has reached so far
+ ;; (but not outside the window where the drag started).
+ (let (event end end-point (end-of-range (point)))
+ (track-mouse
+ (while (progn
+ (setq event (cdr (gnus-read-event-char)))
+ (or (mouse-movement-p event)
+ (eq (car-safe event) 'switch-frame)))
+ (if (eq (car-safe event) 'switch-frame)
+ nil
+ (setq end (event-end event)
+ end-point (posn-point end))
+
+ (cond
+ ;; Are we moving within the original window?
+ ((and (eq (posn-window end) start-window)
+ (integer-or-marker-p end-point))
+ ;; Go to START-POINT first, so that when we move to END-POINT,
+ ;; if it's in the middle of intangible text,
+ ;; point jumps in the direction away from START-POINT.
+ (goto-char start-point)
+ (goto-char end-point)
+ (gnus-pick-article)
+ ;; In case the user moved his mouse really fast, pick
+ ;; articles on the line between this one and the last one.
+ (let* ((this-line (1+ (count-lines 1 end-point)))
+ (min-line (min this-line start-line))
+ (max-line (max this-line start-line)))
+ (while (< min-line max-line)
+ (goto-line min-line)
+ (gnus-pick-article)
+ (setq min-line (1+ min-line)))
+ (setq start-line this-line))
+ (when (zerop (% click-count 3))
+ (setq end-of-range (point))))
+ (t
+ (let ((mouse-row (cdr (cdr (mouse-position)))))
+ (cond
+ ((null mouse-row))
+ ((< mouse-row top)
+ (mouse-scroll-subr start-window (- mouse-row top)))
+ ((>= mouse-row bottom)
+ (mouse-scroll-subr start-window
+ (1+ (- mouse-row bottom)))))))))))
+ (when (consp event)
+ (let ((fun (key-binding (vector (car event)))))
+ ;; Run the binding of the terminating up-event, if possible.
+ ;; In the case of a multiple click, it gives the wrong results,
+ ;; because it would fail to set up a region.
+ (when nil
+ ;; (and (= (mod mouse-selection-click-count 3) 0) (fboundp fun))
+ ;; In this case, we can just let the up-event execute normally.
+ (let ((end (event-end event)))
+ ;; Set the position in the event before we replay it,
+ ;; because otherwise it may have a position in the wrong
+ ;; buffer.
+ (setcar (cdr end) end-of-range)
+ ;; Delete the overlay before calling the function,
+ ;; because delete-overlay increases buffer-modified-tick.
+ (push event unread-command-events))))))))
+