🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

2 total messages Started by Boris Putanec Wed, 11 Sep 1991 04:17
mouse dragging/selection/editing
#1791
Author: Boris Putanec
Date: Wed, 11 Sep 1991 04:17
17 lines
1112 bytes
Has anyone written the necessary elisp to make epoch mouse selection
more like that on the Macintosh?

I want things like double-click on word, triple-click to get the
sentence, with the selection extending at the current selection unit.
Use the selected text as a large insertion point, so one can select
something, and then type the replacement text. Etc.

This would really help new users who move to Unix/X with prior
mouse-editing experience in the Mac/Windows worlds.

Please email, and I will summarize if there is demand.

thanks

boris
Re: mouse dragging/selection/editing
#1794
Author: Brian L. Kahn
Date: Tue, 17 Sep 1991 16:17
230 lines
8220 bytes
In an article bp@mips.com (Boris Putanec) writes:
   I want things like double-click on word, triple-click to get the
   sentence, with the selection extending at the current selection unit.
   Use the selected text as a large insertion point, so one can select
   something, and then type the replacement text. Etc.



Wasn't exactly a flood of replies to this request, so here is a bit of
code that seems to work for me.  May have some bugs, but should at
least get people started.  I bind these functions to my left and right
mouse buttons, works pretty much like xterm selection.  I particularly
like selecting s-expressions in lisp mode!


--- cut here ---
;;; mouse-select.el
;;; revised to support word and sentence selection, triple click
;;; blk@mitre.org - Wed Sep 11 09:39:15 1991
;;; revised to support timed double clicks
;;; blk@mitre.org - Tue Jan 22 15:35:05 1991

(require 'button)
(require 'mouse)
(provide 'multi-click)


;;; This code installs a mouse-button handler which checks for multi-clicks.
;;; Each up-click is time-stamped, and a subsequent down-click within the
;;; delay interval increments the mouse::clicks counter.
;;; Functions bound to the mouse must check the click counter if they care.
;;; Functions recognizing multi-clicks must be progressive, since the
;;; function will be dispatched first as single click, then double, etc.
;;; The code could be modified to wait for the delay period to see if
;;; any more clicks are coming, but this burns CPU and is very nasty.
;;;
;;; This file includes functions to replace the selection mechanism,
;;; allowing word and line selection.  (mouse::align) extends the region
;;; along object boundaries, char/word/sentence/line/sexp.  There is also 
;;; a function which selects the boundary to use by checking the mode name:
;;;  char/word/sentence for text, char/word/sexp for lisp, etc.
;;; Modify (mouse::boundary) if you don't like this arrangement.
;;;
;;; Copyright MITRE corporation and Brian L. Kahn, Thu Sep 12 13:43:39 1991
;;; Permission granted for any and all use, provided proper citation of 
;;; author and corporation is included in source and/or object.


;;; initialization of mouse selection
;;; =================================

(defvar mouse::style (make-style) 
  "Style used by mouse::attribute")
(defvar mouse::attribute (reserve-attribute) 
  "Attribute for mouse::selection")
(defvar mouse::selection (make-button) 
  "Mouse selection button")

(set-style-foreground mouse::style (background))
(set-style-background mouse::style (foreground))
(set-style-underline mouse::style (background))
(set-attribute-style mouse::attribute mouse::style)
(set-button-attribute mouse::selection mouse::attribute)



;;; mouse handler with multiple clicks
;;; ==================================

(defconst mouse::interval 200
  "The number of milliseconds allowed between multi-clicks
   - interval is clocked between a down-click and previous up-click")
(defvar mouse::time-stamp (the-time)
  "The millisecond time of last upclick")
(defvar mouse::clicks 1
  "The number of mouse button clicks, normally one")

(defvar mouse::old-handler (car (resume-event 'button)) 
  "Previous mouse handler")


(defun mouse::multi-click-handler (type value scr)
  "Calls the old handler after checking for multiple clicks."
  ;; value is a 5-tuple of form (PRESS/RELEASE X Y BUTTON MOD-STATE)
  (if (car value) 
      ;; down-click - do timing checks
      (let ((elapsed (- (the-time) mouse::time-stamp)))
	(if (< elapsed mouse::interval) ; multi-click!
	    (setq mouse::clicks (1+ mouse::clicks))
	  (setq mouse::clicks 1))
	)
    ;; up-click - update time stamp
    (setq mouse::time-stamp (the-time))
    )
  ;; handle as a normal mouse button event
  (funcall mouse::old-handler type value scr)
  )

(push-event 'button 'mouse::multi-click-handler)
(setq epoch::buttons-modify-buffer nil)




;;; selection
;;; =========

(defun mouse::start-select (&optional args)
  "Move mouse and cancel selection??"
  ;; args means mouse press
  (if args (mouse::set-point args))
  (let ((boundary (mouse::boundary mouse::clicks)))
    ;; store selection boundary in data field, for extending selection
    (set-button-data mouse::selection boundary)
    (if (null boundary)
	;; unselect
	(move-button mouse::selection (point) (point) (current-buffer))
      ;; do word/sentence expansion
      (mouse::align (point) (point) boundary)
      (move-button mouse::selection (mark) (point) (current-buffer))
      )
    (redisplay-screen)
    ))



(defun mouse::extend-select (&optional args)
  "Reset near end of selection to mouse pointer or point; adjust region."
  ;; set point if mouse button clicked
  (if args (mouse::set-point args))
  ;; start selection if none in this buffer
  (if (not (eq (current-buffer) (button-buffer mouse::selection)))
      (mouse::start-select)
    (let* ((start (button-start mouse::selection))
	   (end (button-end mouse::selection))
	   (center (/ (+ start end) 2))
	   )
      ;; extending which end?
      (if (> (point) center)
	  (set-mark start)
	(set-mark end))
      ;; check for word/line/etc expansion
      (let ((boundary (button-data mouse::selection)))
	(if boundary (mouse::align (mark) (point) boundary)))
      ;; reposition the selection
      (move-button mouse::selection (mark) (point) (current-buffer))
      (redisplay-screen)
      )))

    

(defun mouse::end-select (args)
  "Selection to cut buffer."
  (let ((text (button-text mouse::selection)))
    (if (not (equal "" text))
	(epoch::store-cut-buffer text))
    ))



(defun mouse::align (from to boundary)
  "Align the region FROM - TO along BOUNDARY; 
   word, line, sent, sexp;
   sets point and mark; returns new region as an apair."
  ;; ensure order of from, to
  (condition-case nil
      (progn
	;; do both ends
	(goto-char (min from to))
	(cond
	 ;; nil and 'char do nothing
	 ((null boundary))
	 ((eq 'char boundary))
	 ((eq 'word boundary) 
	  (re-search-backward "\\<"))
	 ((eq 'line boundary)
	  (beginning-of-line))
	 ((eq 'sent boundary) 
	  (re-search-backward sentence-end)
	  (goto-char (match-end 0)))
	 ((eq 'sexp boundary) 
	  (forward-char 1)
	  (up-list -1))
	 )
	(push-mark)

	;; do both ends
	(goto-char (max from to))
	(cond
	 ;; nil and 'char do nothing
	 ((null boundary))
	 ((eq 'char boundary))
	 ((eq 'word boundary) 
	  (re-search-forward "\\>"))
	 ((eq 'line boundary)
	  (end-of-line))
	 ((eq 'sent boundary) 
	  (re-search-forward sentence-end)
	  (goto-char (1+ (match-beginning 0))))
	 ((eq 'sexp boundary) 
	  (forward-char -1)
	  (up-list 1))
	 )
	(cons (mark) (point))
	)
    ;; if we can't match a search pattern, use 'line
    (error (mouse::align from to 'line)) ; this should always work
    ))



(defun mouse::boundary (&optional level)
  "Returns a suitable boundary, depending upon mode."
  ;; Get the first word from the mode name
  (let ((mode (if (string-match "\w*\\>" mode-name)
		  (substring mode-name 0 (match-end 0)))
	      ))
    (cond
     ;; level 2 is word, level >2 is mode dependent
     ((eq level 1) nil) ; defaults to 'char
     ((eq level 2) 'word)
     ((equal mode "Text") 'sent)
     ((equal mode "Lisp") 'sexp)
     ((equal mode "Tex") 'sent)
     (t 'line)
     )))

--
B<   Brian Kahn   blk@security.mitre.org   "may the farce be with you"
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads