diff lisp/modes/outl-mouse.el @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children 4b173ad71786
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/modes/outl-mouse.el	Mon Aug 13 08:45:50 2007 +0200
@@ -0,0 +1,617 @@
+;;; outl-mouse.el --- outline mode mouse commands for Emacs
+
+;; Copyright 1994 (C) Andy Piper <ajp@eng.cam.ac.uk>
+;; Keywords: outlines, mouse
+
+;; This file is part of XEmacs.
+
+;; XEmacs is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; XEmacs is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with XEmacs; see the file COPYING.  If not, write to the Free
+;; Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+;;
+;; outl-mouse.el v1.3.8:
+;;
+;; Defines button one to hide  blocks when clicked on outline-up-arrow
+;; and expand blocks when clicked on outline-down-arrow.  Features are
+;; activated   when   outline-minor-mode  or   outline-mode are turned
+;; on. There is also a menu for each glyph on button 3. 
+;;
+;; To use put:
+;; 	(require 'outl-mouse)
+;; in your .emacs file.
+;;
+;; If you use func-menu all  the time and  want outl-mouse on all  the
+;; time as well then put:
+;;	(setq outline-sync-with-func-menu t)
+;; outlining will then be turned on when func-menu is. Note that this
+;; requires a patch to func-menu 2.16 (in 19.10) to work:
+;;
+;RCS file: func-menu.el,v
+;retrieving revision 1.1
+;diff -r1.1 func-menu.el
+;180a181,183
+;> (defvar fume-found-function-hook nil
+;>   "*Hook to call after every function match.")
+;> 
+;1137,1138c1140,1142
+;<         (if (listp funcname)
+;<             (setq funclist (cons funcname funclist)))
+;---
+;>         (cond ((listp funcname)
+;>              (setq funclist (cons funcname funclist))
+;>              (save-excursion (run-hooks 'fume-found-function-hook))))
+;;
+;; If you  want mac-style outlining  then set  outline-mac-style to t.
+;; If you   want    the  outline   arrows on    the    left then   set
+;; outline-glyphs-on-left  to t. If you  have xpm then arrows are much
+;; better defined.
+;;
+;; This package uses func-menu to  define outline regexps if they  are
+;; not already defined. You should no longer need to use out-xtra.
+;;
+;; You can define the package to  do something other than outlining by
+;; setting outline-fold-in-function and outline-fold-out-function.
+;;
+;; You can define the color of outline arrows, but only in your .emacs.
+;;
+;; Only works in XEmacs 19.10 and onwards. 
+;;
+;; User definable variables.
+;;
+(defvar outline-mac-style nil
+  "*If t then outline glyphs will be right and down arrows.")
+
+(defvar outline-glyphs-on-left nil
+  "*The position of outline glyphs on a line.")
+
+(defvar outline-glyph-colour "Gray75"
+  "*The colour of outlining arrows.")
+
+(defvar outline-glyph-shade-colour "Gray40"
+  "*The shadow colour of outlining arrows.")
+
+(defvar outline-glyph-lit-colour "Gray90"
+  "*The lit colour of outlining arrows.")
+
+(defvar outline-fold-in-function 'outline-fold-in
+  "Function to call for folding in. 
+The function should take an annotation argument.")
+(make-variable-buffer-local 'outline-fold-in-function)
+
+(defvar outline-fold-out-function 'outline-fold-out
+  "Function to call for folding out. 
+The function should take an annotation argument.")
+(make-variable-buffer-local 'outline-fold-out-function)
+
+(defvar outline-sync-with-func-menu nil
+  "*If t then outline glyphs are permanently added by func-menu scans.
+If outline-minor-mode is  turned off then  turing it back on will have
+no  effect. Instead the  buffer  should be rescanned from the function
+menu.")
+
+(defvar outline-move-point-after-click t
+  "*If t then point is moved to the current heading when clicked.")
+
+(defvar outline-scanning-message "Adding glyphs... (%3d%%)"
+  "*Progress message during the scanning of the buffer.
+Set this to nil to inhibit progress messages.")
+
+;;
+;; No user definable variables beyond this point.
+;;
+(defconst outline-up-arrow
+  (make-pixmap	; an up-arrow
+   (if (featurep 'xpm)
+       (concat "/* XPM */
+static char * arrow[] = {
+\"10 10 5 1\",
+\" 	c none\",
+\".	c " outline-glyph-lit-colour "\",
+\"X	c " outline-glyph-shade-colour "\",
+\"o	c " outline-glyph-colour "\",
+\"O	c " outline-glyph-shade-colour "\",
+\"    .X    \",
+\"    .X    \",
+\"   ..XX   \",
+\"   ..XX   \",
+\"  ..ooXX  \",
+\"  ..ooXX  \",
+\" ..ooooXX \",
+\" ..ooooXX \",
+\"..OOOOOOXX\",
+\"OOOOOOOOOO\"};")
+     (list 10 10 (concat "\000\000\000\000\060\000\060\000\150\000"
+			 "\150\000\324\000\324\000\376\001\376\001"))))
+  "Bitmap object for outline up glyph.")
+
+(defconst outline-up-arrow-mask
+  (make-pixmap	; an up-arrow
+   (if (featurep 'xpm)
+       (concat "/* XPM */
+static char * arrow[] = {
+\"10 10 5 1\",
+\" 	c none\",
+\".	c " outline-glyph-shade-colour "\",
+\"X	c " outline-glyph-lit-colour "\",
+\"o	c " outline-glyph-colour "\",
+\"O	c " outline-glyph-lit-colour "\",
+\"    .X    \",
+\"    .X    \",
+\"   ..XX   \",
+\"   ..XX   \",
+\"  ..ooXX  \",
+\"  ..ooXX  \",
+\" ..ooooXX \",
+\" ..ooooXX \",
+\"..OOOOOOXX\",
+\"OOOOOOOOOO\"};")
+     (list 10 10 (concat "\000\000\000\000\060\000\060\000\130\000"
+			 "\130\000\254\000\274\000\006\001\376\001"))))
+  "Bitmap object for outline depressed up glyph.")
+
+(defconst outline-down-arrow
+  (make-pixmap	; a down-arrow
+   (if (featurep 'xpm)
+       (concat "/* XPM */
+static char * down[] = {
+\"10 10 5 1\",
+\" 	c " outline-glyph-lit-colour "\",
+\".	c " outline-glyph-lit-colour "\",
+\"X	c " outline-glyph-shade-colour "\",
+\"o	c none\",
+\"O	c " outline-glyph-colour "\",
+\"          \",
+\"..      XX\",
+\"o..OOOOXXo\",
+\"o..OOOOXXo\",
+\"oo..OOXXoo\",
+\"oo..OOXXoo\",
+\"ooo..XXooo\",
+\"ooo..XXooo\",
+\"oooo.Xoooo\",
+\"oooo.Xoooo\"};")
+     (list 10 10 (concat "\000\000\000\000\376\001\202\001\364\000"
+			 "\324\000\150\000\150\000\060\000\060\000"))))
+  "Bitmap object for outline down glyph.")
+
+(defconst outline-down-arrow-mask
+  (make-pixmap	; a down-arrow
+   (if (featurep 'xpm)
+       (concat "/* XPM */
+static char * down[] = {
+\"10 10 5 1\",
+\" 	c " outline-glyph-shade-colour "\",
+\".	c " outline-glyph-shade-colour "\",
+\"X	c " outline-glyph-lit-colour "\",
+\"o	c none\",
+\"O	c " outline-glyph-colour "\",
+\"          \",
+\"..      XX\",
+\"o..OOOOXXo\",
+\"o..OOOOXXo\",
+\"oo..OOXXoo\",
+\"oo..OOXXoo\",
+\"ooo..XXooo\",
+\"ooo..XXooo\",
+\"oooo.Xoooo\",
+\"oooo.Xoooo\"};")
+   (list 10 10 (concat "\000\000\000\000\376\001\376\001\254\000"
+		       "\254\000\130\000\130\000\060\000\060\000"))))
+  "Bitmap object for outline depressed down glyph.")
+
+(defconst outline-right-arrow
+  (make-pixmap	; a right-arrow
+   (if (featurep 'xpm)
+       (concat "/* XPM */
+static char * right[] = {
+\"10 10 5 1\",
+\" 	c " outline-glyph-lit-colour "\",
+\".	c " outline-glyph-lit-colour "\",
+\"X	c none\",
+\"o	c " outline-glyph-colour "\",
+\"O	c " outline-glyph-shade-colour "\",
+\" .XXXXXXXX\",
+\" ...XXXXXX\",
+\"  ....XXXX\",
+\"  oo....XX\",
+\"  oooo....\",
+\"  ooooOOOO\",
+\"  ooOOOOXX\",
+\"  OOOOXXXX\",
+\" OOOXXXXXX\",
+\" OXXXXXXXX\"};")
+   (list 10 10 (concat "\000\000\006\000\032\000\142\000\232\001"
+		       "\352\001\172\000\036\000\006\000\000\000"))))
+  "Bitmap object for outline right glyph.")
+
+(defconst outline-right-arrow-mask
+  (make-pixmap	; a right-arrow
+   (if (featurep 'xpm)
+       (concat "/* XPM */
+static char * right[] = {
+\"10 10 5 1\",
+\" 	c " outline-glyph-shade-colour "\",
+\".	c " outline-glyph-shade-colour "\",
+\"X	c none\",
+\"o	c " outline-glyph-colour "\",
+\"O	c " outline-glyph-lit-colour "\",
+\" .XXXXXXXX\",
+\" ...XXXXXX\",
+\"  ....XXXX\",
+\"  oo....XX\",
+\"  oooo....\",
+\"  ooooOOOO\",
+\"  ooOOOOXX\",
+\"  OOOOXXXX\",
+\" OOOXXXXXX\",
+\" OXXXXXXXX\"};")
+   (list 10 10 (concat "\000\000\006\000\036\000\176\000\346\001"
+		       "\236\001\146\000\036\000\006\000\000\000"))))
+  "Bitmap object for outline depressed right glyph.")
+
+(defvar outline-glyph-menu
+  '("Outline Commands"
+    ["Hide all"		hide-body			t]
+    ["Hide all subtrees" hide-subtrees-same-level	t]
+    "---"
+    ["Hide subtree"	hide-subtree                    t]
+    ["Hide body"        hide-body                       t]
+    ["Show subtree"	show-subtree                    t]
+    ["Show body"        show-entry                      t]
+    "---"
+    ["Update buffer"	outline-add-glyphs		t]
+    ["Rescan buffer"	outline-rescan-buffer		t])
+  "Menu of commands for outline glyphs.")
+
+(set-pixmap-contributes-to-line-height outline-down-arrow nil)
+(set-pixmap-contributes-to-line-height outline-up-arrow nil)
+(set-pixmap-contributes-to-line-height outline-down-arrow-mask nil)
+(set-pixmap-contributes-to-line-height outline-up-arrow-mask nil)
+(set-pixmap-contributes-to-line-height outline-right-arrow nil)
+(set-pixmap-contributes-to-line-height outline-right-arrow-mask nil)
+
+(require 'annotations)
+(require 'advice)			; help me doctor !
+(require 'outline)
+(require 'func-menu)			; for those most excellent regexps.
+
+(add-hook 'outline-mode-hook 'outline-mouse-hooks)
+(add-hook 'outline-minor-mode-hook 'outline-mouse-hooks)
+;; I thought this was done already ...
+(make-variable-buffer-local 'outline-regexp)
+(make-variable-buffer-local 'outline-level)
+
+(cond (outline-sync-with-func-menu
+       (add-hook 'fume-found-function-hook 'outline-heading-add-glyph-1)
+       (setq-default fume-rescan-buffer-hook '(lambda () 
+						(outline-minor-mode 1)))))
+
+(defadvice fume-set-defaults (after fume-set-defaults-ad activate)
+  "Advise fume-set-defaults to setup outline regexps."
+  (if (and (not (assq 'outline-regexp (buffer-local-variables)))
+	   fume-function-name-regexp)
+      (progn
+	(setq outline-regexp (if (listp fume-function-name-regexp)
+				 (car fume-function-name-regexp)
+			       fume-function-name-regexp))
+	(setq outline-level '(lambda () 1)))))
+
+(defadvice outline-minor-mode (after outline-mode-mouse activate)
+  "Advise outline-minor-mode to delete glyphs when switched off."
+  (if (not outline-minor-mode)
+      (progn 
+	(outline-delete-glyphs)
+	(show-all))))
+
+;; advise all outline commands so that glyphs are synced after use
+(defadvice show-all (after show-all-ad activate)
+  "Advise show-all to sync headings."
+  (outline-sync-visible-sub-headings-in-region (point-min) (point-max)))
+
+(defadvice hide-subtree (after hide-subtree-ad activate)
+  "Advise hide-subtree to sync headings."
+  (outline-sync-visible-sub-headings))
+
+(defadvice hide-entry (after hide-entry-ad activate)
+  "Advise hide-entry to sync headings."
+  (outline-sync-visible-sub-headings))
+
+(defadvice hide-body (after hide-body-ad activate)
+  "Advise hide-body to sync headings."
+  (outline-sync-visible-sub-headings-in-region (point-min) (point-max)))
+
+(defadvice show-subtree (after show-subtree-ad activate)
+  "Advise show-subtree to sync headings."
+  (outline-sync-visible-sub-headings))
+
+(defadvice show-entry (after show-entry-ad activate)
+  "Advise shown-entry to sync headings."
+  (outline-sync-visible-sub-headings))
+
+;;;###autoload
+(defun outl-mouse-mode ()
+  "Calls outline-mode, with outl-mouse extensions"
+  (interactive)
+  (outline-mode))
+    
+;;;###autoload
+(defun outl-mouse-minor-mode (&optional arg)
+  "Toggles outline-minor-mode, with outl-mouse extensions"
+  (interactive "P")
+  (outline-minor-mode arg))
+
+(defun hide-subtrees-same-level ()
+  "Hide all subtrees below the current level."
+  (interactive)
+  (save-excursion
+    (while (progn
+	     (hide-subtree)
+      	     (condition-case nil
+		 (progn
+		   (outline-forward-same-level 1)
+		   t)
+	       (error nil))))))
+
+(defun outline-mouse-hooks ()
+  "Hook for installing outlining with the mouse."
+  ;; use function menu regexps if not set
+  (fume-set-defaults)
+  ;; only add glyphs when we're not synced.
+  (if (not outline-sync-with-func-menu) (outline-add-glyphs))
+  ;; add C-a to local keymap
+  (let ((outline (cond ((keymapp (lookup-key (current-local-map)
+					     outline-minor-mode-prefix))
+			(lookup-key (current-local-map)
+				    outline-minor-mode-prefix))
+		       (t
+			(define-key (current-local-map)
+			  outline-minor-mode-prefix (make-sparse-keymap))
+			(lookup-key (current-local-map) 
+				    outline-minor-mode-prefix)))))
+    (define-key outline "\C-a" 'outline-heading-add-glyph)
+    (define-key outline-mode-map "\C-c\C-a" 'outline-heading-add-glyph)))
+
+(defun outline-add-glyphs ()
+  "Add annotations and glyphs to all heading lines that don't have them."
+  (interactive)
+  (save-excursion
+    (and outline-scanning-message (message outline-scanning-message 0))
+    (goto-char (point-min))
+    (if (not (outline-on-heading-p)) (outline-next-visible-heading-safe))
+    (while 
+	(progn
+	  (outline-heading-add-glyph-1)
+	  (and outline-scanning-message 
+	       (message outline-scanning-message (fume-relative-position)))
+	  (outline-next-visible-heading-safe)))
+    (and outline-scanning-message 
+	 (message "%s done" (format outline-scanning-message 100)))))
+
+(defun outline-delete-glyphs ()
+  "Remove annotations and glyphs from heading lines."
+  (save-excursion
+    (mapcar 'outline-heading-delete-glyph (annotation-list))))
+
+(defun outline-rescan-buffer ()
+  "Remove and insert all annotations."
+  (interactive)
+  (outline-delete-glyphs)
+  (outline-add-glyphs)
+  (save-excursion
+    (outline-sync-visible-sub-headings-in-region (point-min) (point-max))))
+
+(defun outline-heading-delete-glyph (ext)
+  "Delete annotation and glyph from a heading with annotation EXT."
+  (if (and 
+       (progn
+	 (goto-char (extent-start-position ext))
+	 (beginning-of-line)
+	 (outline-on-heading-p))
+       (extent-property ext 'outline))
+      (delete-annotation ext))
+  nil)
+
+(defun outline-heading-add-glyph ()
+  "Interactive version of outline-heading-add-glyph-1."
+  (interactive)
+  (save-excursion
+    (outline-heading-add-glyph-1)))
+
+(defun outline-heading-add-glyph-1 ()
+  "Add glyph to the end of heading line which point is on.
+ Returns nil if point is not on a heading or glyph already exists."
+  (if (or (not (outline-on-heading-p))
+	  (outline-heading-has-glyph-p)
+	  (save-excursion (forward-line) (outline-on-heading-p)))
+      nil
+    (outline-back-to-heading)
+    (let ((anot2 
+	   (make-annotation (if outline-mac-style 
+				outline-right-arrow
+			      outline-down-arrow)
+			    (save-excursion (if outline-glyphs-on-left nil
+					      (outline-end-of-heading))
+					    (point))
+			    'text nil t 
+			    (if outline-mac-style
+				outline-right-arrow-mask
+			      outline-down-arrow-mask)))
+	  (anot1 
+	   (make-annotation (if outline-mac-style
+				outline-down-arrow
+			      outline-up-arrow)
+			    (save-excursion (if outline-glyphs-on-left nil
+					      (outline-end-of-heading))
+					    (point))
+			    'text nil t 
+			    (if outline-mac-style
+				outline-down-arrow-mask
+			      outline-up-arrow-mask))))
+      ;; we cunningly make the annotation data point to its twin.
+      (set-annotation-data anot1 anot2)
+      (set-extent-property anot1 'outline 'up)
+      (set-annotation-action anot1 'outline-up-click)
+      (set-annotation-menu anot1 outline-glyph-menu)
+      (set-extent-priority anot1 1)
+      (set-annotation-data anot2 anot1)
+      (set-extent-property anot2 'outline 'down)
+      (set-annotation-menu anot2 outline-glyph-menu)
+      (set-annotation-action anot2 'outline-down-click)
+      (annotation-hide anot2))
+    t))
+
+(defun outline-heading-has-glyph-p ()
+  "Return t if heading has an outline glyph."
+  (catch 'found
+    (mapcar
+     '(lambda(a)
+	(if (extent-property a 'outline)
+	    (throw 'found t)))
+     (annotations-in-region (save-excursion (outline-back-to-heading) (point))
+			    (save-excursion (outline-end-of-heading) 
+					    (+ 1 (point)))
+			    (current-buffer)))
+    nil))
+
+(defun outline-sync-visible-sub-headings-in-region (pmin pmax)
+  "Make sure all anotations on headings in region PMIN PMAX are 
+displayed correctly."
+  (mapcar '(lambda (x) 
+	     (goto-char (extent-start-position x))
+	     (beginning-of-line)
+	     (cond ((and (eq (extent-property x 'outline) 'down)
+			 ;; skip things we can't see
+			 (not (eq (preceding-char) ?\^M)))
+		    (if (outline-more-to-hide)
+			;; reveal my twin
+			(annotation-reveal (annotation-data x))
+		      (annotation-hide (annotation-data x)))
+		    (if (not (outline-hidden-p))
+			;; hide my self
+			(annotation-hide x)
+		      (annotation-reveal x)))))
+	  (annotations-in-region pmin pmax (current-buffer))))
+
+(defun outline-sync-visible-sub-headings ()
+  "Make sure all anotations on sub-headings below the one point is on are 
+displayed correctly."
+  (outline-sync-visible-sub-headings-in-region 
+   (point) 
+   (progn (outline-end-of-subtree) (point))))
+
+(defun outline-fold-out (annotation)
+  "Fold out the current heading."
+  (beginning-of-line)
+;  (if (not (equal (condition-case nil
+;		      (save-excursion (outline-next-visible-heading 1)
+;				      (point))
+;		    (error nil))
+;		  (save-excursion (outline-next-heading) 
+;				  (if (eobp) nil (point)))))
+  (if (save-excursion (outline-next-heading) 
+		      (eq (preceding-char) ?\^M))
+      (progn 
+	(save-excursion (show-children))
+	(outline-sync-visible-sub-headings))
+    ;; mess with single entry
+    (if (outline-hidden-p) 
+	(progn 
+	  (save-excursion (show-entry))
+	  ;; reveal my twin and hide me
+	  (annotation-hide annotation)
+	  (annotation-reveal (annotation-data annotation))))))
+
+(defun outline-fold-in (annotation)
+  "Fold in the current heading."
+  (beginning-of-line)
+  ;; mess with single entries
+  (if (not (outline-hidden-p))
+      (progn
+	(save-excursion (hide-entry))
+	(if (not (outline-more-to-hide))
+	    (annotation-hide annotation))
+	(annotation-reveal (annotation-data annotation)))
+    ;; otherwise look for more leaves
+    (save-excursion 
+      (if (outline-more-to-hide t)
+	  (hide-subtree)
+	(hide-leaves)))
+    ;; sync everything
+    (outline-sync-visible-sub-headings)))
+
+(defun outline-more-to-hide (&optional arg)
+  "Return t if there are more visible sub-headings or text.
+With ARG return t only if visible sub-headings have no visible text."
+  (if (not (outline-hidden-p))
+      (if arg nil t)
+    (save-excursion
+      (and (< (funcall outline-level) (condition-case nil
+					  (progn 
+					    (outline-next-visible-heading 1)
+					    (funcall outline-level))
+					(error 0)))
+	   (if (and (not (outline-hidden-p)) arg)
+	       nil t)))))
+
+(defun outline-hidden-p ()
+  "Return t if point is on the header of a hidden subtree."
+  (save-excursion
+    (let ((end-of-entry (save-excursion (outline-next-heading))))
+      ;; Make sure that the end of the entry really exists.
+      (if (not end-of-entry)
+	  (setq end-of-entry (point-max)))
+      (outline-back-to-heading)
+      ;; If there are ANY ^M's, the entry is hidden.
+      (search-forward "\^M" end-of-entry t))))
+
+(defun outline-next-visible-heading-safe ()
+  "Safely go to the next visible heading. 
+nil is returned if there is none."
+  (condition-case nil
+      (progn
+	(outline-next-visible-heading 1)
+	t)
+    (error nil)))
+
+(defun outline-up-click (data ev)
+  "Annotation action for clicking on an up arrow.
+DATA is the annotation data. EV is the mouse click event."
+  (save-excursion
+    (goto-char (extent-end-position (event-glyph-extent ev)))
+    (funcall outline-fold-in-function (event-glyph-extent ev)))
+  (if outline-move-point-after-click
+      (progn
+	(goto-char (extent-end-position (event-glyph-extent ev)))
+	(beginning-of-line))))
+; This line demonstrates a bug in redisplay
+(defun outline-down-click (data ev)
+  "Annotation action for clicking on a down arrow.
+DATA is the annotation data. EV is the mouse click event."
+  (save-excursion
+    (goto-char (extent-end-position (event-glyph-extent ev)))
+    (funcall outline-fold-out-function (event-glyph-extent ev)))
+  (if outline-move-point-after-click
+      (progn
+	(goto-char (extent-end-position (event-glyph-extent ev)))
+	(beginning-of-line))))
+
+
+(provide 'outl-mouse)
+(provide 'outln-18)			; fool auctex - outline is ok now.
+
+;; Local Variables:
+;; outline-regexp: ";;; \\|(def.."
+;; End:
+
+
+