Mercurial > hg > xemacs-beta
diff lisp/hyperbole/hui-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 | 4103f0995bd7 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/hyperbole/hui-mouse.el Mon Aug 13 08:45:50 2007 +0200 @@ -0,0 +1,999 @@ +;;!emacs +;; +;; FILE: hui-mouse.el +;; SUMMARY: Use key or mouse key for many functions, e.g. Hypb menus. +;; See the "${data-directory}/hypb-mouse.txt" file and the +;; documentation strings for functions herein. +;; USAGE: GNU Emacs Lisp Library +;; KEYWORDS: hypermedia, mouse +;; +;; AUTHOR: Bob Weiner +;; ORG: Brown U. +;; +;; ORIG-DATE: 04-Feb-89 +;; LAST-MOD: 1-Nov-95 at 20:45:57 by Bob Weiner +;; +;; This file is part of Hyperbole. +;; Available for use and distribution under the same terms as GNU Emacs. +;; +;; Copyright (C) 1989-1995, Free Software Foundation, Inc. +;; Developed with support from Motorola Inc. +;; +;; DESCRIPTION: +;; +;; This code is machine independent. It works best with a pointing device but +;; may also be used from a keyboard. When used with a pointing device it +;; requires an Emacs command that sets point to the location of the pointing +;; device's cursor. +;; +;; If you want to use your shift-middle mouse button to select Hyperbole menu +;; items and Hyperbole buttons, follow these instructions. +;; +;; If you plan to use a mouse only with X windows (Lucid Emacs, GNU Emacs +;; 19, or Epoch), NEXTSTEP, SunView, Apollo's DM, and you want to use the +;; shift-middle and shift-right buttons, you need not do any mouse +;; configuration. Your Emacs executable must have been built so as to +;; include the mouse support files for your window system, however. These +;; are in the Emacs "src" directory: for X "x*.c", for SunView "sunfns.c", +;; and for Apollo DM "apollo.c" and "apollo.el". +;; +;; To use a different mouse key or a different window system, modify the +;; mouse key bindings in "hmouse-key.el". +;; +;; Using the Action Mouse Key to browse through and delete files from +;; Dired listings is exceptionally nice, just as it is when reading mail. +;; +;; DESCRIP-END. + +;;; ************************************************************************ +;;; Public variables +;;; ************************************************************************ + +(defvar hmouse-set-point-command nil + "*Command that sets point to mouse cursor position.") + +(defvar action-key-default-function 'hui:menu + "*Symbol name of function run by the Action Key in an unspecified context.") + +(defvar assist-key-default-function 'hkey-summarize + "*Symbol name of function run by the Assist Key in an unspecified context.") + +;;; ************************************************************************ +;;; Hyperbole context-sensitive keys dispatch table +;;; ************************************************************************ + +(defvar hkey-value nil + "Communicates a value between a Smart Key predicate and its actions.") + +(defvar hkey-alist + '( + ;; + ;; If click in the minibuffer and reading an argument, + ;; accept argument or give completion help. + ((and (> (minibuffer-depth) 0) + (eq (selected-window) (minibuffer-window)) + (not (eq hargs:reading-p 'hmenu))) . + ((exit-minibuffer) . (smart-completion-help))) + ;; + ;; If reading a Hyperbole menu item or a Hyperbole completion-based + ;; argument, allow selection of an item at point. + ((if (> (minibuffer-depth) 0) (setq hkey-value (hargs:at-p))) . + ((hargs:select-p hkey-value) . + (hargs:select-p hkey-value 'assist))) + ;; + ((if (not (eobp)) + (or (eolp) (if selective-display + (= (following-char) ?\^M)))) . + ((smart-scroll-up) . (smart-scroll-down))) + ;; + ((eq major-mode 'smart-menu-mode) . + ((smart-menu-select) . (smart-menu-help))) + ;; + ;; If on a Hyperbole button, perform action or give help. + ((if (fboundp 'hbut:at-p) (or (hbut:at-p) (hbut:label-p))) . + ((hui:hbut-act 'hbut:current) . (hui:hbut-help 'hbut:current))) + ;; + ;; The Smart Menu system provides menus within Emacs running on a dumb + ;; terminal. It is part of InfoDock and is not available separately. + ((and (fboundp 'smart-menu-choose-menu) + (setq hkey-value (and hkey-always-display-menu + (smart-menu-choose-menu))) + (not (and (get-buffer-window *smart-menu-buffer*) + (eq hkey-value *smart-menu-curr*)))) . + ((smart-menu hkey-value) . + (smart-menu hkey-value))) + ;; + ;; + ;; View minor mode + ((if (boundp 'view-minor-mode) view-minor-mode) . + ((cond ((last-line-p) + (view-quit)) + ((pos-visible-in-window-p (point-max)) + (goto-char (point-max))) + (t (scroll-up))) . + (scroll-down))) + ;; + ;; View major mode + ((eq major-mode 'view-mode) . + ((View-scroll-lines-forward) . (View-scroll-lines-backward))) + ;; + ((eq major-mode 'kotl-mode) . + ((kotl-mode:action-key) . (kotl-mode:help-key))) + ;; + ;; Support direct selection and viewing on in-memory relational databases. + ;; Rdb-mode has not been publicly released. + ;; It is not included with Hyperbole. + ((eq major-mode 'rdb-mode) . ((smart-rdb) . (smart-rdb-assist))) + ;; + ;; Restore window config and hide help buffer when click at buffer end. + ((if (= (point) (point-max)) (string-match "Help\\*$" (buffer-name))) . + ((hkey-help-hide) . (hkey-help-hide))) + ;; + ;; Support the OO-Browser, a part of InfoDock, XEmacs, and soon to be a + ;; part of Emacs. + ((or (br-in-browser) (eq major-mode 'br-mode)) . + ((smart-br-dispatch) . (smart-br-assist-dispatch))) + ;; + ((and (memq major-mode '(c-mode c++-c-mode)) + buffer-file-name (setq hkey-value (smart-c-at-tag-p))) . + ((smart-c) . (smart-c nil 'next-tag))) + ;; + ((and (eq major-mode 'asm-mode) + buffer-file-name (setq hkey-value (smart-asm-at-tag-p))) . + ((smart-asm) . (smart-asm nil 'next-tag))) + ;; + ((if (smart-lisp-mode-p) (smart-lisp-at-tag-p)) . + ((smart-lisp) . (smart-lisp 'next-tag))) + ;; + ((and (eq major-mode 'c++-mode) buffer-file-name + ;; Don't use smart-c++-at-tag-p here since it will prevent #include + ;; lines from matching. + (setq hkey-value (smart-c-at-tag-p))) . + ( ;; Only fboundp if OO-Browser has been loaded. + (if (fboundp 'c++-to-definition) + (smart-c++-oobr) (smart-c++)) . + (if (fboundp 'c++-to-definition) + (smart-c++-oobr) + (smart-c++ nil 'next-tag)))) + ;; + ((and (eq major-mode 'objc-mode) buffer-file-name + (setq hkey-value (smart-objc-at-tag-p))) . + ( ;; Only fboundp if OO-Browser has been loaded. + (if (fboundp 'objc-to-definition) + (smart-objc-oobr) (smart-objc)) . + (if (fboundp 'objc-to-definition) + (smart-objc-oobr) + (smart-objc nil 'next-tag)))) + ;; + ((and (eq major-mode 'fortran-mode) + buffer-file-name (setq hkey-value (smart-fortran-at-tag-p))) . + ((smart-fortran) . (smart-fortran nil 'next-tag))) + ;; + ((eq major-mode 'occur-mode) . + ((occur-mode-goto-occurrence) . (occur-mode-goto-occurrence))) + ;; + ((eq major-mode 'moccur-mode) . + ((moccur-mode-goto-occurrence) . (moccur-mode-goto-occurrence))) + ;; + ((eq major-mode 'calendar-mode) . + ((smart-calendar) . (smart-calendar-assist))) + ;; + ((eq major-mode 'unix-apropos-mode) . + ((smart-apropos) . (smart-apropos-assist))) + ;; + ((eq major-mode 'outline-mode) . + ((smart-outline) . (smart-outline-assist))) + ;; + ((eq major-mode 'Info-mode) . + ((smart-info) . (smart-info-assist))) + ;; + ((if (boundp 'hmail:reader) + (or (eq major-mode hmail:reader) + (eq major-mode hmail:lister))) . + ((smart-hmail) . (smart-hmail-assist))) + ;; + ((eq major-mode 'gnus-group-mode) + (smart-gnus-group) . (smart-gnus-group-assist)) + ;; + ((eq major-mode 'gnus-summary-mode) + (smart-gnus-summary) . (smart-gnus-summary-assist)) + ;; + ((eq major-mode 'gnus-article-mode) + (smart-gnus-article) . (smart-gnus-article-assist)) + ;; + ((eq major-mode 'Buffer-menu-mode) . + ((smart-buffer-menu) . (smart-buffer-menu-assist))) + ;; + ((eq major-mode 'dired-mode) . + ((smart-dired) . (smart-dired-assist))) + ;; + ((eq major-mode 'tar-mode) . + ((smart-tar) . (smart-tar-assist))) + ;; + ;; Follow references in man pages. + ((setq hkey-value (smart-man-entry-ref)) . + ((smart-man-display hkey-value) . + (smart-man-display hkey-value))) + ;; + ((eq major-mode 'w3-mode) . + ((w3-follow-link) . (w3-goto-last-buffer))) + ;; + ((if (boundp 'rolo-display-buffer) + (equal (buffer-name) rolo-display-buffer)) . + ((smart-wrolo) . (smart-wrolo-assist))) + ;; + ;; Gomoku game + ((eq major-mode 'gomoku-mode) . + ((gomoku-human-plays) . (gomoku-human-takes-back))) + ;; + ;; Outline minor mode is on and usable. + (selective-display . + ((smart-outline) . (smart-outline-assist))) + ) + "Alist of predicates and form-conses for Action and Assist Keys. +When the Action or Assist Key is pressed, the first or second form, +respectively, associated with the first non-nil predicate is evaluated.") + +;;; ************************************************************************ +;;; driver code +;;; ************************************************************************ + +;; The following autoload is needed if another subsystem besides +;; Hyperbole uses this mouse handling code. +(autoload 'var:append "hvar" "Append to a list variable." nil) + +(require 'hargs) +(require 'hmouse-key) +(if hyperb:window-system + (progn + (defvar hmouse-alist hkey-alist + "Alist of predicates and form-conses for context-sensitive smart key mouse actions. +When the action-key or the assist-key is pressed, the first or +second form, respectively, associated with the first non-nil predicate is +evaluated.") + (load "hui-window"))) + +;;; ************************************************************************ +;;; support code +;;; ************************************************************************ + +;; The 'load' line below loads any local Smart Key function definitions. +;; The public distribution contains none. You may leave it commented out if +;; you prefer. +;; (load "smart-local" t) + +;;; ************************************************************************ +;;; Required Init functions +;;; ************************************************************************ + +(defun first-line-p () + "Returns true if point is on the first line of the buffer." + (save-excursion (beginning-of-line) (bobp))) + +(defun last-line-p () + "Returns true if point is on the last line of the buffer." + (save-excursion (end-of-line) (eobp))) + +(defun smart-completion-help () + "Offer completion help for current minibuffer argument, if any." + (if (where-is-internal 'minibuffer-completion-help (current-local-map)) + (minibuffer-completion-help))) + +(defun smart-symlink-expand (path) + "Returns referent for possible symbolic link, PATH." + (if (not (fboundp 'symlink-referent)) + path + (let ((start 0) (len (length path)) (ref) (part)) + (while (and (< start len) (setq part (string-match "/[^/]*" path start))) + (setq part (concat ref + (substring path start (setq start (match-end 0)))) + ref (symlink-referent part))) + ref))) + +;;; ************************************************************************ +;;; smart-buffer-menu functions +;;; ************************************************************************ + +(defun smart-buffer-menu (&optional in-browser) + "Uses a single key or mouse key to manipulate buffer-menu entries. + +Invoked via a key press when in Buffer-menu-mode. It assumes that its +caller has already checked that the key was pressed in an appropriate buffer +and has moved the cursor there. + +Optional non-nil IN-BROWSER indicates use within the OO-Browser. + +If key is pressed: + (1) on the first column of an entry, the selected buffer is marked for + display; + (2) on the second column of an entry, the selected buffer is marked to be + saved; + (3) anywhere else within an entry line, all saves and deletes are done, and + selected buffers are displayed, including the one just clicked on (if + IN-BROWSER, only the selected buffer is displayed); + (4) on or after the last line in the buffer, all saves and deletes are done." + + (interactive) + (cond ((last-line-p) (Buffer-menu-execute)) + ((bolp) (Buffer-menu-mark)) + ((save-excursion + (goto-char (1- (point))) + (bolp)) + (Buffer-menu-save)) + (in-browser (br-buffer-menu-select)) + (t (Buffer-menu-select)))) + +(defun smart-buffer-menu-assist () + "Uses a single assist-key or mouse assist-key to manipulate buffer-menu entries. + +Invoked via an assist-key press when in Buffer-menu-mode. It assumes that its +caller has already checked that the assist-key was pressed in an appropriate +buffer and has moved the cursor there. + +If assist-key is pressed: + (1) on the first or second column of an entry, the selected buffer is unmarked + for display and for saving or deletion; + (2) anywhere else within an entry line, the selected buffer is marked for + deletion; + (3) on or after the last line in the buffer, all display, save, and delete + marks on all entries are undone." + + (interactive) + (cond ((last-line-p) (progn (list-buffers) (forward-line 3))) + ((bolp) (Buffer-menu-unmark)) + ((save-excursion + (goto-char (1- (point))) + (bolp)) + (Buffer-menu-unmark)) + (t (Buffer-menu-delete)))) + +;;; ************************************************************************ +;;; smart-calendar functions +;;; ************************************************************************ + +(defun smart-calendar () + "Uses a single key or mouse key to manipulate the scrolling calendar. + +Invoked via a key press when in calendar-mode. It assumes that its +caller has already checked that the key was pressed in an appropriate buffer +and has moved the cursor there. + +If key is pressed: + (1) at the end of the buffer, the calendar is scrolled forward 3 months; + (2) to the left of any dates on a calendar line, the calendar is scrolled + backward 3 months; + (3) on a date, the diary entries for the date, if any, are displayed." + + (interactive) + (cond ((eobp) (calendar-cursor-to-nearest-date) + (scroll-calendar-left-three-months 1)) + ((< (current-column) 5) (calendar-cursor-to-nearest-date) + (scroll-calendar-right-three-months 1)) + (t (calendar-cursor-to-nearest-date) + (view-diary-entries 1)))) + +(defun smart-calendar-assist () + "Uses a single assist-key or mouse assist-key to manipulate the scrolling calendar. + +Invoked via an assist-key press when in calendar-mode. It assumes that its +caller has already checked that the assist-key was pressed in an appropriate +buffer and has moved the cursor there. + +If assist-key is pressed: + (1) at the end of the buffer, the calendar is scrolled backward 3 months; + (2) to the left of any dates on a calendar line, the calendar is scrolled + forward 3 months; + (3) anywhere else, all dates with marking diary entries are marked in the + calendar window." + + (interactive) + (cond ((eobp) (calendar-cursor-to-nearest-date) + (scroll-calendar-right-three-months 1)) + ((< (current-column) 5) (calendar-cursor-to-nearest-date) + (scroll-calendar-left-three-months 1)) + (t (mark-diary-entries)))) + + +;;; ************************************************************************ +;;; smart-dired functions +;;; ************************************************************************ + +(defun smart-dired () + "Uses a single key or mouse key to manipulate directory entries. + +Invoked via a key press when in dired-mode. It assumes that its +caller has already checked that the key was pressed in an appropriate buffer +and has moved the cursor there. + +If key is pressed: + (1) within an entry line, the selected file/directory is displayed for + editing in the other window; + (2) on or after the last line in the buffer, if any deletes are to be + performed, they are executed after user verification, otherwise, this + dired invocation is quit." + + (interactive) + (cond ((last-line-p) + (let (flagged) + (save-excursion + (goto-char 1) + (setq flagged (re-search-forward "^D" nil t))) + (if flagged + (cond ((fboundp 'dired-do-deletions) + (dired-do-deletions)) + ;; For Tree-dired compatibility + ((fboundp 'dired-do-flagged-delete) + (dired-do-flagged-delete)) + (t (error "(smart-dired): No Dired expunge function."))) + (dired-quit)))) + (t (hpath:find-other-window (dired-get-filename))))) + +(defun smart-dired-assist () + "Uses a single assist-key or mouse assist-key to manipulate directory entries. + +Invoked via an assist-key press when in dired-mode. It assumes that its +caller has already checked that the assist-key was pressed in an appropriate +buffer and has moved the cursor there. + +If assist-key is pressed: + (1) on a '~' character, all backup files in the directory are marked for + deletion; + (2) on a '#' character, all auto-save files in the directory are marked for + deletion; + (3) anywhere else within an entry line, the current entry is marked for + deletion; + (4) on or after the last line in the buffer, all delete marks on all entries + are undone." + + (interactive) + (cond ((last-line-p) + (dired-unflag (- (count-lines (point-min) (point-max)))) + (goto-char (point-max))) + ((looking-at "~") (dired-flag-backup-files)) + ((looking-at "#") (dired-flag-auto-save-files)) + (t (dired-flag-file-deleted 1)))) + +;;; ************************************************************************ +;;; smart-gnus functions +;;; ************************************************************************ + +(defun smart-gnus-group () + "Uses a key or mouse key to move through Gnus Newsgroup listings. +Invoked via a key press when in gnus-group-mode. It assumes that its caller +has already checked that the key was pressed in an appropriate buffer and has +moved the cursor to the selected buffer. + +If key is pressed within: + (1) a GNUS-GROUP line, that newsgroup is read; + (2) to the left of any GNUS-GROUP line, on any of the whitespace, the current + group is unsubscribed or resubscribed; + (3) at the end of the GNUS-GROUP buffer, after all lines, checks for new + news." + + (interactive) + (cond ((last-line-p) (gnus-group-get-new-news)) + ((progn (skip-chars-backward " U") (bolp)) + (gnus-group-unsubscribe-current-group)) + (t (gnus-group-read-group nil)))) + +(defun smart-gnus-group-assist () + "Uses an assist-key or assist-mouse key to move through Gnus Newsgroup listings. +Invoked via an assist-key press when in gnus-group-mode. It assumes that its +caller has already checked that the key was pressed in an appropriate buffer +and has moved the cursor to the selected buffer. + +If key is pressed within: + (1) a GNUS-GROUP line, that newsgroup is read; + (2) to the left of any GNUS-GROUP line, on any of the whitespace, the user is + prompted for a group name to subscribe or unsubscribe to; + (3) at the end of the GNUS-GROUP buffer, after all lines, quits from the + newsreader." + + (interactive) + (cond ((last-line-p) (gnus-group-exit)) + ((progn (skip-chars-backward " U") (bolp)) + (call-interactively 'gnus-group-unsubscribe-group)) + (t (gnus-group-read-group nil)))) + +(defun smart-gnus-summary () + "Uses a key or mouse key to move through Gnus News article listings. +Invoked via a key press when in gnus-summary-mode. It assumes that its caller +has already checked that the key was pressed in an appropriate buffer and has +moved the cursor to the selected buffer. + +If key is pressed within: + (1) to the left of an article number, that article is marked as unread; + (2) a GNUS-SUMMARY line, that article is read, marked deleted, and scrolled + forward; + (3) at the end of the GNUS-SUMMARY buffer, the next undeleted article + is read or the next group is entered." + + (interactive) + (cond ((last-line-p) + (if gnus-current-article + (progn (goto-char (point-min)) + (re-search-forward + (format "^.[ ]+%d:" gnus-current-article) nil t) + (setq this-command 'gnus-summary-next-page) + (call-interactively 'gnus-summary-next-page)) + (goto-char (point-min)) + (setq this-command 'gnus-summary-first-unread-article) + (call-interactively 'gnus-summary-first-unread-article))) + ((save-excursion (skip-chars-backward " D") (bolp)) + (gnus-summary-mark-as-unread-forward 1)) + (t (setq this-command 'gnus-summary-next-page) + (call-interactively 'gnus-summary-next-page)))) + +(defun smart-gnus-summary-assist () + "Uses an assist-key or assist-mouse key to move through Gnus News articles. +Invoked via an assist-key press when in gnus-summary-mode. It assumes that its +caller has already checked that the key was pressed in an appropriate buffer +and has moved the cursor to the selected buffer. + +If key is pressed within: + (1) to the left of an article number, that article is marked as unread; + (2) a GNUS-SUMMARY line, that article is read and scrolled backward; + (3) at the end of the GNUS-SUMMARY buffer, the summary is exited, the user + is returned to group mode." + + (interactive) + (cond ((last-line-p) + (setq this-command 'gnus-summary-prev-page) + (call-interactively 'gnus-summary-exit)) + ((save-excursion (skip-chars-backward " D") (bolp)) + (gnus-summary-mark-as-unread-backward 1)) + (t (setq this-command 'gnus-summary-prev-page) + (call-interactively 'gnus-summary-prev-page)))) + +(defun smart-gnus-article () + "Uses a key or mouse key to move through Gnus netnews articles. + +Invoked via a key press when in gnus-article-mode. +It assumes that its caller has already checked that the key was pressed in an +appropriate buffer and has moved the cursor to the selected buffer. + +If key is pressed within: + (1) the first line or end of an article, the next unread message is displayed; + (2) the first line of an Info cross reference, the reference is followed; + (3) anywhere else, the window is scrolled up a windowful." + (interactive) + (cond ((or (last-line-p) (and (not (eolp)) (first-line-p))) + (unwind-protect + (progn (set-buffer gnus-summary-buffer) + (setq this-command 'gnus-summary-next-unread-article) + (gnus-summary-next-unread-article) + (gnus-summary-goto-subject gnus-current-article) + ) + (let ((artic (get-buffer-window gnus-article-buffer))) + (if artic (select-window artic))))) + ((and (not (eolp)) (Info-handle-in-note))) + (t (smart-scroll-up)))) + +(defun smart-gnus-article-assist () + "Uses an assist-key or mouse assist-key to move through Gnus netnews articles. + +Invoked via an assist-key press when in gnus-article-mode. +It assumes that its caller has already checked that the assist-key was pressed in +an appropriate buffer and has moved the cursor to the selected buffer. + +If assist-key is pressed within: + (1) the first line or end of an article, the previous message is displayed; + (2) the first line of an Info cross reference, the reference is followed; + (3) anywhere else, the window is scrolled down a windowful." + (interactive) + (cond ((or (last-line-p) (and (not (eolp)) (first-line-p))) + (unwind-protect + (progn (set-buffer gnus-summary-buffer) + (setq this-command 'gnus-summary-prev-article) + (gnus-summary-prev-article nil) + (gnus-summary-goto-subject gnus-current-article) + ) + (let ((artic (get-buffer-window gnus-summary-buffer))) + (if artic (select-window artic))))) + ((and (not (eolp)) (Info-handle-in-note))) + (t (smart-scroll-down)))) + +;;; ************************************************************************ +;;; smart-hmail functions +;;; ************************************************************************ + +(defun smart-hmail () + "Uses a key or mouse key to move through e-mail messages and summaries. + +Invoked via a key press when in hmail:reader or hmail:lister mode. +It assumes that its caller has already checked that the key was pressed in an +appropriate buffer and has moved the cursor to the selected buffer. + +If key is pressed within: + (1) a msg buffer, within the first line or at the end of a message, + the next undeleted message is displayed; + (2) a msg buffer within the first line of an Info cross reference, the + reference is followed; + (3) anywhere else in a msg buffer, the window is scrolled up a windowful; + (4) a msg summary buffer on a header entry, the message corresponding to + the header is displayed in the msg window; + (5) a msg summary buffer, on or after the last line, the messages marked + for deletion are expunged." + + (interactive) + ;; + ;; Branch on buffer type + ;; + (cond ((eq major-mode hmail:reader) + (cond ((or (last-line-p) (and (not (eolp)) (first-line-p))) + (rmail:msg-next)) + ((and (not (eolp)) (Info-handle-in-note))) + ((smart-scroll-up)))) + ;; + ;; Assume are in msg summary buffer + ;; + ((last-line-p) (lmail:expunge)) + (t (lmail:goto)))) + +(defun smart-hmail-assist () + "Uses an assist key or mouse key to move through e-mail messages and summaries. + +Invoked via an assist key press when in hmail:reader or hmail:lister mode. +It assumes that its caller has already checked that the assist-key was pressed in +an appropriate buffer and has moved the cursor to the selected buffer. + +If assist-key is pressed within: + (1) a msg buffer, within the first line or at the end of a message, + the previous undeleted message is displayed; + (2) a msg buffer within the first line of an Info cross reference, the + reference is followed; + (3) anywhere else in a msg buffer, the window is scrolled down a windowful; + (4) a msg summary buffer on a header entry, the message corresponding to + the header is marked as deleted; + (5) a msg summary buffer, on or after the last line, all messages are + marked undeleted." + + (interactive) + ;; + ;; Branch on buffer type + ;; + (cond ((eq major-mode hmail:reader) + (cond ((or (last-line-p) (and (not (eolp)) (first-line-p))) + (rmail:msg-prev)) + ((and (not (eolp)) (Info-handle-in-note))) + ((smart-scroll-down)))) + ;; + ;; Assume are in msg summary buffer + ;; + ((last-line-p) (lmail:undelete-all)) + (t (lmail:delete)))) + + +;;; ************************************************************************ +;;; smart-info functions +;;; ************************************************************************ +;;; Autoloaded in "hyperbole.el". + +;;; ************************************************************************ +;;; smart-man functions +;;; ************************************************************************ + +;; "unix-apropos.el" is a publicly available Emacs Lisp package that +;; allows man page browsing from apropos listings. "superman.el" is a +;; newer, much more complete package that you would probably prefer at +;; this point, but there is no Smart Key apropos support for it. There +;; is smart key support within the man page buffers it produces, however. +;; + +(defun smart-apropos () + "Moves through UNIX man apropos listings by using one key or mouse key. + +Invoked via a key press when in unix-apropos-mode. It assumes that +its caller has already checked that the key was pressed in an appropriate +buffer and has moved the cursor to the selected buffer. + +If key is pressed: + (1) on a UNIX man apropos entry, the man page for that entry is displayed in + another window; + (2) on or after the last line, the buffer in the other window is scrolled up + a windowful." + + (interactive) + (if (last-line-p) + (scroll-other-window) + (unix-apropos-get-man))) + +(defun smart-apropos-assist () + "Moves through UNIX man apropos listings by using one assist-key or mouse assist-key. + +Invoked via an assist-key press when in unix-apropos-mode. It assumes that +its caller has already checked that the assist-key was pressed in an appropriate +buffer and has moved the cursor to the selected buffer. + +If assist-key is pressed: + (1) on a UNIX man apropos entry, the man page for that entry is displayed in + another window; + (2) on or after the last line, the buffer in the other window is scrolled down + a windowful." + + (interactive) + (if (last-line-p) + (scroll-other-window (- 3 (window-height))) + (unix-apropos-get-man))) + +(defun smart-man-display (lisp-form) + "Evaluates LISP-FORM returned from 'smart-man-entry-ref' to display a man page." + (eval lisp-form)) + +(defun smart-man-entry-ref () + "Returns form which displays referenced manual entry that point is on or nil. +Handles references in sections: NAME, SEE ALSO, or PACKAGES USED. Also can +display C routine definitions selected in a man page, see +'smart-man-c-routine-ref'. + +Man page buffer must either have an attached file or else a `man-path' +local variable containing its pathname." + (interactive) + (let ((ref "")) + (if (not (or (if (string-match "Manual Entry\\|\\*man " + (buffer-name (current-buffer))) + (progn (and (boundp 'man-path) man-path + (setq ref (smart-symlink-expand man-path))) + t)) + (if buffer-file-name + (string-match "/man/" (setq ref (smart-symlink-expand + buffer-file-name)))))) + (setq ref nil) + (or (setq ref (or (smart-man-file-ref) + (smart-man-c-routine-ref))) + (save-excursion + (let ((opoint (point)) + (case-fold-search)) + (and + (re-search-backward "^[.A-Z]" nil t) + (looking-at + "\\(\\.SH[ \t]+\\)?\\(SEE ALSO\\|NAME\\|PACKAGES USED\\)") + (progn (goto-char opoint) + (skip-chars-backward "-_a-zA-Z0-9?.(") + (let ((start (point))) + (skip-chars-forward "-_a-zA-Z0-9?.()") + (setq ref (buffer-substring start (point))) + ;; Leave only one char within ref parens + (if ref + (if (string-match "(\\(.\\)\\(.+\\))" ref) + (setq ref (concat (substring ref 0 (match-end 1)) + "\)")))) + ))))))) + (cond ((equal ref "") nil) + ((stringp ref) (list 'manual-entry ref)) + (t ref)))) + +(defun smart-man-c-routine-ref () + "Returns form to jump to def of C function whose name is at point, if any. +Valid sections within the man page are: ROUTINES, MACROS or FUNCTIONS. +Uses (smart-tags-file) function to determine etags file from which to +locate the definition. + +Returns etags file name if point is on an identifier in the appropriate +section and the jump is done, otherwise, returns nil." + (let ((ref) + (opoint (point)) + (case-fold-search)) + (save-excursion + (and (re-search-backward "^[.A-Z]" nil t) + (looking-at "^\\(FUNCTIONS\\|ROUTINES\\|MACROS\\)[ \t\n]") + (progn (goto-char opoint) + (skip-chars-backward "_~<>:a-zA-Z0-9(") + (if (or (looking-at "\\([_~<>:a-zA-Z0-9]+\\)[ \t\n]*(") + (looking-at "\\([_~<:A-Z][_<>:A-Z0-9]+\\)")) + (setq ref (buffer-substring + (match-beginning 1) (match-end 1)) + ))))) + (if ref + (let ((tags-file-name + (smart-tags-file (if (and (boundp 'man-path) man-path) + man-path + default-directory)))) + (and (file-exists-p tags-file-name) + (file-readable-p tags-file-name) + (list 'let (list (list 'tags-file-name tags-file-name)) + (list (if (br-in-browser) + 'find-tag 'find-tag-other-window) + ref))))))) + +(defun smart-man-file-ref () + "Returns form to eval to display file whose name point is on, within a FILES man page section. +If not on a file name, returns nil." + (let ((ref) + (opoint (point)) + (case-fold-search)) + (save-excursion + (and (re-search-backward "^[.A-Z]" nil t) + (looking-at "^FILES[ \t\n]") + (progn (goto-char opoint) + (skip-chars-backward "^ \t") + (if (looking-at "/[^ \t\n]+") + (setq ref (buffer-substring + (match-beginning 0) (match-end 0)) + ))))) + (if ref + (list (if (br-in-browser) + 'find-file 'find-file-other-window) + ref)))) + +;;; ************************************************************************ +;;; smart-outline functions +;;; ************************************************************************ + +;; The functions in this section require InfoDock's version of outline.el +;; in order to work properly. + +(defvar smart-outline-cut nil + "Non-nil means outline region was cut and is ready to be pasted at point.") + +(let ((proc + '((lambda () + (make-local-variable 'smart-outline-cut) + ;; Non-nil means outline region was cut and is available to be + ;; pasted at point. + (setq smart-outline-cut nil) + )))) + (if (boundp 'outline-mode-map) + (eval proc) + (var:append 'outline-mode-hook proc))) + +(defun smart-outline () + "Collapses, expands, and moves outline entries. +Invoked via a key press when in outline-mode. It assumes that +its caller has already checked that the key was pressed in an appropriate +buffer and has moved the cursor to the selected buffer. + +If key is pressed: + (1) after an outline heading has been cut via the Action Key, then paste the + cut heading at point; + (2) at the end of buffer, show all buffer text + (3) at the beginning of a heading line, cut the headings subtree from the + buffer; + (4) on a header line but not at the beginning or end, if headings subtree is + hidden then show it, otherwise hide it; + (5) anywhere else, scroll up a windowful." + + (interactive) + (cond (smart-outline-cut + (setq smart-outline-cut nil) (yank)) + ((eobp) (show-all)) + ((and (bolp) (looking-at outline-regexp)) + (setq smart-outline-cut t) + (kill-region + (point) + (or (outline-get-next-sibling) + ;; Skip past start of current entry + (progn (re-search-forward outline-regexp nil t) + (smart-outline-to-entry-end t (outline-level)))))) + + ((or (eolp) (zerop (save-excursion (beginning-of-line) + (outline-level)))) + (smart-scroll-up)) + ;; On an outline header line but not at the start/end of line. + ((smart-outline-subtree-hidden-p) + (show-subtree)) + (t (hide-subtree)))) + + +(defun smart-outline-assist () + "Collapses, expands, and moves outline entries. +Invoked via an assist-key press when in outline-mode. It assumes that +its caller has already checked that the assist-key was pressed in an appropriate +buffer and has moved the cursor to the selected buffer. + +If assist-key is pressed: + (1) after an outline heading has been cut via the action-key, allow multiple + pastes throughout the buffer (last paste should be done with the Action Key, + not the Assist Key); + (2) at the end of buffer, hide all bodies in buffer; + (3) at the beginning of a heading line, cut the current heading (sans + subtree) from the buffer; + (4) on a header line but not at the beginning or end, if heading body is + hidden then show it, otherwise hide it; + (5) anywhere else, scroll down a windowful." + + (interactive) + (cond (smart-outline-cut (yank)) + ((eobp) (hide-body )) + ((and (bolp) (looking-at outline-regexp)) + (setq smart-outline-cut t) + (kill-region (point) + ;; Skip past start of current entry + (progn (re-search-forward outline-regexp nil t) + (smart-outline-to-entry-end + nil (outline-level))))) + ((or (eolp) (zerop (save-excursion (beginning-of-line) + (outline-level)))) + (smart-scroll-down)) + ;; On an outline header line but not at the start/end of line. + ((smart-outline-subtree-hidden-p) + (show-entry)) + (t (hide-entry)))) + +(defun smart-outline-to-entry-end + (&optional include-sub-entries curr-entry-level) + "Goes to end of whole entry if optional INCLUDE-SUB-ENTRIES is non-nil. +CURR-ENTRY-LEVEL is an integer representing the length of the current level +string which matched to 'outline-regexp'. If INCLUDE-SUB-ENTRIES is nil, +CURR-ENTRY-LEVEL is not needed." + (let (next-entry-exists) + (while (and (setq next-entry-exists + (re-search-forward outline-regexp nil t)) + include-sub-entries + (save-excursion + (beginning-of-line) + (> (outline-level) + curr-entry-level)))) + (if next-entry-exists + (progn (beginning-of-line) (point)) + (goto-char (point-max))))) + +(defun smart-outline-subtree-hidden-p () + "Returns t if at least initial subtree of heading is hidden, else nil." + (save-excursion + (if (re-search-forward "[\n\^M]" nil t) (= (preceding-char) ?\^M)))) + +;;; ************************************************************************ +;;; smart-tar functions +;;; ************************************************************************ + +(defun smart-tar () + "Uses a single key or mouse key to manipulate tar file entries. + +Invoked via a key press when in tar-mode. It assumes that its +caller has already checked that the key was pressed in an appropriate buffer +and has moved the cursor there. + +If key is pressed: + (1) within an entry line, the selected file/directory is displayed for + editing in the other window; + (2) on or after the last line in the buffer, if any deletes are to be + performed, they are executed after user verification, otherwise, this + tar file browser is quit." + + (interactive) + (cond ((last-line-p) + (let (flagged) + (save-excursion + (goto-char 1) + (setq flagged (re-search-forward "^D" nil t))) + (if flagged + (tar-expunge) + (kill-buffer nil)))) + (t (tar-extract-other-window)))) + +(defun smart-tar-assist () + "Uses a single assist-key or mouse assist-key to manipulate tar file entries. + +Invoked via an assist-key press when in dired-mode. It assumes that its +caller has already checked that the assist-key was pressed in an appropriate +buffer and has moved the cursor there. + +If assist-key is pressed: + (1) on an entry line, the current entry is marked for deletion; + (2) on or after the last line in the buffer, all delete marks on all entries + are undone." + + (interactive) + (cond ((last-line-p) + (tar-unflag (- (count-lines (point-min) (point-max)))) + (goto-char (point-max))) + (t (tar-flag-deleted 1)))) + +;;; ************************************************************************ +;;; smart-wrolo functions +;;; ************************************************************************ + +(defun smart-wrolo () + "In wrolo match buffer, edits current entry. +Uses one key or mouse key. + +Invoked via a key press when in the 'rolo-display-buffer'. It assumes that +its caller has already checked that the key was pressed in an appropriate +buffer and has moved the cursor to the selected buffer." + (interactive) + (rolo-edit-entry)) + +(fset 'smart-wrolo-assist 'smart-wrolo) + +(provide 'hui-mouse)