+(defun riece-format-identity (identity &optional prefix-only)
+ "Convert IDENTITY object to a string.
+If the optional 2nd argument PREFIX-ONLY is non-nil, don't append
+server part of the identity.
+
+The returned string will be abbreviated by
+`riece-abbrev-identity-string-function', and `riece-identity' property
+will be added."
+ (let ((string
+ (if (or prefix-only
+ (equal (riece-identity-server identity) ""))
+ (copy-sequence (riece-identity-prefix identity))
+ (concat (riece-identity-prefix identity) " "
+ (riece-identity-server identity)))))
+ (if riece-abbrev-identity-string-function
+ (setq string (funcall riece-abbrev-identity-string-function string)))
+ (riece-put-text-property-nonsticky 0 (length string)
+ 'riece-identity identity
+ string)
+ (if prefix-only
+ (riece-put-text-property-nonsticky 0 (length string)
+ 'riece-format-identity-prefix-only t
+ string))
+ string))
+
+(defun riece-parse-identity (string)
+ "Convert STRING to an identity object.
+The string will be expanded by
+`riece-expand-identity-string-function'."
+ (if riece-expand-identity-string-function
+ (setq string (funcall riece-expand-identity-string-function string)))
+ (riece-make-identity (if (string-match " " string)
+ (substring string 0 (match-beginning 0))
+ string)
+ (if (string-match " " string)
+ (substring string (match-end 0))
+ "")))
+
+(defun riece-completing-read-identity (prompt channels
+ &optional predicate require-match
+ initial history default
+ no-server)
+ "Read an identity object in the minibuffer, with completion.
+PROMPT is a string to prompt with; normally it ends in a colon and a space.
+CHANNELS is a list of identity objects.
+The rest of arguments are the same as `completing-read'."
+ (let* ((string
+ (completing-read
+ prompt
+ (mapcar (lambda (channel)
+ (list (riece-format-identity channel no-server)))
+ (delq nil (copy-sequence (or channels
+ riece-current-channels))))
+ predicate require-match initial history default))
+ (identity
+ (riece-parse-identity string)))
+;;; (unless (string-match (concat "^\\(" riece-channel-regexp "\\|"
+;;; riece-user-regexp "\\)")
+;;; (riece-identity-prefix identity))
+;;; (error "Invalid channel name!"))
+ identity))
+
+(defun riece-coding-system-for-identity (identity)
+ (let ((alist riece-channel-coding-system-alist)
+ matcher)
+ (catch 'found
+ (while alist
+ (setq matcher (riece-parse-identity (car (car alist))))
+ (if (and (equal (riece-identity-server matcher)
+ (riece-identity-server identity))
+ (equal (riece-identity-prefix matcher)
+ (riece-identity-prefix identity)))
+ (throw 'found (cdr (car alist))))
+ (setq alist (cdr alist))))))
+
+(defun riece-decoded-string-for-identity (decoded identity)
+ "Return the string decoded for IDENTITY."
+ (let ((coding-system (riece-coding-system-for-identity identity)))
+ (if (and coding-system
+ (not (eq (riece-decoded-coding-system decoded)
+ (if (consp coding-system)
+ (car coding-system)
+ coding-system))))
+ (riece-decode-coding-string-1 (riece-decoded-encoded-string decoded)
+ coding-system)
+ decoded)))
+
+(defun riece-encode-coding-string-for-identity (string identity)
+ (let ((coding-system (riece-coding-system-for-identity identity)))
+ (if coding-system
+ (encode-coding-string string
+ (if (consp coding-system)
+ (cdr coding-system)
+ coding-system))
+ (riece-encode-coding-string string))))