Mark outgoing encrypted message.
[riece] / lisp / riece-button.el
1 ;;; riece-button.el --- display useful buttons in IRC buffers
2 ;; Copyright (C) 1998-2003 Daiki Ueno
3
4 ;; Author: Daiki Ueno <ueno@unixuser.org>
5 ;; Created: 1998-09-28
6 ;; Keywords: IRC, riece
7
8 ;; This file is part of Riece.
9
10 ;; This program is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
13 ;; any later version.
14
15 ;; This program is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 ;; GNU General Public License for more details.
19
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
22 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 ;; Boston, MA 02110-1301, USA.
24
25 ;;; Commentary:
26
27 ;; NOTE: This is an add-on module for Riece.
28
29 ;;; Code:
30
31 (require 'riece-commands)
32 (require 'riece-identity)
33 (require 'riece-misc)
34 (require 'wid-edit)
35
36 (defconst riece-channel-button-popup-menu
37   '("Channel"
38     ["Switch To Channel" riece-channel-button-switch-to-channel]
39     ["Part Channel" riece-channel-button-part]
40     ["List Channel" riece-channel-button-list])
41   "Menu for channel buttons.")
42
43 (defconst riece-user-button-popup-menu
44   '("User"
45     ["Finger (WHOIS)" riece-user-button-finger]
46     ["Start Private Conversation" riece-user-button-join-partner]
47     ["Set +o" riece-user-button-set-operators]
48     ["Set +v" riece-user-button-set-speakers])
49   "Menu for user buttons.")
50
51 (defconst riece-button-description
52   "Display useful buttons in IRC buffers.")
53
54 (defvar help-echo-owns-message)
55 (define-widget 'riece-identity-button 'push-button
56   "A channel button."
57   :action 'riece-button-switch-to-identity
58   :help-echo
59   (lambda (widget/window &optional overlay pos)
60     ;; Needed to properly clear the message due to a bug in
61     ;; wid-edit (XEmacs only).
62     (if (boundp 'help-echo-owns-message)
63         (setq help-echo-owns-message t))
64     (format "%S: switch to %s; down-mouse-3: more options"
65             (aref riece-mouse-2 0)
66             ;; XEmacs will get a single widget arg; Emacs 21 will get
67             ;; window, overlay, position.
68             (riece-format-identity
69              (if overlay
70                  (with-current-buffer (riece-overlay-buffer overlay)
71                    (widget-value (widget-at (riece-overlay-start overlay))))
72                (widget-value widget/window))))))
73
74 (defun riece-button-switch-to-identity (widget &optional event)
75   "Switch to identity stored in WIDGET.
76 This function is used as a callback for a channel button."
77   (let ((channel (widget-value widget)))
78     (if (riece-identity-member channel riece-current-channels)
79         (riece-command-switch-to-channel channel)
80       (message "%s" (substitute-command-keys
81                      "Type \\[riece-command-join] to join the channel")))))
82
83 (defun riece-identity-button-click (event)
84   "Call widget-button-click and select the last selected window."
85   (interactive "e")                     ;widget-button-click has
86                                         ;interactive spec "@e"
87   (let ((buffer (current-buffer))
88         (point (point))
89         window)
90     (unwind-protect
91         (save-excursion
92           (set-buffer (riece-event-buffer event))
93           (goto-char (riece-event-point event))
94           (widget-button-click event))
95       ;; riece-button-switch-to-identity changes window-configuration
96       ;; so we must select the last selected window by _buffer_.
97       (if (setq window (get-buffer-window buffer))
98           (progn
99             (select-window window)
100             (set-window-point window point))
101         (if riece-debug
102             (riece-debug (format "buffer %s not visible"
103                                  (buffer-name buffer))))))))
104
105 (defun riece-identity-button-popup-menu (event)
106   "Popup the menu for identity buttons."
107   (interactive "e")
108   (save-excursion
109     (set-buffer (riece-event-buffer event))
110     (goto-char (riece-event-point event))
111     (riece-popup-menu-popup
112      (if (riece-channel-p (riece-identity-prefix
113                            (get-text-property (point) 'riece-identity)))
114          riece-channel-button-popup-menu
115        riece-user-button-popup-menu)
116      event)))
117
118 (defun riece-channel-button-switch-to-channel ()
119   (interactive)
120   (riece-command-switch-to-channel
121    (get-text-property (point) 'riece-identity)))
122
123 (defun riece-channel-button-part ()
124   (interactive)
125   (riece-command-part
126    (get-text-property (point) 'riece-identity)))
127
128 (defun riece-channel-button-list ()
129   (interactive)
130   (riece-command-list
131    (riece-identity-prefix (get-text-property (point) 'riece-identity))))
132
133 (defun riece-user-button-join-partner ()
134   (interactive)
135   (riece-command-join-partner
136    (get-text-property (point) 'riece-identity)))
137
138 (defun riece-user-button-set-operators ()
139   (interactive)
140   (let (group users)
141     (if (riece-region-active-p)
142         (save-excursion
143           (riece-scan-property-region
144            'riece-identity
145            (region-beginning) (region-end)
146            (lambda (start end)
147              (setq group (cons (get-text-property start 'riece-identity)
148                                group)))))
149       (setq group (list (get-text-property (point) 'riece-identity))))
150     (setq users (riece-with-server-buffer
151                     (riece-identity-server riece-current-channel)
152                   (riece-channel-get-users (riece-identity-prefix
153                                             riece-current-channel))))
154     (if (setq group
155               (delq nil
156                     (mapcar
157                      (lambda (identity)
158                        (unless (memq ?o (cdr (riece-identity-assoc
159                                               (riece-identity-prefix identity)
160                                               users
161                                               t)))
162                          identity))
163                      group)))
164         (riece-command-set-operators (mapcar #'riece-identity-prefix group)))))
165
166 (defun riece-user-button-set-speakers ()
167   (interactive)
168   (let (group users)
169     (if (riece-region-active-p)
170         (save-excursion
171           (riece-scan-property-region
172            'riece-identity
173            (region-beginning) (region-end)
174            (lambda (start end)
175              (setq group (cons (get-text-property start 'riece-identity)
176                                group)))))
177       (setq group (list (get-text-property (point) 'riece-identity))))
178     (setq users (riece-with-server-buffer
179                     (riece-identity-server riece-current-channel)
180                   (riece-channel-get-users (riece-identity-prefix
181                                             riece-current-channel))))
182     (if (setq group
183               (delq nil
184                     (mapcar
185                      (lambda (identity)
186                        (unless (memq ?v (cdr (riece-identity-assoc
187                                               (riece-identity-prefix identity)
188                                               users
189                                               t)))
190                          identity))
191                      group)))
192         (riece-command-set-speakers (mapcar #'riece-identity-prefix group)))))
193
194 (defun riece-user-button-finger ()
195   (interactive)
196   (riece-command-finger (get-text-property (point) 'riece-identity)))
197
198 (defun riece-make-identity-button-map ()
199   (let ((map (make-sparse-keymap)))
200     (set-keymap-parent map (current-local-map))
201     (define-key map [down-mouse-2] 'riece-identity-button-click)
202     (define-key map [down-mouse-3] 'riece-identity-button-popup-menu)
203     map))
204
205 (defvar riece-identity-button-map)
206 (defun riece-button-add-identity-button (start end)
207   (if (get 'riece-button 'riece-addon-enabled)
208       (riece-scan-property-region
209        'riece-identity
210        start end
211        (lambda (start end)
212          (let ((inhibit-read-only t)
213                buffer-read-only)
214            (widget-convert-button 'riece-identity-button start end
215                                   (get-text-property start 'riece-identity))
216            (add-text-properties
217             start end
218             (list 'local-map riece-identity-button-map
219                   'keymap riece-identity-button-map)))))))
220
221 (defun riece-button-update-buffer ()
222   (riece-button-add-identity-button (point-min) (point-max)))
223
224 (defvar riece-channel-list-mode-map)
225 (defvar riece-user-list-mode-map)
226 (defvar riece-dialogue-mode-map)
227
228 (defun riece-button-channel-list-mode-hook ()
229   (set-keymap-parent riece-channel-list-mode-map widget-keymap)
230   (set (make-local-variable 'riece-identity-button-map)
231        (riece-make-identity-button-map))
232   (add-hook 'riece-update-buffer-functions
233             'riece-button-update-buffer t t))
234
235 (defun riece-button-user-list-mode-hook ()
236   (set-keymap-parent riece-user-list-mode-map widget-keymap)
237   (set (make-local-variable 'riece-identity-button-map)
238        (riece-make-identity-button-map))
239   (add-hook 'riece-update-buffer-functions
240             'riece-button-update-buffer t t))
241
242 (defun riece-button-dialogue-mode-hook ()
243   (set-keymap-parent riece-dialogue-mode-map widget-keymap)
244   (set (make-local-variable 'riece-identity-button-map)
245        (riece-make-identity-button-map)))
246
247 (defun riece-button-insinuate ()
248   (save-excursion
249     (when riece-channel-list-buffer
250       (set-buffer riece-channel-list-buffer)
251       (riece-button-channel-list-mode-hook))
252     (when riece-user-list-buffer
253       (set-buffer riece-user-list-buffer)
254       (riece-button-user-list-mode-hook))
255     (let ((buffers riece-buffer-list))
256       (while buffers
257         (set-buffer (car buffers))
258         (if (eq (derived-mode-class major-mode)
259                 'riece-dialogue-mode)
260             (riece-button-dialogue-mode-hook))
261         (setq buffers (cdr buffers)))))
262   (add-hook 'riece-channel-list-mode-hook
263             'riece-button-channel-list-mode-hook)
264   (add-hook 'riece-user-list-mode-hook
265             'riece-button-user-list-mode-hook)
266   (add-hook 'riece-dialogue-mode-hook
267             'riece-button-dialogue-mode-hook)
268   (add-hook 'riece-after-insert-functions 'riece-button-add-identity-button))
269
270 (defun riece-button-uninstall ()
271   (let ((buffers riece-buffer-list))
272     (save-excursion
273       (while buffers
274         (set-buffer (car buffers))
275         (remove-hook 'riece-update-buffer-functions
276                      'riece-button-update-buffer t)
277         (if (local-variable-p 'riece-identity-button-map
278                               (car buffers))
279             (kill-local-variable 'riece-identity-button-map))
280         (setq buffers (cdr buffers)))))
281   (remove-hook 'riece-channel-list-mode-hook
282                'riece-button-channel-list-mode-hook)
283   (remove-hook 'riece-user-list-mode-hook
284                'riece-button-user-list-mode-hook)
285   (remove-hook 'riece-dialogue-mode-hook
286                'riece-button-dialogue-mode-hook)
287   (remove-hook 'riece-after-insert-functions
288                'riece-button-add-identity-button))
289
290 (defun riece-button-enable ()
291   (let ((pointer riece-buffer-list))
292     (while pointer
293       (with-current-buffer (car pointer)
294         (if (eq (derived-mode-class major-mode)
295                 'riece-dialogue-mode)
296             (riece-button-update-buffer)))
297       (setq pointer (cdr pointer)))
298     (if riece-current-channel
299         (riece-emit-signal 'user-list-changed riece-current-channel))
300     (riece-emit-signal 'channel-list-changed)))
301
302 (defun riece-button-disable ()
303   (save-excursion
304     (let ((pointer riece-buffer-list))
305       (while pointer
306         ;; On XEmacs, BUFFER arg of widget-map-buttons is ignored.
307         (set-buffer (car pointer))
308         (widget-map-buttons
309          (lambda (widget maparg)
310            (widget-leave-text widget)))
311         (setq pointer (cdr pointer))))))
312
313 (provide 'riece-button)
314
315 ;;; riece-button.el ends here