Annotation of GNUtools/emacs/lisp/sun-mouse.el, revision 1.1

1.1     ! root        1: ;; Mouse handling for Sun windows
        !             2: ;; Copyright (C) 1987, 1991 Free Software Foundation, Inc.
        !             3: 
        !             4: ;; This file is part of GNU Emacs.
        !             5: 
        !             6: ;; GNU Emacs is free software; you can redistribute it and/or modify
        !             7: ;; it under the terms of the GNU General Public License as published by
        !             8: ;; the Free Software Foundation; either version 1, or (at your option)
        !             9: ;; any later version.
        !            10: 
        !            11: ;; GNU Emacs is distributed in the hope that it will be useful,
        !            12: ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            13: ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            14: ;; GNU General Public License for more details.
        !            15: 
        !            16: ;; You should have received a copy of the GNU General Public License
        !            17: ;; along with GNU Emacs; see the file COPYING.  If not, write to
        !            18: ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
        !            19: 
        !            20: ;;; Jeff Peck, Sun Microsystems, Jan 1987.
        !            21: ;;; Original idea by Stan Jefferson
        !            22: ;;
        !            23: ;;     Mar 90          get/set selections
        !            24: ;;     Mar 91          add mouse-help, print bindings dynamically
        !            25: 
        !            26: (provide 'sun-mouse)
        !            27: 
        !            28: ;;;
        !            29: ;;;     Modelled after the GNUEMACS keymap interface.
        !            30: ;;;
        !            31: ;;; User Functions:
        !            32: ;;;   make-mousemap, copy-mousemap, 
        !            33: ;;;   define-mouse, global-set-mouse, local-set-mouse,
        !            34: ;;;   use-global-mousemap, use-local-mousemap,
        !            35: ;;;   mouse-lookup, describe-mouse-bindings
        !            36: ;;;
        !            37: ;;; Options:
        !            38: ;;;   extra-click-wait, scrollbar-width
        !            39: ;;;
        !            40: 
        !            41: (defvar extra-click-wait 150
        !            42:   "*Number of milliseconds to wait for an extra click.
        !            43: Set this to zero if you don't want chords or double clicks.")
        !            44: 
        !            45: (defvar scrollbar-width 5
        !            46:   "*The character width of the scrollbar.
        !            47: The cursor is deemed to be in the right edge scrollbar if it is this near the
        !            48: right edge, and more than two chars past the end of the indicated line.
        !            49: Setting to nil limits the scrollbar to the edge or vertical dividing bar.")
        !            50: 
        !            51: ;;;
        !            52: ;;; Mousemaps
        !            53: ;;;
        !            54: (defun make-mousemap ()
        !            55:   "Returns a new mousemap."
        !            56:   (cons 'mousemap nil))
        !            57: 
        !            58: (defun copy-mousemap (mousemap)
        !            59:   "Return a copy of mousemap."
        !            60:   (copy-alist mousemap))
        !            61: 
        !            62: (defun define-mouse (mousemap mouse-list def)
        !            63:   "Args MOUSEMAP, MOUSE-LIST, DEF.  Define MOUSE-LIST in MOUSEMAP as DEF.
        !            64: MOUSE-LIST is a list of atoms specifing a mouse hit according to these rules:
        !            65:   * One of these atoms specifies the active region of the definition.
        !            66:        text, scrollbar, modeline, minibuffer
        !            67:   * One or two or these atoms specify the button or button combination.
        !            68:         left, middle, right, double
        !            69:   * Any combination of these atoms specify the active shift keys.
        !            70:         control, shift, meta
        !            71:   * With a single unshifted button, you can add
        !            72:        up
        !            73:     to indicate an up-click.
        !            74: The atom `double' is used with a button designator to denote a double click.
        !            75: Two button chords are denoted by listing the two buttons.
        !            76: See sun-mouse-handler for the treatment of the form DEF."
        !            77:   (mousemap-set (mouse-list-to-mouse-code mouse-list) mousemap def))
        !            78: 
        !            79: (defun global-set-mouse (mouse-list def)
        !            80:   "Give MOUSE-EVENT-LIST a local definition of DEF.
        !            81: See define-mouse for a description of MOUSE-EVENT-LIST and DEF.
        !            82: Note that if MOUSE-EVENT-LIST has a local definition in the current buffer,
        !            83: that local definition will continue to shadow any global definition."
        !            84:   (interactive "xMouse event: \nxDefinition: ")
        !            85:   (define-mouse current-global-mousemap mouse-list def))
        !            86: 
        !            87: (defun local-set-mouse (mouse-list def)
        !            88:   "Give MOUSE-EVENT-LIST a local definition of DEF.
        !            89: See define-mouse for a description of the arguments.
        !            90: The definition goes in the current buffer's local mousemap.
        !            91: Normally buffers in the same major mode share a local mousemap."
        !            92:   (interactive "xMouse event: \nxDefinition: ")
        !            93:   (if (null current-local-mousemap)
        !            94:       (setq current-local-mousemap (make-mousemap)))
        !            95:   (define-mouse current-local-mousemap mouse-list def))
        !            96: 
        !            97: (defun use-global-mousemap (mousemap)
        !            98:   "Selects MOUSEMAP as the global mousemap."
        !            99:   (setq current-global-mousemap mousemap))
        !           100: 
        !           101: (defun use-local-mousemap (mousemap)
        !           102:   "Selects MOUSEMAP as the local mousemap.
        !           103: nil for MOUSEMAP means no local mousemap."
        !           104:   (setq current-local-mousemap mousemap))
        !           105: 
        !           106: 
        !           107: ;;;
        !           108: ;;; Interface to the Mouse encoding defined in Emacstool.c
        !           109: ;;;
        !           110: ;;; Called when mouse-prefix is sent to emacs, additional
        !           111: ;;; information is read in as a list (button x y time-delta)
        !           112: ;;;
        !           113: ;;; First, some generally useful functions:
        !           114: ;;;
        !           115: 
        !           116: (defun logtest (x y)
        !           117:   "True if any bits set in X are also set in Y.
        !           118: Just like the Common Lisp function of the same name."
        !           119:   (not (zerop (logand x y))))
        !           120: 
        !           121: 
        !           122: ;;;
        !           123: ;;; Hit accessors.
        !           124: ;;;
        !           125: 
        !           126: (defconst sm::ButtonBits 7)            ; Lowest 3 bits.
        !           127: (defconst sm::ShiftmaskBits 56)                ; Second lowest 3 bits (56 = 63 - 7).
        !           128: (defconst sm::DoubleBits 64)           ; Bit 7.
        !           129: (defconst sm::UpBits 128)              ; Bit 8.
        !           130: 
        !           131: ;;; All the useful code bits
        !           132: (defmacro sm::hit-code (hit)
        !           133:   (` (nth 0 (, hit))))
        !           134: ;;; The button, or buttons if a chord.
        !           135: (defmacro sm::hit-button (hit)
        !           136:   (` (logand sm::ButtonBits (nth 0 (, hit)))))
        !           137: ;;; The shift, control, and meta flags.
        !           138: (defmacro sm::hit-shiftmask (hit)
        !           139:   (` (logand sm::ShiftmaskBits (nth 0 (, hit)))))
        !           140: ;;; Set if a double click (but not a chord).
        !           141: (defmacro sm::hit-double (hit)
        !           142:   (` (logand sm::DoubleBits (nth 0 (, hit)))))
        !           143: ;;; Set on button release (as opposed to button press).
        !           144: (defmacro sm::hit-up (hit)
        !           145:   (` (logand sm::UpBits (nth 0 (, hit)))))
        !           146: ;;; Screen x position.
        !           147: (defmacro sm::hit-x (hit) (list 'nth 1 hit))
        !           148: ;;; Screen y position.
        !           149: (defmacro sm::hit-y (hit) (list 'nth 2 hit))
        !           150: ;;; Millisconds since last hit.
        !           151: (defmacro sm::hit-delta (hit) (list 'nth 3 hit))
        !           152: 
        !           153: (defmacro sm::hit-up-p (hit)           ; A predicate.
        !           154:   (` (not (zerop (sm::hit-up (, hit))))))
        !           155: 
        !           156: ;;;
        !           157: ;;; Loc accessors.  for sm::window-xy
        !           158: ;;;
        !           159: (defmacro sm::loc-w (loc) (list 'nth 0 loc))
        !           160: (defmacro sm::loc-x (loc) (list 'nth 1 loc))
        !           161: (defmacro sm::loc-y (loc) (list 'nth 2 loc))
        !           162: 
        !           163: (defmacro eval-in-buffer (buffer &rest forms)
        !           164:   "Macro to switches to BUFFER, evaluates FORMS, returns to original buffer."
        !           165:   ;; When you don't need the complete window context of eval-in-window
        !           166:   (` (let ((StartBuffer (current-buffer)))
        !           167:     (unwind-protect
        !           168:        (progn
        !           169:          (set-buffer (, buffer))
        !           170:          (,@ forms))
        !           171:     (set-buffer StartBuffer)))))
        !           172: 
        !           173: (put 'eval-in-buffer 'lisp-indent-hook 1)
        !           174: 
        !           175: ;;; this is used extensively by sun-fns.el
        !           176: ;;;
        !           177: (defmacro eval-in-window (window &rest forms)
        !           178:   "Switch to WINDOW, evaluate FORMS, return to original window."
        !           179:   (` (let ((OriginallySelectedWindow (selected-window)))
        !           180:        (unwind-protect
        !           181:           (progn
        !           182:             (select-window (, window))
        !           183:             (,@ forms))
        !           184:         ;; don't go back to window if it has been destroyed...
        !           185:         ;; window-point seems to work as an indication of existence
        !           186:         (if (window-point OriginallySelectedWindow)
        !           187:             (select-window OriginallySelectedWindow))))))
        !           188: (put 'eval-in-window 'lisp-indent-hook 1)
        !           189: 
        !           190: ;;;
        !           191: ;;; handy utility, generalizes window_loop
        !           192: ;;;
        !           193: 
        !           194: ;;; It's a macro (and does not evaluate its arguments).
        !           195: (defmacro eval-in-windows (form &optional yesmini)
        !           196:   "Switches to each window and evaluates FORM.  Optional argument
        !           197: YESMINI says to include the minibuffer as a window.
        !           198: This is a macro, and does not evaluate its arguments."
        !           199:   (` (let ((OriginallySelectedWindow (selected-window)))
        !           200:        (unwind-protect 
        !           201:           (while (progn
        !           202:                    (, form)
        !           203:                    (not (eq OriginallySelectedWindow
        !           204:                             (select-window
        !           205:                              (next-window nil (, yesmini)))))))
        !           206:         (select-window OriginallySelectedWindow)))))
        !           207: (put 'eval-in-window 'lisp-indent-hook 0)
        !           208: 
        !           209: (defun move-to-loc (x y)
        !           210:   "Move cursor to window location X, Y.
        !           211: Handles wrapped and horizontally scrolled lines correctly."
        !           212:   (move-to-window-line y)
        !           213:   ;; window-line-end expects this to return the window column it moved to.
        !           214:   (let ((cc (current-column))
        !           215:        (nc (move-to-column
        !           216:             (if (zerop (window-hscroll))
        !           217:                 (+ (current-column)
        !           218:                    (min (- (window-width) 2)   ; To stay on the line.
        !           219:                         x))
        !           220:               (+ (window-hscroll) -1
        !           221:                  (min (1- (window-width))      ; To stay on the line.
        !           222:                       x))))))
        !           223:     (- nc cc)))
        !           224: 
        !           225: 
        !           226: (defun minibuffer-window-p (window)
        !           227:   "True iff this WINDOW is minibuffer."
        !           228:   (= (screen-height)
        !           229:      (nth 3 (window-edges window))     ; The bottom edge.
        !           230:      ))
        !           231: 
        !           232: 
        !           233: (setq *mouse-help* nil)                        ; flag to display, rather than execute
        !           234: (defun sun-mouse-handler (&optional hit)
        !           235:   "Evaluates the function or list associated with a mouse hit.
        !           236: Expecting to read a hit, which is a list: (button x y delta).  
        !           237: A form bound to button by define-mouse is found by mouse-lookup. 
        !           238: The variables: *mouse-window*, *mouse-x*, *mouse-y* are bound.  
        !           239: If the form is a symbol (symbolp), it is funcall'ed with *mouse-window*,
        !           240: *mouse-x*, and *mouse-y* as arguments; if the form is a list (listp),
        !           241: the form is eval'ed; if the form is neither of these, it is an error.
        !           242: Returns nil."
        !           243:   (interactive)
        !           244:   (if (null hit) (setq hit (sm::combined-hits)))
        !           245:   (let ((loc (sm::window-xy (sm::hit-x hit) (sm::hit-y hit))))
        !           246:     (let ((*mouse-window* (sm::loc-w loc))
        !           247:          (*mouse-x* (sm::loc-x loc))
        !           248:          (*mouse-y* (sm::loc-y loc))
        !           249:          (mouse-code (mouse-event-code hit loc)))
        !           250:       (let ((form (eval-in-buffer (window-buffer *mouse-window*)
        !           251:                    (mouse-lookup mouse-code))))
        !           252:        (cond ((null form)
        !           253:               (if (not (sm::hit-up-p hit))     ; undefined up hits are ok.
        !           254:                   (error "Undefined mouse event: %s" 
        !           255:                          (prin1-to-string 
        !           256:                           (mouse-code-to-mouse-list mouse-code)))))
        !           257:              ((symbolp form)
        !           258:               (setq this-command form)
        !           259:               (if *mouse-help*
        !           260:                   (progn (prin1 (list form *mouse-window* *mouse-x* *mouse-y*))
        !           261:                          (exit-recursive-edit))
        !           262:                   (funcall form *mouse-window* *mouse-x* *mouse-y*)))
        !           263:              ((listp form)
        !           264:               (setq this-command (car form))
        !           265:               (if *mouse-help*
        !           266:                   (progn (prin1 form) (exit-recursive-edit))
        !           267:                   (eval form)))
        !           268:              (t
        !           269:               (error "Mouse action must be symbol or list, but was: %s"
        !           270:                      form))))))
        !           271:   ;; Don't let 'sun-mouse-handler get on last-command,
        !           272:   ;; since this function should be transparent.
        !           273:   (if (eq this-command 'sun-mouse-handler)
        !           274:       (setq this-command last-command))
        !           275:   ;; (message (prin1-to-string this-command))  ; to see what your buttons did
        !           276:   nil)
        !           277: 
        !           278: (defun mouse-help ()
        !           279:   (interactive)
        !           280:   (let ((*mouse-help* t))
        !           281:     (recursive-edit)))
        !           282: 
        !           283: (defun sm::combined-hits ()
        !           284:   "Read and return next mouse-hit, include possible double click"
        !           285:   (let ((hit1 (mouse-hit-read)))
        !           286:     (if (not (sm::hit-up-p hit1))      ; Up hits dont start doubles or chords.
        !           287:        (let ((hit2 (mouse-second-hit extra-click-wait)))
        !           288:          (if hit2      ; we cons'd it, we can smash it.
        !           289:              ; (setf (sm::hit-code hit1) (logior (sm::hit-code hit1) ...))
        !           290:              (setcar hit1 (logior (sm::hit-code hit1) 
        !           291:                                   (sm::hit-code hit2)
        !           292:                                   (if (= (sm::hit-button hit1) 
        !           293:                                          (sm::hit-button hit2))
        !           294:                                       sm::DoubleBits 0))))))
        !           295:     hit1))
        !           296: 
        !           297: (defun mouse-hit-read ()
        !           298:   "Read mouse-hit list from keyboard.  Like (read 'read-char),
        !           299: but that uses minibuffer, and mucks up last-command."
        !           300:   (let ((char-list nil) (char nil))
        !           301:     (while (not (equal 13              ; Carriage return.
        !           302:                       (prog1 (setq char (read-char)) 
        !           303:                         (setq char-list (cons char char-list))))))
        !           304:     (read (mapconcat 'char-to-string (nreverse char-list) ""))
        !           305:     ))
        !           306: 
        !           307: ;;; Second Click Hackery....
        !           308: ;;; if prefix is not mouse-prefix, need a way to unread the char...
        !           309: ;;; or else have mouse flush input queue, or else need a peek at next char.
        !           310: 
        !           311: ;;; There is no peek, but since one character can be unread, we only
        !           312: ;;; have to flush the queue when the command after a mouse click
        !           313: ;;; starts with mouse-prefix1 (see below).
        !           314: ;;;   Something to do later:  We could buffer the read commands and
        !           315: ;;; execute them ourselves after doing the mouse command (using
        !           316: ;;; lookup-key ??).
        !           317: 
        !           318: (defvar mouse-prefix1 24               ; C-x
        !           319:   "First char of mouse-prefix.  Used to detect double clicks and chords.")
        !           320: 
        !           321: (defvar mouse-prefix2 0                        ; C-@
        !           322:   "Second char of mouse-prefix.  Used to detect double clicks and chords.")
        !           323: 
        !           324: 
        !           325: (defun mouse-second-hit (hit-wait)
        !           326:   "Returns the next mouse hit occurring within HIT-WAIT milliseconds."
        !           327:   (if (sit-for-millisecs hit-wait) nil ; No input within hit-wait millisecs.
        !           328:     (let ((pc1 (read-char)))
        !           329:       (if (or (not (equal pc1 mouse-prefix1))
        !           330:              (sit-for-millisecs 3))    ; a mouse prefix will have second char
        !           331:          (progn (setq unread-command-char pc1) ; Can get away with one unread.
        !           332:                 nil)                   ; Next input not mouse event.
        !           333:        (let ((pc2 (read-char)))
        !           334:          (if (not (equal pc2 mouse-prefix2))
        !           335:              (progn (setq unread-command-char pc1) ; put back the ^X
        !           336: ;;; Too bad can't do two: (setq unread-command-char (list pc1 pc2))
        !           337:                (ding)                  ; user will have to retype that pc2.
        !           338:                nil)                    ; This input is not a mouse event.
        !           339:            ;; Next input has mouse prefix and is within time limit.
        !           340:            (let ((new-hit (mouse-hit-read))) ; Read the new hit.
        !           341:                (if (sm::hit-up-p new-hit)      ; Ignore up events when timing.
        !           342:                    (mouse-second-hit (- hit-wait (sm::hit-delta new-hit)))
        !           343:                  new-hit               ; New down hit within limit, return it.
        !           344:                  ))))))))
        !           345: 
        !           346: (defun sm::window-xy (x y)
        !           347:   "Find window containing screen coordinates X and Y.
        !           348: Returns list (window x y) where x and y are relative to window."
        !           349:   (or
        !           350:    (catch 'found
        !           351:      (eval-in-windows 
        !           352:       (let ((we (window-edges (selected-window))))
        !           353:        (let ((le (nth 0 we))
        !           354:              (te (nth 1 we))
        !           355:              (re (nth 2 we))
        !           356:              (be (nth 3 we)))
        !           357:          (if (= re (screen-width))
        !           358:              ;; include the continuation column with this window
        !           359:              (setq re (1+ re)))
        !           360:          (if (= be (screen-height))
        !           361:              ;; include partial line at bottom of screen with this window
        !           362:              ;; id est, if window is not multple of char size.
        !           363:              (setq be (1+ be)))
        !           364: 
        !           365:          (if (and (>= x le) (< x re)
        !           366:                   (>= y te) (< y be))
        !           367:              (throw 'found 
        !           368:                     (list (selected-window) (- x le) (- y te))))))
        !           369:       t))                              ; include minibuffer in eval-in-windows
        !           370:    ;;If x,y from a real mouse click, we shouldn't get here.
        !           371:    (list nil x y)
        !           372:    ))
        !           373: 
        !           374: (defun sm::window-region (loc)
        !           375:   "Parse LOC into a region symbol.
        !           376: Returns one of (text scrollbar modeline minibuffer)"
        !           377:   (let ((w (sm::loc-w loc))
        !           378:        (x (sm::loc-x loc))
        !           379:        (y (sm::loc-y loc)))
        !           380:     (let ((right (1- (window-width w)))
        !           381:          (bottom (1- (window-height w))))
        !           382:       (cond ((minibuffer-window-p w) 'minibuffer)
        !           383:            ((>= y bottom) 'modeline)
        !           384:            ((>= x right) 'scrollbar)
        !           385:            ;; far right column (window seperator) is always a scrollbar
        !           386:            ((and scrollbar-width
        !           387:                  ;; mouse within scrollbar-width of edge.
        !           388:                  (>= x (- right scrollbar-width))
        !           389:                  ;; mouse a few chars past the end of line.
        !           390:                  (>= x (+ 2 (window-line-end w x y))))
        !           391:             'scrollbar)
        !           392:            (t 'text)))))
        !           393: 
        !           394: (defun window-line-end (w x y)
        !           395:   "Return WINDOW column (ignore X) containing end of line Y"
        !           396:   (eval-in-window w (save-excursion (move-to-loc (screen-width) y))))
        !           397: 
        !           398: ;;;
        !           399: ;;; The encoding of mouse events into a mousemap.
        !           400: ;;; These values must agree with coding in emacstool:
        !           401: ;;;
        !           402: (defconst sm::keyword-alist 
        !           403:   '((left . 1) (middle . 2) (right . 4)
        !           404:     (shift . 8) (control . 16) (meta . 32) (double . 64) (up . 128)
        !           405:     (text . 256) (scrollbar . 512) (modeline . 1024) (minibuffer . 2048)
        !           406:     ))
        !           407: 
        !           408: (defun mouse-event-code (hit loc)
        !           409:   "Maps MOUSE-HIT and LOC into a mouse-code."
        !           410: ;;;Region is a code for one of text, modeline, scrollbar, or minibuffer.
        !           411:   (logior (sm::hit-code hit)
        !           412:          (mouse-region-to-code (sm::window-region loc))))
        !           413: 
        !           414: (defun mouse-region-to-code (region)
        !           415:   "Returns partial mouse-code for specified REGION."
        !           416:   (cdr (assq region sm::keyword-alist)))
        !           417: 
        !           418: (defun mouse-list-to-mouse-code (mouse-list)
        !           419:   "Map a MOUSE-LIST to a mouse-code."
        !           420:   (apply 'logior
        !           421:         (mapcar (function (lambda (x)
        !           422:                             (cdr (assq x sm::keyword-alist))))
        !           423:                  mouse-list)))
        !           424: 
        !           425: (defun mouse-code-to-mouse-list (mouse-code)
        !           426:   "Map a MOUSE-CODE to a mouse-list."
        !           427:   (apply 'nconc (mapcar
        !           428:                 (function (lambda (x)
        !           429:                             (if (logtest mouse-code (cdr x))
        !           430:                                 (list (car x)))))
        !           431:                 sm::keyword-alist)))
        !           432: 
        !           433: (defun mousemap-set (code mousemap value)
        !           434:   (let* ((alist (cdr mousemap))
        !           435:         (assq-result (assq code alist)))
        !           436:     (if assq-result
        !           437:        (setcdr assq-result value)
        !           438:       (setcdr mousemap (cons (cons code value) alist)))))
        !           439: 
        !           440: (defun mousemap-get (code mousemap)
        !           441:   (cdr (assq code (cdr mousemap))))
        !           442: 
        !           443: (defun mouse-lookup (mouse-code)
        !           444:   "Look up MOUSE-EVENT and return the definition. nil means undefined."
        !           445:   (or (mousemap-get mouse-code current-local-mousemap)
        !           446:       (mousemap-get mouse-code current-global-mousemap)))
        !           447: 
        !           448: ;;;
        !           449: ;;; I (jpeck) don't understand the utility of the next four functions
        !           450: ;;; ask Steven Greenbaum <froud@kestrel>
        !           451: ;;;
        !           452: (defun mouse-mask-lookup (mask list)
        !           453:   "Args MASK (a bit mask) and LIST (a list of (code . form) pairs).
        !           454: Returns a list of elements of LIST whose code or'ed with MASK is non-zero."
        !           455:   (let ((result nil))
        !           456:     (while list
        !           457:       (if (logtest mask (car (car list)))
        !           458:          (setq result (cons (car list) result)))
        !           459:       (setq list (cdr list)))
        !           460:     result))
        !           461: 
        !           462: (defun mouse-union (l l-unique)
        !           463:   "Return the union of list of mouse (code . form) pairs L and L-UNIQUE,
        !           464: where L-UNIQUE is considered to be union'ized already."
        !           465:   (let ((result l-unique))
        !           466:     (while l
        !           467:       (let ((code-form-pair (car l)))
        !           468:        (if (not (assq (car code-form-pair) result))
        !           469:            (setq result (cons code-form-pair result))))
        !           470:       (setq l (cdr l)))
        !           471:     result))
        !           472: 
        !           473: (defun mouse-union-first-prefered (l1 l2)
        !           474:   "Return the union of lists of mouse (code . form) pairs L1 and L2,
        !           475: based on the code's, with preference going to elements in L1."
        !           476:   (mouse-union l2 (mouse-union l1 nil)))
        !           477: 
        !           478: (defun mouse-code-function-pairs-of-region (region)
        !           479:   "Return a list of (code . function) pairs, where each code is
        !           480: currently set in the REGION."
        !           481:   (let ((mask (mouse-region-to-code region)))
        !           482:     (mouse-union-first-prefered
        !           483:      (mouse-mask-lookup mask (cdr current-local-mousemap))
        !           484:      (mouse-mask-lookup mask (cdr current-global-mousemap))
        !           485:      )))
        !           486: 
        !           487: ;;;
        !           488: ;;; Functions for DESCRIBE-MOUSE-BINDINGS
        !           489: ;;; And other mouse documentation functions
        !           490: ;;; Still need a good procedure to print out a help sheet in readable format.
        !           491: ;;;
        !           492: 
        !           493: (defun one-line-doc-string (function)
        !           494:   "Returns first line of documentation string for FUNCTION.
        !           495: If there is no documentation string, then the string
        !           496: \"No documentation\" is returned."
        !           497:   (while (consp function) (setq function (car function)))
        !           498:   (let ((doc (documentation function)))
        !           499:     (if (null doc)
        !           500:        "No documentation."
        !           501:       (string-match "^.*$" doc)
        !           502:       (substring doc 0 (match-end 0)))))
        !           503: 
        !           504: (defun print-mouse-format (binding)
        !           505:   (princ (car binding))
        !           506:   (princ ": ")
        !           507:   (mapcar (function
        !           508:           (lambda (mouse-list)
        !           509:             (princ mouse-list)
        !           510:             (princ " ")))
        !           511:          (cdr binding))
        !           512:   (terpri)
        !           513:   (princ "  ")
        !           514:   (princ (one-line-doc-string (car binding)))
        !           515:   (terpri)
        !           516:   )
        !           517: 
        !           518: (defun print-mouse-bindings (region)
        !           519:   "Prints mouse-event bindings for REGION."
        !           520:   (mapcar 'print-mouse-format (sm::event-bindings region)))
        !           521: 
        !           522: (defun sm::event-bindings (region)
        !           523:   "Returns an alist of (function . (mouse-list1 ... mouse-listN)) for REGION,
        !           524: where each mouse-list is bound to the function in REGION."
        !           525:   (let ((mouse-bindings (mouse-code-function-pairs-of-region region))
        !           526:        (result nil))
        !           527:     (while mouse-bindings
        !           528:       (let* ((code-function-pair (car mouse-bindings))
        !           529:             (current-entry (assoc (cdr code-function-pair) result)))
        !           530:        (if current-entry
        !           531:            (setcdr current-entry
        !           532:                    (cons (mouse-code-to-mouse-list (car code-function-pair))
        !           533:                          (cdr current-entry)))
        !           534:          (setq result (cons (cons (cdr code-function-pair)
        !           535:                                   (list (mouse-code-to-mouse-list
        !           536:                                          (car code-function-pair))))
        !           537:                             result))))
        !           538:       (setq mouse-bindings (cdr mouse-bindings))
        !           539:       )
        !           540:     result))
        !           541: 
        !           542: (defun describe-mouse-bindings ()
        !           543:   "Lists all current mouse-event bindings."
        !           544:   (interactive)
        !           545:   (with-output-to-temp-buffer "*Help*"
        !           546:     (princ "Text Region") (terpri)
        !           547:     (princ "---- ------") (terpri)
        !           548:     (print-mouse-bindings 'text) (terpri)
        !           549:     (princ "Modeline Region") (terpri)
        !           550:     (princ "-------- ------") (terpri)
        !           551:     (print-mouse-bindings 'modeline) (terpri)
        !           552:     (princ "Scrollbar Region") (terpri)
        !           553:     (princ "--------- ------") (terpri)
        !           554:     (print-mouse-bindings 'scrollbar)))
        !           555: 
        !           556: (defun describe-mouse-briefly (mouse-list)
        !           557:   "Print a short description of the function bound to MOUSE-LIST."
        !           558:   (interactive "xDescibe mouse list briefly: ")
        !           559:   (let ((function (mouse-lookup (mouse-list-to-mouse-code mouse-list))))
        !           560:     (if function
        !           561:        (message "%s runs the command %s" mouse-list function)
        !           562:       (message "%s is undefined" mouse-list))))
        !           563: 
        !           564: (defun mouse-help-menu (function-and-binding)
        !           565:   (cons (prin1-to-string (car function-and-binding))
        !           566:        (menu-create    ; Two sub-menu items of form ("String" . nil)
        !           567:         (list (list (one-line-doc-string (car function-and-binding)))
        !           568:               (list (prin1-to-string (cdr function-and-binding)))))))
        !           569: 
        !           570: (defun mouse-help-region (w x y &optional region)
        !           571:   "Displays a menu of mouse functions callable in this region."
        !           572:   (let* ((region (or region (sm::window-region (list w x y))))
        !           573:         (mlist (mapcar (function mouse-help-menu)
        !           574:                        (sm::event-bindings region)))
        !           575:         (menu (menu-create (cons (list (symbol-name region)) mlist)))
        !           576:         (item (sun-menu-evaluate w 0 y menu))
        !           577:         )))
        !           578: 
        !           579: ;;;
        !           580: ;;; Menu interface functions
        !           581: ;;;
        !           582: ;;; use defmenu, because this interface is subject to change
        !           583: ;;; really need a menu-p, but we use vectorp and the context...
        !           584: ;;;
        !           585: (defun menu-create (items)
        !           586:   "Functional form for defmenu, given a list of ITEMS returns a menu.
        !           587: Each ITEM is a (STRING . VALUE) pair."
        !           588:   (apply 'vector items)
        !           589:   )
        !           590: 
        !           591: (defmacro defmenu (menu &rest itemlist)
        !           592:   "Defines MENU to be a menu, the ITEMS are (STRING . VALUE) pairs.
        !           593: See sun-menu-evaluate for interpretation of ITEMS."
        !           594:   (list 'defconst menu (funcall 'menu-create itemlist))
        !           595:   )
        !           596: 
        !           597: (defun sun-menu-evaluate (*menu-window* *menu-x* *menu-y* menu)
        !           598:   "Display a pop-up menu in WINDOW at X Y and evaluate selected item
        !           599: of MENU.  MENU (or its symbol-value) should be a menu defined by defmenu.
        !           600:   A menu ITEM is a (STRING . FORM) pair;
        !           601: the FORM associated with the selected STRING is evaluated,
        !           602: and the resulting value is returned.  Generally these FORMs are
        !           603: evaluated for their side-effects rather than their values.
        !           604:   If the selected form is a menu or a symbol whose value is a menu, 
        !           605: then it is displayed and evaluated as a pullright menu item.
        !           606:   If the the FORM of the first ITEM is nil, the STRING of the item
        !           607: is used as a label for the menu, i.e. it's inverted and not selectible."
        !           608: 
        !           609:   (if (symbolp menu) (setq menu (symbol-value menu)))
        !           610:   (eval (sun-menu-internal *menu-window* *menu-x* *menu-y* 4 menu)))
        !           611: 
        !           612: (defun sun-get-frame-data (code)
        !           613:   "Sends the tty-sub-window escape sequence CODE to terminal,
        !           614: and returns a cons of the two numbers in returned escape sequence.
        !           615: That is it returns (cons <car> <cdr>) from \"\\E[n;<car>;<cdr>t\". 
        !           616: CODE values: 13 = Tool-Position, 14 = Size-in-Pixels, 18 = Size-in-Chars."
        !           617:   (send-string-to-terminal (concat "\033[" (int-to-string code) "t"))
        !           618:   (let (char str x y)
        !           619:     (while (not (equal 116 (setq char (read-char)))) ; #\t = 116
        !           620:       (setq str (cons char str)))
        !           621:     (setq str (mapconcat 'char-to-string (nreverse str) ""))
        !           622:     (string-match ";[0-9]*" str)
        !           623:     (setq y (substring str (1+ (match-beginning 0)) (match-end 0)))
        !           624:     (setq str (substring str (match-end 0)))
        !           625:     (string-match ";[0-9]*" str)
        !           626:     (setq x (substring str (1+ (match-beginning 0)) (match-end 0)))
        !           627:     (cons (string-to-int y) (string-to-int x))))
        !           628: 
        !           629: (defun sm::font-size ()
        !           630:   "Returns font size in pixels: (cons Ysize Xsize)"
        !           631:   (let ((pix (sun-get-frame-data 14))  ; returns size in pixels
        !           632:        (chr (sun-get-frame-data 18)))  ; returns size in chars
        !           633:     (cons (/ (car pix) (car chr)) (/ (cdr pix) (cdr chr)))))
        !           634: 
        !           635: (defvar sm::menu-kludge-x nil 
        !           636:   "Cached frame-to-window X-Offset for sm::menu-kludge")
        !           637: (defvar sm::menu-kludge-y nil 
        !           638:   "Cached frame-to-window Y-Offset for sm::menu-kludge")
        !           639: 
        !           640: (defun sm::menu-kludge ()
        !           641:   "If sunfns.c uses <Menu_Base_Kludge> this function must be here!"
        !           642:   (or sm::menu-kludge-y
        !           643:       (let ((fs (sm::font-size)))
        !           644:        (setq sm::menu-kludge-y (+ 8 (car fs))  ; a title line and borders
        !           645:              sm::menu-kludge-x 4)))    ; best values depend on .defaults/Menu
        !           646:   (let ((wl (sun-get-frame-data 13)))          ; returns frame location
        !           647:     (cons (+ (car wl) sm::menu-kludge-y)
        !           648:          (+ (cdr wl) sm::menu-kludge-x))))
        !           649: 
        !           650: ;;;
        !           651: ;;;  Function interface to selection/region
        !           652: ;;;  primative functions are defined in sunfns.c
        !           653: ;;;
        !           654: (defun sunview-yank-stuff ()
        !           655:   "Set mark and yank the contents of the current TTYSW `STUFF' selection
        !           656: into the current buffer at point.  The STUFF selection contains the currently
        !           657: or previously highlighted text from a TTYSW."
        !           658:   (interactive "*")
        !           659:   (set-mark-command nil)
        !           660:   (insert-string (sun-get-selection)))
        !           661: 
        !           662: ;;;
        !           663: (defun display-host ()
        !           664:   "Extract <host> from DISPLAY environment variable, or return nil if not specified."
        !           665:   (let ((display (getenv "DISPLAY")))
        !           666:     (if display
        !           667:        (let ((colon_at (string-match ":" display)))
        !           668:          (if colon_at
        !           669:              (if (not (zerop colon_at))
        !           670:                  (substring display 0 colon_at)
        !           671:                ))))))
        !           672: 
        !           673: ;;; get_selection has been extended to work in X
        !           674: ;;; we extend to work on remote X display...
        !           675: (defun sunview-yank-clipboard ()
        !           676:   "Set mark and yank the contents of the SunView Clipboard into the
        !           677: current buffer at point."
        !           678:   (interactive "*")
        !           679:   (set-mark-command nil)
        !           680:   (let ((host (display-host)))
        !           681:     (if host
        !           682:        (call-process "rsh" nil t t (display-host) "get_selection" "3")
        !           683:       (call-process "get_selection" nil t t "3")))
        !           684:   )
        !           685: 
        !           686: (defun sunview-yank-current-selection ()
        !           687:   "Set mark and yank the contents of the current SunView selection
        !           688: into current buffer at point. The current selection is the currently
        !           689: highlighted text in either a textsw or a ttysw."
        !           690:   (interactive "*")
        !           691:   (set-mark-command nil)
        !           692:   (let ((host (display-host)))
        !           693:     (if host
        !           694:        (call-process "rsh" nil t t (display-host) "get_selection")
        !           695:       (call-process "get_selection" nil t t))))
        !           696: 
        !           697: (defun sunview-yank-any-selection (arg)
        !           698:   "Yank one of the sunview selections:
        !           699: with no arg, the current selection; with minus-only prefix, the clipboard;
        !           700: with any other arg, the ttysw STUFF."
        !           701:   (interactive "*P")
        !           702:   (cond ((null arg) (sunview-yank-current-selection))
        !           703:        ((eq arg '-) (sunview-yank-clipboard))
        !           704:        (t (sunview-yank-stuff))))
        !           705: 
        !           706: ;;; define the selection file used by this emacs
        !           707: ;;; if not local machine, then automounter must find /net/<host>/tmp
        !           708: (defvar owselectionfilex nil "Cache path to ttysw selection file (a kludge!).")
        !           709: ;;; determine value at runtime, not when this file loaded into temacs
        !           710: (defun owselectionfile ()
        !           711:   (or owselectionfilex 
        !           712:       (let* ((host (display-host))
        !           713:             (filex 
        !           714:              (if host
        !           715:                  (concat "/net/" host "/tmp/ttyselection")
        !           716:                "/tmp/ttyselection")))
        !           717:        (if (file-exists-p filex)
        !           718:            (setq owselectionfilex filex)
        !           719:          (progn
        !           720:            (message "no TTYSW selection file")
        !           721:            nil)
        !           722:          ))))
        !           723: 
        !           724: (defun xv-yank-selection ()
        !           725:   "Set mark and yank the contents of the current Xview selection
        !           726: into the current buffer at point.  The STUFF selection contains the currently
        !           727: or previously highlighted text from a TTYSW."
        !           728:   (interactive "*")
        !           729:   (if (owselectionfile)
        !           730:       (progn
        !           731:        (insert-file (owselectionfile))
        !           732:        (exchange-point-and-mark)))
        !           733:   )
        !           734: 
        !           735: (defun xv-select-region (beg end)
        !           736:   "Set the TTYSW selection to the region in the current buffer."
        !           737:   (interactive "r")
        !           738:   (if (owselectionfile)
        !           739:       (write-region beg end (owselectionfile) nil 'noprint))
        !           740:   )
        !           741: 
        !           742: (defun sun-yank-selection ()
        !           743:   "Set mark and yank the contents of the current TTYSW `STUFF' or Xview selection
        !           744: into the current buffer at point."
        !           745:   (interactive "*")
        !           746:   (if (getenv "DISPLAY")
        !           747:       (xv-yank-selection)
        !           748:       (sunview-yank-stuff))
        !           749:   )
        !           750: 
        !           751: (defun sun-select-region (beg end)
        !           752:   "Set the TTYSW 'STUFF' or Xview selection to the region in the current buffer."
        !           753:   (interactive "r")
        !           754:   (if (getenv "DISPLAY")
        !           755:       (xv-select-region beg end)
        !           756:       (sun-set-selection (buffer-substring beg end)))
        !           757:   )
        !           758: 
        !           759: 
        !           760: 
        !           761: ;;;
        !           762: ;;; support for emacstool
        !           763: ;;; This closes the window instead of stopping emacs.
        !           764: ;;;
        !           765: (defun suspend-emacstool (&optional stuffstring)
        !           766:   "If running under as a detached process emacstool,
        !           767: you don't want to suspend  (there is no way to resume), 
        !           768: just close the window, and wait for reopening."
        !           769:   (interactive)
        !           770:   (if (and (boundp 'suspend-hook) suspend-hook)
        !           771:       (funcall suspend-hook))
        !           772:   (if stuffstring (send-string-to-terminal stuffstring))
        !           773:   (send-string-to-terminal "\033[2t")  ; To close EmacsTool window.
        !           774:   (if (and (boundp 'suspend-resume-hook) suspend-resume-hook)
        !           775:       (funcall suspend-resume-hook)))
        !           776: ;;;
        !           777: ;;; initialize mouse maps
        !           778: ;;;
        !           779: 
        !           780: (make-variable-buffer-local 'current-local-mousemap)
        !           781: (setq-default current-local-mousemap nil)
        !           782: (defvar current-global-mousemap (make-mousemap))

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.