;; emchat-xwem.el --- Activity indicator for XWEM tray ;; Copyright (C) 2005 - 2011 Steve Youngs ;; Author: Steve Youngs ;; Maintainer: Steve Youngs ;; Created: <2005-10-15> ;; Homepage: http://www.emchat.org/ ;; Keywords: emchat, icq, xwem, dock, tray ;; This file is part of EMchat. ;; Redistribution and use in source and binary forms, with or without ;; modification, are permitted provided that the following conditions ;; are met: ;; ;; 1. Redistributions of source code must retain the above copyright ;; notice, this list of conditions and the following disclaimer. ;; ;; 2. Redistributions in binary form must reproduce the above copyright ;; notice, this list of conditions and the following disclaimer in the ;; documentation and/or other materials provided with the distribution. ;; ;; 3. Neither the name of the author nor the names of any contributors ;; may be used to endorse or promote products derived from this ;; software without specific prior written permission. ;; ;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR ;; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ;; DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ;; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE ;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN ;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ;;; Commentary: ;; ;; Puts a spiffy activity indicator into the XWEM systray. ;; To use this, add... ;; ;; (require 'emchat-xwem) ;; (add-hook 'xwem-after-init-hook 'emchat-xwem-init) ;; ;; ...to your ~/.xwem/xwemrc.el ;; ;;; Todo: ;; ;; o Add more XWEM things... can't think of any right now. ;; ;;; Code: (require 'font) ;; for font-x-registry-and-encoding-regexp (eval-when-compile (autoload 'xwem-dpy "xwem-struct" nil nil 'macro) (autoload 'xwem-message "xwem-misc") (autoload 'xwem-misc-find-cl-by-emacs-frame "xwem-misc") (autoload 'xwem-osd-clear "xwem-osd") (autoload 'xwem-osd-create "xwem-osd") (autoload 'xwem-osd-create-dock "xwem-osd") (autoload 'xwem-osd-destroy "xwem-osd") (autoload 'xwem-osd-destroy-instances "xwem-osd") (autoload 'xwem-osd-get-prop "xwem-osd") (autoload 'xwem-osd-hide "xwem-osd") (autoload 'xwem-osd-icon-data-add "xwem-osd") (autoload 'xwem-osd-p "xwem-osd") (autoload 'xwem-osd-put-prop "xwem-osd") (autoload 'xwem-osd-rem-prop "xwem-osd") (autoload 'xwem-osd-set-color "xwem-osd") (autoload 'xwem-osd-set-font "xwem-osd") (autoload 'xwem-osd-show "xwem-osd") (autoload 'xwem-osd-text "xwem-osd") (autoload 'xwem-osd-text-add "xwem-osd") (autoload 'xwem-popup-menu "xwem-mouse") (autoload 'xwem-select-client "xwem-clients") (defvar xwem-current-cl) ) (defgroup emchat-xwem nil "Group to customize emchat's xwem capabilities." :group 'emchat :prefix "emchat-xwem-") (defcustom emchat-xwem-osd-enable t "*Non-nil to show incoming messages in OSD." :group 'emchat-xwem :type 'boolean) (defcustom emchat-xwem-dock-enable t "*Non-nil to start emchat dock in system tray." :group 'emchat-xwem :type 'boolean) (defcustom emchat-xwem-osd-show-icon t "*Non-nil to show ICQ icon in OSD as well as message." :group 'emchat-xwem :type 'boolean) (defcustom emchat-xwem-osd-font (font-create-name (make-font :weight "bold" :size 32)) "Font to be used to display OSD message." :group 'emchat-xwem :type '(restricted-sexp :match-alternatives (nil try-font-name))) (defcustom emchat-xwem-osd-color "magenta3" "*Default color for OSD messages." :group 'emchat-xwem :type 'color) (defcustom emchat-xwem-osd-group-colors '((:girls . "deeppink") (:vip . "gold") (:work . "red3") (:friends . "green3")) "*Alist of colors to be used in OSD for emchat groups. Each element is cons in form (GROUP . COLOR)." :group 'emchat-xwem :type '(repeat (cons (keyword :tag "group") color))) (defcustom emchat-xwem-osd-coordinates '(100 . 700) "*Place on screen for OSD messages." :group 'emchat-xwem :type '(cons (number :tag "X") (number :tag "Y"))) (defcustom emchat-xwem-osd-display-time 3 "*Time the OSD to be shown." :group 'emchat-xwem :type 'number) ;;; Internal variables (defvar emchat-xwem-osd-icon (concat "/* XPM */\n" "static char *icq[] = {\n" "/* columns rows colors chars-per-pixel */\n" "\"50 50 8 1\",\n" "\" c #09090C\",\n" "\". c #385930\",\n" "\"X c #43FD32\",\n" "\"o c #33C326\",\n" "\"O c #ECE345\",\n" "\"+ c #C5C6C7\",\n" "\"@ c None\",\n" "\"# c #DC3129\",\n" "/* pixels */\n" "\"@@@@@@@@@@@@@@@@@@@@@@@@@@@@++.+.++@@@@@@@@@@@@@@@\",\n" "\"@@@@@@@@@@@@@@++++++@@@@@@++. .+@@@@@@@@@@@@@\",\n" "\"@@@@@@@@@@@@@+ .+@@@@+. +@@@@@@@@@@@@\",\n" "\"@@@@@@@@@@@@+ .+@@++ .... .+@@@@@@@@@@@\",\n" "\"@@@@@@@@@@@+ .. +@. oXXXXXo. +@@@@@@@@@@\",\n" "\"@@@@@@@@@@@+ oXXo .+ oXXXXXXXo +@@@@@@@@@@\",\n" "\"@@@@@@@@@@@+ .XXXXo XXXXXXXXXo .+@@@@@@@@@\",\n" "\"@@@@@@@@@@@. oXXXXX. oXXXXXXXXXo .+@@@@@@@@@\",\n" "\"@@@@@@@@@@@. oXXXXXX ooXXXXXXXXX +@@@@@@@@@\",\n" "\"@@@@@@@@@@@+ oXXXXXX. oXXXXXXXXXo .+@@@@@@@@@\",\n" "\"@@@@@@@@@@@+ XXXXXXo .XXXXXXXXX. .@@@@@@@@@@\",\n" "\"@@@@@@@@@@@+ .XXXXoo oXXXXXXXXX ++++++@@@@@\",\n" "\"@@@@@@++...++ oXXXXo .XXXXXXXX .. ..++@@@\",\n" "\"@@@+++ . oXXXo .XXXXXXX. . .+@@\",\n" "\"@@+. oXXX XXXXXX. .+@\",\n" "\"@++ ..... oXX. oXXXXo .ooXo. +@\",\n" "\"@+ XXXXXXo .XXo oXXXo XXXXXXXo .+\",\n" "\"+. .XXXXXXXXo .oo oXXX .XXXXXXXXo .+\",\n" "\"+ XXXXXXXXXXX. . .XX oXXXXXXXXXo .+\",\n" "\"+ .XXXXXXXXXXXXo .. oXXXXXXXXXo +@\",\n" "\". .XXXXXXXXXXXXXX. .oXXXXXXXXXo .+@\",\n" "\". .XXXXXXXXXXXXXX .OOO. .oXXXXXoooo +@@\",\n" "\"+ oXXXXXXXXXXXoo OOOOOOO .oo.. .+@@@\",\n" "\"+. ooXooooo... .OOOOOOO. .+@@@@\",\n" "\"@+. OOOOOOOOO .+@@@\",\n" "\"@@+. OOOOOOOOO +@@\",\n" "\"@@@++. OOOOOOOO. ..ooooo. +@\",\n" "\"@@@@@+ # ### .OOOOOOO. .oXXXXXXXXXXXo. .+\",\n" "\"@@@@+. ######## .OOOOO. oXXXXXXXXXXXXXo +\",\n" "\"@@@+. ######### .OOO. .XXXXXXXXXXXXXX. +\",\n" "\"@@@+ ######### .oXXXoXXXXXXXXo .\",\n" "\"@@@+ ######### . . .oXXXXXXXXXXXo .\",\n" "\"@@@+ ######## XXo ooXo oXXXXXXXXXXo .\",\n" "\"@@@. ###### oXXX oXXX. oXXXXXXXXX. .\",\n" "\"@@@+ oXXXX .XXXX. .XXXXXXXo +\",\n" "\"@@@@+. oXXXXX. oXXXX .ooXXXo ++\",\n" "\"@@@@@++. . ooXXXXX. oXXXXX. .. +@\",\n" "\"@@@@@@@+++++ .XXXXXXX. oXXXXXo .+@@\",\n" "\"@@@@@@@@@@@. XXXXXXXXo .XXXXXo ... ++@@@\",\n" "\"@@@@@@@@@@+ oXXXXXXXX. .XXXXXX. +@++++++@@@@@\",\n" "\"@@@@@@@@@@+ .XXXXXXXXXo XXXXXX. .@@@@@@@@@@@@\",\n" "\"@@@@@@@@@@. .XXXXXXXXXo .XXXXX +@@@@@@@@@@@@\",\n" "\"@@@@@@@@@@. .XXXXXXXXXo .XXXo +@@@@@@@@@@@@\",\n" "\"@@@@@@@@@@+ .XXXXXXXXX. .oo. .+@@@@@@@@@@@@\",\n" "\"@@@@@@@@@@+ XXXXXXXXX +. +@@@@@@@@@@@@@\",\n" "\"@@@@@@@@@@+. .oXXXXXo. .@+.. ..@@@@@@@@@@@@@@\",\n" "\"@@@@@@@@@@@+ ooXo. +@@@++..++@@@@@@@@@@@@@@@\",\n" "\"@@@@@@@@@@@++ +@@@@@@@@@@@@@@@@@@@@@@@@@\",\n" "\"@@@@@@@@@@@@@+. .+@@@@@@@@@@@@@@@@@@@@@@@@@@\",\n" "\"@@@@@@@@@@@@@@++.....++@@@@@@@@@@@@@@@@@@@@@@@@@@@\"\n" "};\n")) (defvar emchat-xwem-active (concat "/* XPM */\n" "static char *noname[] = {\n" "/* columns rows colors chars-per-pixel */\n" "\"16 16 17 1\",\n" "\" c #000100\",\n" "\". c #013200\",\n" "\"X c #31000b\",\n" "\"o c #2c2c00\",\n" "\"O c #035500\",\n" "\"+ c #037700\",\n" "\"@ c #4d0011\",\n" "\"# c #736f00\",\n" "\"$ c #068600\",\n" "\"% c #07ab00\",\n" "\"& c #09cb00\",\n" "\"* c #08ed00\",\n" "\"= c #a00024\",\n" "\"- c #d1002f\",\n" "\"; c #878200\",\n" "\": c #fff82a\",\n" "\"> c None\",\n" "/* pixels */\n" "\">>>> > >>>>\",\n" "\">>> + %&. >>>\",\n" "\">>> +*$ $**% >>>\",\n" "\">>> *& +**$ >\",\n" "\"> O* +*% . \",\n" "\" O**O O..& .**$ \",\n" "\" &***$ oo O**% \",\n" "\" O$+O #:: . >\",\n" "\"> XX;::oO+++. \",\n" "\"> @--@ #o %***& \",\n" "\"> ==X $.OO +**& \",\n" "\"> $*OO*O O+. \",\n" "\">>> O**+.*& >\",\n" "\">>> %**+ +& >>>>\",\n" "\">>> .&& >>>>>\",\n" "\">>>> >>>>>>>\>\"\n" "};\n")) (defvar emchat-xwem-inactive (concat "/* XPM */\n" "static char *noname[] = {\n" "\"16 16 7 1\",\n" "\" c None\",\n" "\". c #000100 s foreground\",\n" "\"+ c #013200\",\n" "\"@ c #2C2C00\",\n" "\"# c #000000\",\n" "\"$ c #31000B\",\n" "\"o c gray s background\",\n" "/* pixels */\n" "\" ... .... \",\n" "\" ..o...oo+. \",\n" "\" .ooo.oooo. \",\n" "\" ..oo.oooo... \",\n" "\" ....oo.ooo..+..\",\n" "\".oooo.o++o.oooo.\",\n" "\".ooooo.@@.oooo..\",\n" "\".oooo.ooo.+.... \",\n" "\" ...#$ooo@oooo+.\",\n" "\" .ooo#.o@.ooooo.\",\n" "\" .oo$oo+oo.oooo.\",\n" "\" ....ooo#oo.oo+.\",\n" "\" .oooo#oo.... \",\n" "\" .oooo.oo. \",\n" "\" .+oo.... \",\n" "\" .... \"\n" "};\n")) (defvar emchat-xwem-saved-client nil "Saved selected xwem client.") (defvar emchat-xwem-keymap (let ((map (make-sparse-keymap))) (define-key map [button1] 'emchat-xwem-select-emchat) (define-key map [button3] 'emchat-xwem-restore-client) map) "*Keymap for emchat dock.") (defvar emchat-xwem-osd nil) (defvar emchat-xwem-dock nil) (defun emchat-xwem-activity-off () "Make the EMchat/XWEM activity indicator inactive." (emchat-xwem-dock-change-icon emchat-xwem-inactive) (emchat-xwem-osd-hide)) (defun emchat-xwem-activity-on () "Make the EMchat/XWEM activity indicator active." (emchat-xwem-dock-change-icon emchat-xwem-active) ;; NICK and MESSAGE are set by dynamic binding (declare (special nick message)) (emchat-xwem-osd-show-message nick message)) (defun emchat-xwem-init () "*Display EMchat activity indicator." (interactive) ;; Possible create dock (emchat-xwem-dock-change-icon emchat-xwem-inactive) (add-hook 'emchat-track-activity-hook 'emchat-xwem-activity-on) (add-hook 'emchat-track-clear-hook 'emchat-xwem-activity-off)) (defun emchat-xwem-fini () "Remove the EMchat activity indicator from the XWEM systray." (interactive) (emchat-xwem-dock-destroy) (emchat-xwem-osd-destroy) (remove-hook 'emchat-track-activity-hook 'emchat-xwem-activity-on) (remove-hook 'emchat-track-clear-hook 'emchat-xwem-activity-off)) ;; OSD (defun emchat-xwem-osd-create () "Create OSD for emchat messages." (setq emchat-xwem-osd (xwem-osd-create (xwem-dpy) (car emchat-xwem-osd-coordinates) (cdr emchat-xwem-osd-coordinates) 2048 1024)) (xwem-osd-set-font emchat-xwem-osd emchat-xwem-osd-font)) (defun emchat-xwem-osd-destroy () "Destroy emchat OSD." (when emchat-xwem-osd (when (itimerp (xwem-osd-get-prop emchat-xwem-osd 'timer)) (delete-itimer (xwem-osd-get-prop emchat-xwem-osd 'timer))) (xwem-osd-destroy emchat-xwem-osd) (setq emchat-xwem-osd nil))) (defun emchat-xwem-osd-color-for-nick (nick) "Return OSD color to use for NICK." (let ((groups (plist-get (assoc nick emchat-world) 'group))) (or (cdr (find groups emchat-xwem-osd-group-colors :key #'car :test #'(lambda (g i) (member i g)))) emchat-xwem-osd-color))) (defun emchat-xwem-osd-show-message (nick message) "Display NICK and MESSAGE in emchat OSD." (when emchat-xwem-osd-enable (unless emchat-xwem-osd (emchat-xwem-osd-create)) ;; Find and set proper color (xwem-osd-set-color emchat-xwem-osd (emchat-xwem-osd-color-for-nick nick)) ;; Just make sure OSD is clear (xwem-osd-clear emchat-xwem-osd) (when emchat-xwem-osd-show-icon (xwem-osd-icon-data-add emchat-xwem-osd emchat-xwem-osd-icon)) (xwem-osd-text-add emchat-xwem-osd (if emchat-xwem-osd-show-icon (glyph-width (make-glyph `[xpm :data ,emchat-xwem-osd-icon])) 0) 0 (encode-coding-string (format "%s: %s" nick message) (and (string-match font-x-registry-and-encoding-regexp emchat-xwem-osd-font) (intern (downcase (format "%s-%s" (match-string 1 emchat-xwem-osd-font) (match-string 2 emchat-xwem-osd-font))))) )) (xwem-osd-show emchat-xwem-osd) (when (itimerp (xwem-osd-get-prop emchat-xwem-osd 'timer)) (delete-itimer (xwem-osd-get-prop emchat-xwem-osd 'timer))) (xwem-osd-put-prop emchat-xwem-osd 'timer (start-itimer "emchat-osd" #'emchat-xwem-osd-hide emchat-xwem-osd-display-time)))) (defun emchat-xwem-osd-hide () "Hide emchat OSD." (when (xwem-osd-p emchat-xwem-osd) (xwem-osd-hide emchat-xwem-osd) (xwem-osd-destroy-instances emchat-xwem-osd) (when (itimerp (xwem-osd-get-prop emchat-xwem-osd 'timer)) (delete-itimer (xwem-osd-get-prop emchat-xwem-osd 'timer))) (xwem-osd-rem-prop emchat-xwem-osd 'timer))) ;; Dock (defun emchat-xwem-dock-create () "Create emchat dock." (setq emchat-xwem-dock (xwem-osd-create-dock (xwem-dpy) 16 16 (list 'keymap emchat-xwem-keymap))) (xwem-osd-show emchat-xwem-dock)) (defun emchat-xwem-dock-destroy () "Destroy emchat dock." (when (xwem-osd-p emchat-xwem-dock) (xwem-osd-destroy emchat-xwem-dock)) (setq emchat-xwem-dock nil)) (defun emchat-xwem-dock-change-icon (icon) "Change emchat dock icon to ICON." (when emchat-xwem-dock-enable (unless emchat-xwem-dock (emchat-xwem-dock-create)) (xwem-osd-icon-data-add emchat-xwem-dock icon))) ;;; Commands ;; Note: we can use ordinary Emacs commands here, because interactive ;; form is empty, for complex commands we must use ;; `define-xwem-command' and `xwem-interactive'. (defun emchat-xwem-select-emchat () "Make emchat be current client." (interactive) (let ((eicl (xwem-misc-find-cl-by-emacs-frame emchat-frame))) (setq emchat-xwem-saved-client (xwem-cl-selected)) (xwem-select-client eicl) (emchat-show-window))) (defun emchat-xwem-restore-client () "Display unseen senders." (interactive) (if (xwem-cl-alive-p emchat-xwem-saved-client) (xwem-select-client emchat-xwem-saved-client) (xwem-message 'warn "EMchat: Saved client dissapeared"))) (provide 'emchat-xwem) ;;; emchat-xwem.el ends here