(provide (quote sun-mouse))

(defvar extra-click-wait 150 "\
*Number of milliseconds to wait for an extra click.
Set this to zero if you don't want chords or double clicks.")

(defvar scrollbar-width 5 "\
*The character width of the scrollbar.
The cursor is deemed to be in the right edge scrollbar if it is this near the
right edge, and more than two chars past the end of the indicated line.
Setting to nil limits the scrollbar to the edge or vertical dividing bar.")

(defun make-mousemap nil "\
Returns a new mousemap." (byte-code "B" [nil mousemap] 2))

(defun copy-mousemap (mousemap) "\
Return a copy of mousemap." (byte-code "!" [mousemap copy-alist] 2))

(defun define-mouse (mousemap mouse-list def) "\
MOUSE-LIST is a list of atoms specifing a mouse hit according to these rules:
  * One of these atoms specifies the active region of the definition.
	text, scrollbar, modeline, minibuffer
  * One or two or these atoms specify the button or button combination.
        left, middle, right, double
  * Any combination of these atoms specify the active shift keys.
        control, shift, meta
  * With a single unshifted button, you can add
    to indicate an up-click.
The atom `double' is used with a button designator to denote a double click.
Two button chords are denoted by listing the two buttons.
See sun-mouse-handler for the treatment of the form DEF." (byte-code "!	
#" [mouse-list mousemap def mousemap-set mouse-list-to-mouse-code] 5))

(defun global-set-mouse (mouse-list def) "\
Give MOUSE-EVENT-LIST a local definition of DEF.
See define-mouse for a description of MOUSE-EVENT-LIST and DEF.
Note that if MOUSE-EVENT-LIST has a local definition in the current buffer,
that local definition will continue to shadow any global definition." (interactive "xMouse event: 
xDefinition: ") (byte-code "È	
#" [current-global-mousemap mouse-list def nil define-mouse] 4))

(defun local-set-mouse (mouse-list def) "\
Give MOUSE-EVENT-LIST a local definition of DEF.
See define-mouse for a description of the arguments.
The definition goes in the current buffer's local mousemap.
Normally buffers in the same major mode share a local mousemap." (interactive "xMouse event: 
xDefinition: ") (byte-code "È? 	
#" [current-local-mousemap mouse-list def nil make-mousemap define-mouse] 5))

(defun use-global-mousemap (mousemap) "\
Selects MOUSEMAP as the global mousemap." (byte-code "	" [current-global-mousemap mousemap] 2))

(defun use-local-mousemap (mousemap) "\
Selects MOUSEMAP as the local mousemap.
nil for MOUSEMAP means no local mousemap." (byte-code "	" [current-local-mousemap mousemap] 2))

(defun logtest (x y) "\
True if any bits set in X are also set in Y.
Just like the Common Lisp function of the same name." (byte-code "	\"!?" [x y zerop logand] 4))

(defconst sm::ButtonBits 7)

(defconst sm::ShiftmaskBits 56)

(defconst sm::DoubleBits 64)

(defconst sm::UpBits 128)

(defmacro sm::hit-code (hit) (byte-code "E" [hit nth 0] 3))

(defmacro sm::hit-button (hit) (byte-code "EE" [hit logand sm::ButtonBits nth 0] 5))

(defmacro sm::hit-shiftmask (hit) (byte-code "EE" [hit logand sm::ShiftmaskBits nth 0] 5))

(defmacro sm::hit-double (hit) (byte-code "EE" [hit logand sm::DoubleBits nth 0] 5))

(defmacro sm::hit-up (hit) (byte-code "EE" [hit logand sm::UpBits nth 0] 5))

(defmacro sm::hit-x (hit) (byte-code "E" [hit nth 1] 3))

(defmacro sm::hit-y (hit) (byte-code "E" [hit nth 2] 3))

(defmacro sm::hit-delta (hit) (byte-code "E" [hit nth 3] 3))

(defmacro sm::hit-up-p (hit) (byte-code "DDD" [hit not zerop sm::hit-up] 4))

(defmacro sm::loc-w (loc) (byte-code "E" [loc nth 0] 3))

(defmacro sm::loc-x (loc) (byte-code "E" [loc nth 1] 3))

(defmacro sm::loc-y (loc) (byte-code "E" [loc nth 2] 3))

(defmacro eval-in-buffer (buffer &rest forms) "Macro to switches to BUFFER, evaluates FORMS, returns to original buffer." (byte-code "DD	\"EE" [buffer forms let ((StartBuffer (current-buffer))) unwind-protect append progn set-buffer (set-buffer StartBuffer)] 7))

(put (quote eval-in-buffer) (quote lisp-indent-hook) 1)

(defmacro eval-in-window (window &rest forms) "Switch to WINDOW, evaluate FORMS, return to original window." (byte-code "DD	\"EE" [window forms let ((OriginallySelectedWindow (selected-window))) unwind-protect append progn select-window (select-window OriginallySelectedWindow)] 7))

(put (quote eval-in-window) (quote lisp-indent-hook) 1)

(defmacro eval-in-windows (form &optional yesmini) "Switches to each window and evaluates FORM.  Optional argument
YESMINI says to include the minibuffer as a window.
This is a macro, and does not evaluate its arguments." (byte-code "	EDEDEDEE" [form yesmini let ((OriginallySelectedWindow (selected-window))) unwind-protect while progn not eq OriginallySelectedWindow select-window next-window nil (select-window OriginallySelectedWindow)] 13))

(put (quote eval-in-window) (quote lisp-indent-hook) 0)

(defun move-to-loc (x y) "\
Move cursor to window location X, Y.
Handles wrapped and horizontally scrolled lines correctly." (byte-code "!i !i Z^\\\"  S^#!
	Z*" [y cc nc x move-to-window-line move-to-column zerop window-hscroll window-width 2 + -1] 13))

(defun minibuffer-window-p (window) "\
True iff this WINDOW is minibuffer." (byte-code " !8U" [window screen-height 3 window-edges] 5))

(defun sun-mouse-handler (&optional hit) "\
Evaluates the function or list associated with a mouse hit.
Expecting to read a hit, which is a list: (button x y delta).  
A form bound to button by define-mouse is found by mouse-lookup. 
The variables: *mouse-window*, *mouse-x*, *mouse-y* are bound.  
If the form is a symbol (symbolp), it is funcall'ed with *mouse-window*,
*mouse-x*, and *mouse-y* as arguments; if the form is a list (listp),
the form is eval'ed; if the form is neither of these, it is an error.
Returns nil." (interactive) (byte-code "̈? 88\"	8	8	8	\"pӎ
$<@	!\"),)	=	̇" [hit loc *mouse-window* *mouse-x* *mouse-y* mouse-code form StartBuffer sm::UpBits this-command t last-command nil sm::combined-hits sm::window-xy 1 2 0 mouse-event-code ((byte-code "q" [StartBuffer] 1)) window-buffer mouse-lookup zerop logand error "Undefined mouse event: %s" prin1-to-string mouse-code-to-mouse-list funcall eval "Mouse action must be symbol or list, but was: %s" sun-mouse-handler] 15))

(defun sm::combined-hits nil "\
Read and return next mouse-hit, include possible double click" (byte-code " 	8\"!??9!
88\"
6#\"))" [hit1 sm::UpBits hit2 extra-click-wait sm::ButtonBits sm::DoubleBits mouse-hit-read zerop logand 0 mouse-second-hit setcar logior] 15))

(defun mouse-hit-read nil "\
Read mouse-hit list from keyboard.  Like (read 'read-char),
but that uses minibuffer, and mucks up last-command." (byte-code "r
B\"?!#!*" [char-list nil char equal 13 read mapconcat char-to-string nreverse ""] 7))

(defvar mouse-prefix1 24 "\
First char of mouse-prefix.  Used to detect double clicks and chords.")

(defvar mouse-prefix2 0 "\
Second char of mouse-prefix.  Used to detect double clicks and chords.")

(defun mouse-second-hit (hit-wait) "\
Returns the next mouse hit occurring within HIT-WAIT milliseconds." (byte-code "!
 X 8\"!?U8Z!W)))" [hit-wait nil pc1 mouse-prefix1 unread-command-char pc2 mouse-prefix2 new-hit sm::UpBits sit-for-millisecs equal 3 ding mouse-hit-read zerop logand 0 mouse-second-hit] 12))

(defun sm::window-xy (x y) "\
Find window containing screen coordinates X and Y.
Returns list (window x y) where x and y are relative to window." (byte-code "č
E" [nil x y found (byte-code " ˎ !	8	8	8	8 U%T
ZZE\",)\"!=?pȈ))" [OriginallySelectedWindow we le te re be x y nil t selected-window ((byte-code "!" [OriginallySelectedWindow select-window] 2)) window-edges 0 1 2 3 screen-width screen-height throw found select-window next-window] 12)] 3))

(defun sm::window-region (loc) "\
Parse LOC into a region symbol.
Returns one of (text scrollbar modeline minibuffer)" (byte-code "	8	8	8!S!S! ΂S

#\\YRЂS*+" [w loc x y right bottom scrollbar-width t 0 1 2 window-width window-height minibuffer-window-p minibuffer modeline scrollbar window-line-end text] 9))

(defun window-line-end (w x y) "\
Return WINDOW column (ignore X) containing end of line Y" (byte-code " Ď	! 
\")))" [OriginallySelectedWindow w y selected-window ((byte-code "!" [OriginallySelectedWindow select-window] 2)) select-window move-to-loc screen-width] 6))

(defconst sm::keyword-alist (quote ((left . 1) (middle . 2) (right . 4) (shift . 8) (control . 16) (meta . 32) (double . 64) (up . 128) (text . 256) (scrollbar . 512) (modeline . 1024) (minibuffer . 2048))))

(defun mouse-event-code (hit loc) "\
Maps MOUSE-HIT and LOC into a mouse-code." (byte-code "8	!!\"" [hit loc logior 0 mouse-region-to-code sm::window-region] 5))

(defun mouse-region-to-code (region) "\
Returns partial mouse-code for specified REGION." (byte-code "	\"A" [region sm::keyword-alist assq] 3))

(defun mouse-list-to-mouse-code (mouse-list) "\
Map a MOUSE-LIST to a mouse-code." (byte-code "\"\"" [mouse-list apply logior mapcar (lambda (x) (byte-code "	\"A" [x sm::keyword-alist assq] 3))] 5))

(defun mouse-code-to-mouse-list (mouse-code) "\
Map a MOUSE-CODE to a mouse-list." (byte-code "\"\"" [sm::keyword-alist apply nconc mapcar (lambda (x) (byte-code "	A\"	@C" [mouse-code x logtest] 3))] 5))

(defun mousemap-set (code mousemap value) (byte-code "	A\"

\"	BB\"*" [alist mousemap assq-result code value assq setcdr] 6))

(defun mousemap-get (code mousemap) (byte-code "	A\"A" [code mousemap assq] 3))

(defun mouse-lookup (mouse-code) "\
Look up MOUSE-EVENT and return the definition. nil means undefined." (byte-code "	\"
\"" [mouse-code current-local-mousemap current-global-mousemap mousemap-get] 4))

(defun mouse-mask-lookup (mask list) "\
Args MASK (a bit mask) and LIST (a list of (code . form) pairs).
Returns a list of elements of LIST whose code or'ed with MASK is non-zero." (byte-code "

A)" [result nil list mask logtest] 4))

(defun mouse-union (l l-unique) "\
Return the union of list of mouse (code . form) pairs L and L-UNIQUE,
where L-UNIQUE is considered to be union'ized already." (byte-code "	
A)" [result l-unique l code-form-pair assq] 4))

(defun mouse-union-first-prefered (l1 l2) "\
Return the union of lists of mouse (code . form) pairs L1 and L2,
based on the code's, with preference going to elements in L1." (byte-code "	\"\"" [l2 l1 nil mouse-union] 5))

(defun mouse-code-function-pairs-of-region (region) "\
Return a list of (code . function) pairs, where each code is
currently set in the REGION." (byte-code "	!
A\"A\"\")" [mask region current-local-mousemap current-global-mousemap mouse-region-to-code mouse-union-first-prefered mouse-mask-lookup] 7))

(defun one-line-doc-string (function) "\
Returns first line of documentation string for FUNCTION.
If there is no documentation string, then the string
\"No documentation\" is returned." (byte-code ":
@!	?Â&	\"	!O)" [function doc documentation "No documentation." string-match "^.*$" 0 match-end] 6))

(defun print-mouse-format (binding) (byte-code "@!!A\" !@!! " [binding princ ": " mapcar (lambda (mouse-list) (byte-code "!!" [mouse-list princ " "] 3)) terpri "  " one-line-doc-string] 9))

(defun print-mouse-bindings (region) "\
Prints mouse-event bindings for REGION." (byte-code "!\"" [region mapcar print-mouse-format sm::event-bindings] 4))

(defun sm::event-bindings (region) "\
Returns an alist of (function . (mouse-list1 ... mouse-listN)) for REGION,
where each mouse-list is bound to the function in REGION." (byte-code "	!:@A
AB\"0A@!CB
*" [mouse-bindings region result nil code-function-pair current-entry mouse-code-function-pairs-of-region assoc setcdr mouse-code-to-mouse-list] 8))

(defun describe-mouse-bindings nil "\
Lists all current mouse-event bindings." (interactive) (byte-code "! ! ! ! ! ! ! ! !" [nil "*Help*" princ "Text Region" terpri "---- ------" print-mouse-bindings text "Modeline Region" "-------- ------" modeline "Scrollbar Region" "--------- ------" scrollbar] 19))

(defun describe-mouse-briefly (mouse-list) "\
Print a short description of the function bound to MOUSE-LIST." (interactive "xDescibe mouse list briefly: ") (byte-code "ˆ	!!	#	\")" [function mouse-list nil mouse-lookup mouse-list-to-mouse-code message "%s runs the command %s" "%s is undefined"] 6))

(defun mouse-help-menu (function-and-binding) (byte-code "@!@!CA!CD!B" [function-and-binding prin1-to-string menu-create one-line-doc-string] 7))

(defun mouse-help-region (w x y &optional region) "\
Displays a menu of mouse functions callable in this region." (byte-code "
E!K!\"!CB!	
$," [region w x y mlist menu item sm::window-region mapcar mouse-help-menu sm::event-bindings menu-create symbol-name sun-menu-evaluate 0 nil] 11))

(defun menu-create (items) "\
Functional form for defmenu, given a list of ITEMS returns a menu.
Each ITEM is a (STRING . VALUE) pair." (byte-code "\"" [items apply vector] 3))

(defmacro defmenu (menu &rest itemlist) "Defines MENU to be a menu, the ITEMS are (STRING . VALUE) pairs.
See sun-menu-evaluate for interpretation of ITEMS." (byte-code "	\"E" [menu itemlist defconst funcall menu-create] 5))

(defun sun-menu-evaluate (*menu-window* *menu-x* *menu-y* menu) "\
Display a pop-up menu in WINDOW at X Y and evaluate selected item
of MENU.  MENU (or its symbol-value) should be a menu defined by defmenu.
  A menu ITEM is a (STRING . FORM) pair;
the FORM associated with the selected STRING is evaluated,
and the resulting value is returned.  Generally these FORMs are
evaluated for their side-effects rather than their values.
  If the selected form is a menu or a symbol whose value is a menu, 
then it is displayed and evaluated as a pullright menu item.
  If the the FORM of the first ITEM is nil, the STRING of the item
is used as a label for the menu, i.e. it's inverted and not selectible." (byte-code "9	J	
%!" [menu *menu-window* *menu-x* *menu-y* eval sun-menu-internal 4] 7))

(defun sun-get-frame-data (code) "\
Sends the tty-sub-window escape sequence CODE to terminal,
and returns a cons of the two numbers in returned escape sequence.
That is it returns (cons <car> <cdr>) from \"\\E[n;<car>;<cdr>t\". 
CODE values: 13 = Tool-Position, 14 = Size-in-Pixels, 18 = Size-in-Chars." (byte-code "!Q!r\"?$	
!T!O!!B," [code char str x y send-string-to-terminal "[" int-to-string "t" nil equal 116 mapconcat char-to-string nreverse "" string-match ";[0-9]*" match-beginning 0 match-end string-to-int] 16))

(defun sm::font-size nil "\
Returns font size in pixels: (cons Ysize Xsize)" (byte-code "!!@	@\"A	A\"B*" [pix chr sun-get-frame-data 14 18 /] 7))

(defvar sm::menu-kludge-x nil "\
Cached frame-to-window X-Offset for sm::menu-kludge")

(defvar sm::menu-kludge-y nil "\
Cached frame-to-window Y-Offset for sm::menu-kludge")

(defun sm::menu-kludge nil "\
If sunfns.c uses <Menu_Base_Kludge> this function must be here!" (byte-code " 	@\\Ɖ)!@\\A
\\B)" [sm::menu-kludge-y fs sm::menu-kludge-x wl sm::font-size 8 4 sun-get-frame-data 13] 5))

(defun sun-yank-selection nil "\
Set mark and yank the contents of the current sunwindows selection
into the current buffer at point." (interactive "*") (byte-code "! !" [nil set-mark-command insert-string sun-get-selection] 4))

(defun sun-select-region (beg end) "\
Set the sunwindows selection to the region in the current buffer." (interactive "r") (byte-code "ˆ	\"!" [beg end nil sun-set-selection buffer-substring] 4))

(defun suspend-emacstool (&optional stuffstring) "\
If running under as a detached process emacstool,
you don't want to suspend  (there is no way to resume), 
just close the window, and wait for reopening." (interactive) (byte-code "È!	!		!!!#
!" [suspend-hook stuffstring suspend-resume-hook nil boundp funcall send-string-to-terminal ""] 7))

(make-variable-buffer-local (quote current-local-mousemap))

(setq-default current-local-mousemap nil)

(defvar current-global-mousemap (make-mousemap))