;;; Code:
-(eval-when-compile (require 'riece-inlines))
-
(require 'riece-globals)
-
-(defun riece-find-server-name ()
- (or riece-overriding-server-name
- ;already in the server buffer
- (if (local-variable-p 'riece-server-name (current-buffer))
- riece-server-name
- (if riece-current-channel
- (riece-identity-server riece-current-channel)))))
-
-(defun riece-find-server-process ()
- (let ((server-name (riece-find-server-name)))
- (if server-name
- (cdr (assoc server-name riece-server-process-alist))
- riece-server-process)))
-
-(defmacro riece-with-server-buffer (&rest body)
- `(let ((process (riece-find-server-process)))
- (if process
- (with-current-buffer (process-buffer process)
- ,@body)
- (error "Server closed."))))
+(require 'riece-coding)
+(require 'riece-server)
(defun riece-identity-prefix (identity)
"Return the component sans its server from IDENTITY."
- (if (string-match " " identity)
- (substring identity 0 (match-beginning 0))
- identity))
+ (aref identity 0))
(defun riece-identity-server (identity)
"Return the server component in IDENTITY."
- (if (string-match " " identity)
- (substring identity (match-end 0))))
+ (aref identity 1))
-(defun riece-make-identity (prefix &optional server)
+(defun riece-make-identity (prefix server)
"Make an identity object from PREFIX and SERVER."
- (if (riece-identity-server prefix)
- prefix
- (unless server
- (setq server (riece-find-server-name)))
- (if server
- (concat prefix " " server)
- prefix)))
-
-(defun riece-identity-equal-no-server (ident1 ident2)
- "Return t, if IDENT1 and IDENT2 is equal.
-The only difference with `riece-identity-equal', this function doesn't
-append server name before comparison."
- (and (string-equal-ignore-case
+ (vector prefix server))
+
+(defun riece-identity-equal (ident1 ident2)
+ "Return t, if IDENT1 and IDENT2 is equal."
+ (and (riece-identity-equal-no-server
(riece-identity-prefix ident1)
(riece-identity-prefix ident2))
(equal
(riece-identity-server ident1)
(riece-identity-server ident2))))
-(defun riece-identity-equal (ident1 ident2)
- "Return t, if IDENT1 and IDENT2 is equal."
- (riece-identity-equal-no-server
- (if (riece-identity-server ident1)
- ident1
- (riece-make-identity ident1))
- (if (riece-identity-server ident2)
- ident2
- (riece-make-identity ident2))))
-
-(defun riece-identity-member-no-server (elt list)
- "Return non-nil if an identity ELT is an element of LIST.
-The only difference with `riece-identity-member', this function uses
-`riece-identity-equal-no-server' for comparison."
- (catch 'found
- (while list
- (if (and (stringp (car list))
- (riece-identity-equal-no-server (car list) elt))
- (throw 'found list)
- (setq list (cdr list))))))
+(defun riece-identity-canonicalize-prefix (prefix)
+ "Canonicalize identity PREFIX.
+This function downcases PREFIX first, then does special treatment for
+Scandinavian alphabets.
+
+RFC2812, 2.2 \"Character codes\" says:
+ Because of IRC's Scandinavian origin, the characters {}|^ are
+ considered to be the lower case equivalents of the characters []\~,
+ respectively. This is a critical issue when determining the
+ equivalence of two nicknames or channel names."
+ (let* ((result (downcase prefix))
+ (length (length result))
+ (index 0))
+ (while (< index length)
+ (if (eq (aref result index) ?\[)
+ (aset result index ?{)
+ (if (eq (aref result index) ?\])
+ (aset result index ?})
+ (if (eq (aref result index) ?\\)
+ (aset result index ?|)
+ (if (eq (aref result index) ?~)
+ (aset result index ?^)))))
+ (setq index (1+ index)))
+ result))
+
+(defun riece-identity-equal-no-server (prefix1 prefix2)
+ "Return t, if IDENT1 and IDENT2 is equal without server."
+ (equal (riece-identity-canonicalize-prefix prefix1)
+ (riece-identity-canonicalize-prefix prefix2)))
(defun riece-identity-member (elt list)
"Return non-nil if an identity ELT is an element of LIST."
(catch 'found
(while list
- (if (and (stringp (car list))
+ (if (and (vectorp (car list)) ;needed because
+ ;riece-current-channels
+ ;contains nil.
(riece-identity-equal (car list) elt))
(throw 'found list)
(setq list (cdr list))))))
-(defun riece-identity-assoc-no-server (elt alist)
- "Return non-nil if an identity ELT matches the car of an element of ALIST."
- (catch 'found
- (while alist
- (if (riece-identity-equal-no-server (car (car alist)) elt)
- (throw 'found (car alist))
- (setq alist (cdr alist))))))
-
(defun riece-identity-assoc (elt alist)
"Return non-nil if an identity ELT matches the car of an element of ALIST."
(catch 'found
(setcar pointer item)
list))
-(defun riece-current-nickname ()
- "Return the current nickname."
- (riece-with-server-buffer
- (if riece-real-nickname
- (riece-make-identity riece-real-nickname))))
+(defmacro riece-with-identity-buffer (identity &rest body)
+ `(let ((process (riece-server-process (riece-identity-server ,identity))))
+ (if process
+ (with-current-buffer (process-buffer process)
+ ,@body)
+ (error "Server closed"))))
+
+(put 'riece-with-identity-buffer 'lisp-indent-function 1)
+
+(defun riece-decode-identity (identity &optional prefix-only)
+ (riece-with-identity-buffer identity
+ (let ((prefix (riece-decode-coding-string
+ (riece-identity-prefix identity)))
+ (server (riece-identity-server identity)))
+ (if (or prefix-only (equal server ""))
+ prefix
+ (concat prefix " " server)))))
+
+(defun riece-encode-identity (string)
+ (let ((prefix (if (string-match " " string)
+ (substring string 0 (match-beginning 0))
+ string))
+ (server (if (string-match " " string)
+ (substring string (match-end 0))
+ "")))
+ (riece-with-server-buffer server
+ (riece-make-identity (riece-encode-coding-string prefix) server))))
+
+(defun riece-completing-read-identity (prompt channels
+ &optional predicate must-match)
+ (let* ((decoded
+ (completing-read
+ prompt
+ (mapcar (lambda (channel)
+ (list (riece-decode-identity channel)))
+ (delq nil (copy-sequence (or channels
+ riece-current-channels))))
+ predicate must-match))
+ (encoded
+ (riece-encode-identity decoded)))
+ (if (and (not (string-match "[ ,]" decoded))
+ (string-match "[ ,]" (riece-identity-prefix encoded))
+ (not (y-or-n-p (format "The encoded channel name contains illegal character \"%s\". continue? "
+ (match-string 0 (riece-identity-prefix encoded))))))
+ (error "Invalid channel name!"))
+ encoded))
(provide 'riece-identity)