Merge XEmacs changes.
[elisp/liece.git] / lisp / liece-channel.el
index e340a23..80377a6 100644 (file)
@@ -30,6 +30,7 @@
 ;;; Code:
 
 (eval-when-compile (require 'liece-inlines))
+(eval-when-compile (require 'liece-misc))
 
 (eval-when-compile (require 'liece-clfns))
 
 
 ;;; Reader conventions
 (defun liece-channel-p (chnl)
-  (string-match
-   (eval-when-compile
-     (concat "^" liece-channel-regexp))
-   chnl))
+  (string-match (concat "^" liece-channel-regexp) chnl))
 
 (defun liece-channel-modeless-p (chnl)
-  (string-match
-   (eval-when-compile
-     (concat "^" liece-channel-modeless-regexp))
-   chnl))
+  (string-match (concat "^" liece-channel-modeless-regexp) chnl))
 
-(defalias 'liece-channel-equal 'string-equal-ignore-case)
+(defun liece-channel-equal (c1 c2)
+  (string-equal-ignore-case c1 c2))
 
 (defun liece-channel-member (chnl chnls)
   "Return non-nil if CHNL is member of CHNLS."
 
 (defun liece-channel-get-modes (&optional chnl)
   "Return CHNL or current channels's mode."
-  (get (intern (or chnl liece-current-channel) liece-obarray)
-       'mode))
+  (get (intern (or chnl liece-current-channel) liece-obarray) 'mode))
 
 (defun liece-channel-get-bans (&optional chnl)
   "Return CHNL or current channels's ban list."
-  (get (intern (or chnl liece-current-channel) liece-obarray)
-       'ban))
+  (get (intern (or chnl liece-current-channel) liece-obarray) 'ban))
 
 (defun liece-channel-get-invites (&optional chnl)
   "Return CHNL or current channels's invite list."
-  (get (intern (or chnl liece-current-channel) liece-obarray)
-       'invite))
+  (get (intern (or chnl liece-current-channel) liece-obarray) 'invite))
 
 (defun liece-channel-get-exceptions (&optional chnl)
   "Return CHNL or current channels's exception list."
-  (get (intern (or chnl liece-current-channel) liece-obarray)
-       'exception))
+  (get (intern (or chnl liece-current-channel) liece-obarray) 'exception))
 
-;;; Internal functions
-(defun liece-channel-remove (chnl chnls)
-  "Remove CHNL from CHNLS."
+;;; Channel status functions
+(defun liece-channel-remove (channel channels)
+  "Remove CHANNEL from CHANNELS."
   (remove-if
    (lambda (item)
-     (and (stringp item) (liece-channel-equal chnl item)))
-   chnls))
+     (and (stringp item) (liece-channel-equal channel item)))
+   channels))
 
-(defun liece-channel-delete (chnl chnls)
-  "Delete CHNL from CHNLS."
+(defun liece-channel-delete (channel channels)
+  "Delete CHANNEL from CHANNELS."
   (delete-if
    (lambda (item)
-     (and (stringp item) (liece-channel-equal chnl item)))
-   chnls))
-
-(defmacro liece-channel-set-topic (topic &optional chnl)
-  "Set CHNL or current channels's topic."
-  `(put (intern (or ,chnl liece-current-channel) liece-obarray)
-       'topic ,topic))
-
-(defmacro liece-channel-add-mode (mode &optional chnl)
-  "Add MODE as char to CHNL."
-  `(let ((modes (string-to-char-list (or (liece-channel-get-modes ,chnl)
-                                        ""))))
-     (pushnew ,mode modes)
-     (put (intern (or ,chnl liece-current-channel) liece-obarray)
-         'mode (mapconcat #'char-to-string modes ""))))
-
-(defmacro liece-channel-remove-mode (mode &optional chnl)
-  "Remove MODE as char to CHNL."
-  `(let ((modes (string-to-char-list (or (liece-channel-get-modes ,chnl)
-                                        ""))))
-     (delq ,mode modes)
-     (put (intern (or ,chnl liece-current-channel) liece-obarray)
-         'mode (mapconcat #'char-to-string modes ""))))
-
-(defmacro liece-channel-set-mode (val mode &optional chnl)
-  "Set character VAL as channel MODE into the CHNL."
-  `(if val
-       (liece-channel-add-mode ,mode ,chnl)
-     (liece-channel-remove-mode ,mode ,chnl)))
-
-(defmacro liece-channel-add-ban (pattern &optional chnl)
-  "Add ban PATTERN as char to CHNL."
-  `(let ((patterns (liece-channel-get-bans ,chnl)))
-     (add-to-list 'patterns ,pattern)
-     (put (intern (or ,chnl liece-current-channel) liece-obarray)
-         'ban patterns)))
-
-(defmacro liece-channel-remove-ban (pattern &optional chnl)
-  "Remove ban PATTERN as char to CHNL."
-  `(let ((patterns (remove-if (lambda (elm) (string-equal ,pattern elm))
-                             (liece-channel-get-bans ,chnl))))
-     (put (intern (or ,chnl liece-current-channel) liece-obarray)
-         'ban patterns)))
-
-(defmacro liece-channel-set-ban (chnl pattern val)
-  "Set ban PATTERN as char to CHNL."
-  `(if val
-       (liece-channel-add-ban ,pattern ,chnl)
-     (liece-channel-remove-ban ,pattern ,chnl)))
-
-(defmacro liece-channel-add-exception (pattern &optional chnl)
-  "Add exception PATTERN as char to CHNL."
-  `(let ((patterns (liece-channel-get-exceptions ,chnl)))
-     (pushnew ,pattern patterns)
-     (put (intern (or ,chnl liece-current-channel) liece-obarray)
-         'exception patterns)))
-
-(defmacro liece-channel-remove-exception (pattern &optional chnl)
-  "Remove exception PATTERN as char to CHNL."
-  `(let ((patterns (remove-if (lambda (elm) (string-equal ,pattern elm))
-                             (liece-channel-get-exceptions ,chnl))))
-     (put (intern (or ,chnl liece-current-channel) liece-obarray)
-         'exception patterns)))
-
-(defmacro liece-channel-set-exception (chnl pattern val)
-  "Set exception PATTERN as char to CHNL."
-  `(if val
-       (liece-channel-add-exception ,pattern ,chnl)
-     (liece-channel-remove-exception ,pattern ,chnl)))
-
-(defmacro liece-channel-add-invite (pattern &optional chnl)
-  "Add invite PATTERN as char to CHNL."
-  `(let ((patterns (liece-channel-get-invites ,chnl)))
-     (pushnew ,pattern patterns)
-     (put (intern (or ,chnl liece-current-channel) liece-obarray)
-         'invite patterns)))
-
-(defmacro liece-channel-remove-invite (pattern &optional chnl)
-  "Remove invite PATTERN as char to CHNL."
-  `(let ((patterns (remove-if (lambda (elm) (string-equal ,pattern elm))
-                             (liece-channel-get-invites ,chnl))))
-     (put (intern (or ,chnl liece-current-channel) liece-obarray)
-         'invite patterns)))
-
-(defmacro liece-channel-set-invite (chnl pattern val)
-  "Set invite PATTERN as char to CHNL."
-  `(if val
-       (liece-channel-add-invite ,pattern ,chnl)
-     (liece-channel-remove-invite ,pattern ,chnl)))
+     (and (stringp item) (liece-channel-equal channel item)))
+   channels))
+
+(defun liece-channel-set-topic (topic &optional channel)
+  "Set CHANNEL's topic."
+  (put (intern (or channel liece-current-channel) liece-obarray)
+       'topic topic))
+
+(defun liece-channel-add-mode (mode &optional channel)
+  "Add MODE to CHANNEL.
+MODE is a string splitted into characters one by one."
+  (let ((modes
+        (liece-string-to-list
+         (or (liece-channel-get-modes channel)
+             ""))))
+    (or (memq mode modes)
+       (push mode modes))
+    (put (intern (or channel liece-current-channel) liece-obarray)
+        'mode (mapconcat #'char-to-string modes ""))))
+
+(defun liece-channel-remove-mode (mode &optional channel)
+  "Remove MODE from CHANNEL.
+MODE is a string splitted into characters one by one."
+  (let ((modes
+        (liece-string-to-list
+         (or (liece-channel-get-modes channel)
+             ""))))
+    (delq mode modes)
+    (put (intern (or channel liece-current-channel) liece-obarray)
+        'mode (mapconcat #'char-to-string modes ""))))
+
+(defun liece-channel-set-mode (channel mode flag)
+  "Add or remove channel MODE of CHANNEL.
+MODE is a string splitted into characters one by one.
+If FLAG is non-nil, given modes are added to the channel.
+Otherwise they are removed from the channel."
+  (if flag
+      (liece-channel-add-mode mode channel)
+    (liece-channel-remove-mode mode channel)))
+
+(defun liece-channel-add-ban (pattern &optional channel)
+  "Add ban PATTERN to CHANNEL."
+  (let ((patterns (liece-channel-get-bans channel)))
+    (or (string-list-member-ignore-case pattern patterns)
+       (push pattern patterns))
+    (put (intern (or channel liece-current-channel) liece-obarray)
+        'ban patterns)))
+
+(defun liece-channel-remove-ban (pattern &optional channel)
+  "Remove ban PATTERN from CHANNEL."
+  (let ((patterns
+        (remove-if
+         (lambda (elm) (string-equal pattern elm))
+         (liece-channel-get-bans channel))))
+    (put (intern (or channel liece-current-channel) liece-obarray)
+        'ban patterns)))
+
+(defun liece-channel-set-ban (channel pattern flag)
+  "Add or remove ban PATTERN to CHANNEL.
+If FLAG is non-nil, given ban patterns are added to the channel.
+Otherwise they are removed from the channel."
+  (if flag
+      (liece-channel-add-ban pattern channel)
+    (liece-channel-remove-ban pattern channel)))
+
+(defun liece-channel-add-exception (pattern &optional channel)
+  "Add exception PATTERN to CHANNEL."
+  (let ((patterns (liece-channel-get-exceptions channel)))
+    (or (string-list-member-ignore-case pattern patterns)
+       (push pattern patterns))
+    (put (intern (or channel liece-current-channel) liece-obarray)
+        'exception patterns)))
+
+(defun liece-channel-remove-exception (pattern &optional channel)
+  "Remove exception PATTERN from CHANNEL."
+  (let ((patterns
+        (remove-if
+         (lambda (elm) (string-equal pattern elm))
+         (liece-channel-get-exceptions channel))))
+    (put (intern (or channel liece-current-channel) liece-obarray)
+        'exception patterns)))
+
+(defun liece-channel-set-exception (channel pattern flag)
+  "Add or remove exception PATTERN to CHANNEL.
+If FLAG is non-nil, given exception patterns are added to the channel.
+Otherwise they are removed from the channel."
+  (if flag
+      (liece-channel-add-exception pattern channel)
+     (liece-channel-remove-exception pattern channel)))
+
+(defun liece-channel-add-invite (pattern &optional channel)
+  "Add invite PATTERN to CHANNEL."
+  (let ((patterns (liece-channel-get-invites channel)))
+    (or (string-list-member-ignore-case pattern patterns)
+       (push pattern patterns))
+    (put (intern (or channel liece-current-channel) liece-obarray)
+        'invite patterns)))
+
+(defun liece-channel-remove-invite (pattern &optional channel)
+  "Remove invite PATTERN from CHANNEL."
+  (let ((patterns
+        (remove-if
+         (lambda (elm) (string-equal pattern elm))
+         (liece-channel-get-invites channel))))
+    (put (intern (or channel liece-current-channel) liece-obarray)
+        'invite patterns)))
+
+(defun liece-channel-set-invite (channel pattern flag)
+  "Add or remove invite PATTERN to CHANNEL.
+If FLAG is non-nil, given invite patterns are added to the channel.
+Otherwise they are removed from the channel."
+  (if flag
+      (liece-channel-add-invite pattern channel)
+     (liece-channel-remove-invite pattern channel)))
   
-(defun liece-channel-virtual (chnl)
+(defun liece-channel-virtual (channel)
   "Convert channel name into internal representation.
-\(For example if CHNL is a string \"#...:*\", it will be converted into
+\(For example if CHANNEL is a string \"#...:*\", it will be converted into
 \"%...\"\)"
   (let ((mapping liece-channel-conversion-map) match)
     (while mapping
-      (if (string-equal-ignore-case (caar mapping) chnl)
+      (if (string-equal-ignore-case (caar mapping) channel)
          (setq match (cdar mapping)))
       (pop mapping))
     (if match
        match
       (save-match-data
        (cond
-        ((and (string-match "^[#+]\\(.*\\):\\(.*\\)$" chnl)
-              (string= (match-string 2 chnl)
-                       liece-channel-conversion-default-mask))
-         (if (eq ?+ (aref chnl 0))
-             (concat "-" (match-string 1 chnl))
-           (concat "%" (match-string 1 chnl))))
-        ((string= "" chnl) chnl)
-;       ((eq ?! (aref chnl 0))
-;        (concat "!" (substring chnl (1+ liece-channel-id-length))))
-        (t chnl))))))
-
-(defun liece-channel-real (chnl)
+        ((string-match
+          (format "^[#+]\\(.*\\):%s$"
+                  (regexp-quote liece-channel-conversion-default-mask))
+          channel)
+         (if (eq ?+ (aref channel 0))
+             (concat "-" (match-string 1 channel))
+           (concat "%" (match-string 1 channel))))
+;;;     ((and (not (equal channel "")) (eq ?! (aref channel 0)))
+;;;      (concat "!" (substring channel (1+ liece-channel-id-length))))
+        (t channel))))))
+
+(defun liece-channel-real (channel)
   "Convert channel name into external representation.
-\(For example if CHNL is a string \"%...\", it will be converted into
+\(For example if CHANNEL is a string \"%...\", it will be converted into
 \"#...:*\"\)"
   (let ((mapping liece-channel-conversion-map) match)
     (while mapping
-      (if (string-equal-ignore-case (cdar mapping) chnl)
+      (if (string-equal-ignore-case (cdar mapping) channel)
          (setq match (caar mapping)))
       (pop mapping))
     (cond
      (match match)
-     ((eq ?% (aref chnl 0))
-      (concat "#" (substring chnl 1) ":"
+     ((eq ?% (aref channel 0))
+      (concat "#" (substring channel 1) ":"
              liece-channel-conversion-default-mask))
-     ((eq ?- (aref chnl 0))
-      (concat "+" (substring chnl 1) ":"
+     ((eq ?- (aref channel 0))
+      (concat "+" (substring channel 1) ":"
              liece-channel-conversion-default-mask))
-     (t chnl))))
+     (t channel))))
 
 ;;;###liece-autoload
 (defun liece-command-toggle-channel-buffer-mode ()
       (setq liece-channel-buffer-mode (not liece-channel-buffer-mode)))
   (liece-configure-windows))
 
-(defmacro liece-channel-buffer-create (chnl)
+(defun liece-channel-buffer-create (chnl)
   "Create channel buffer of CHNL."
-  `(with-current-buffer
-       (liece-get-buffer-create (format liece-channel-buffer-format ,chnl))
+  (with-current-buffer
+       (liece-get-buffer-create (format liece-channel-buffer-format chnl))
      (let (buffer-read-only)
        (liece-insert-info (current-buffer)
                           (concat (funcall liece-format-time-function
                                   " Created.\n")))
      (unless (eq major-mode 'liece-channel-mode)
        (liece-channel-mode))
-     (set-alist 'liece-channel-buffer-alist ,chnl (current-buffer))
+     (set-alist 'liece-channel-buffer-alist chnl (current-buffer))
      (current-buffer)))
 
 (defun liece-channel-join-internal (item chnls &optional hints)
@@ -324,6 +341,12 @@ If NOSW is non-nil do not switch to newly created channel."
            liece-nick-buffer nbuf))
     (liece-channel-change)))
 
+(defmacro liece-channel-switch-to-last (chnls)
+  `(let ((chnl (liece-channel-last ,chnls)))
+     (if chnl
+        (liece-switch-to-channel chnl))
+     (liece-channel-change)))
+
 (defun liece-channel-part-internal (item chnls &optional hints)
   (if hints
       (mapcar
@@ -352,17 +375,12 @@ If NOSW is non-nil do not switch to newly created channel."
 (defun liece-channel-last (chnls)
   (car (last (delq nil (copy-sequence chnls)))))
 
-(defmacro liece-channel-switch-to-last (chnls)
-  `(let ((chnl (liece-channel-last ,chnls)))
-     (if chnl
-        (liece-switch-to-channel chnl))
-     (liece-channel-change)))
-
 (defun liece-channel-change ()
   (let ((chnls (if (eq liece-command-buffer-mode 'chat)
                   liece-current-chat-partners
                 liece-current-channels))
-       (string ""))
+       (string "")
+       chnl)
     (with-current-buffer liece-channel-list-buffer
       (let ((n 1) buffer-read-only)
        (erase-buffer)
@@ -373,17 +391,18 @@ If NOSW is non-nil do not switch to newly created channel."
            (liece-channel-list-add-button n chnl))
          (incf n))))
     (if (string-equal string "")
-       (cond
-        ((eq liece-command-buffer-mode 'chat)
-         (setq liece-channels-indicator "No partner"
-               liece-current-chat-partner nil))
-        (t
-         (setq liece-channels-indicator "No channel"
-               liece-current-channel nil)))
+       (if (eq liece-command-buffer-mode 'chat)
+           (setq liece-channels-indicator "No partner")
+         (setq liece-channels-indicator "No channel"))
       (setq liece-channels-indicator (substring string 1)))
     (liece-set-channel-indicator)
-    (save-excursion
-      (run-hook-with-args 'liece-redisplay-buffer-functions chnl))
+    (setq chnl (if (eq liece-command-buffer-mode 'chat)
+                  liece-current-chat-partner
+                liece-current-channel))
+    (when chnl
+      (save-excursion
+       (run-hook-with-args 'liece-redisplay-buffer-functions chnl)))
+    (liece-redisplay-unread-mark)
     (liece-configure-windows)))
 
 (defsubst liece-channel-set-operator-1 (chnl user val)
@@ -502,9 +521,10 @@ If NOSW is non-nil do not switch to newly created channel."
         (cdr (string-assoc-ignore-case
               chnl liece-channel-buffer-alist)))
        (window (liece-get-buffer-window liece-channel-buffer)))
-    (and (liece-channel-unread-p chnl)
-        (setq liece-channel-unread-list
-              (delete chnl liece-channel-unread-list)))
+    (when (liece-channel-unread-p chnl)
+      (setq liece-channel-unread-list
+           (delete chnl liece-channel-unread-list))
+      (run-hook-with-args 'liece-channel-read-functions chnl))
     (and buffer window
         (with-current-buffer buffer
           (set-window-buffer window buffer)