+;;; Channels and users
+;;
+
+(defvar lirc-current-channel nil)
+
+(defun lirc-channel (name next prev users)
+ (list name prev next users))
+
+(defun lirc-get-channel-name (channel)
+ (elt channel 0))
+(defun lirc-get-channel-next (channel)
+ (elt channel 1))
+(defun lirc-get-channel-prev (channel)
+ (elt channel 2))
+(defun lirc-get-channel-users (channel)
+ (elt channel 3))
+
+(defun lirc-set-channel-name (channel name)
+ (setf (elt channel 0) name))
+(defun lirc-set-channel-next (channel next)
+ (setf (elt channel 1) next))
+(defun lirc-set-channel-prev (channel prev)
+ (setf (elt channel 2) prev))
+(defun lirc-set-channel-users (channel users)
+ (setf (elt channel 3) users))
+
+(defun lirc-add-channel (new-channel)
+ (if lirc-current-channel
+ (let* ((prev lirc-current-channel)
+ (next (lirc-get-channel-next lirc-current-channel)))
+ (lirc-set-channel-next new-channel prev)
+ (lirc-set-channel-prev new-channel next))
+ (lirc-set-channel-next new-channel new-channel)
+ (lirc-set-channel-prev new-channel new-channel))
+ (setq lirc-current-channel new-channel))
+
+(defun lirc-del-channel (channel)
+ (let ((prev (lirc-get-channel-prev channel))
+ (next (lirc-get-channel-next channel)))
+ (if (and prev next)
+ (if (eq prev next)
+ (progn
+ (lirc-set-channel-next prev nil)
+ (lirc-set-channel-prev prev nil)
+ (setq lirc-current-channel prev))
+ (lirc-set-channel-next prev next)
+ (lirc-set-channel-prev next prev)
+ (if (eq channel lirc-current-channel)
+ (setq lirc-current-channel prev)))
+ (setq lirc-current-channel nil))))
+
+(defun lirc-channel-do (proc)
+ (if lirc-current-channel
+ (let ((channel lirc-current-channel))
+ (funcall proc lirc-current-channel)
+ (while (not (eq (lirc-get-channel-next channel) lirc-current-channel))
+ (setq channel (lirc-get-channel-next channel))
+ (funcall proc channel)))))
+
+(defun lirc-get-channel-with-name (channel-name)
+ (if lirc-current-channel
+ (let ((channel lirc-current-channel))
+ (while (and (not (equal (lirc-get-channel-name channel) channel-name))
+ (not (eq (lirc-get-channel-next channel) lirc-current-channel)))
+ (setq channel (lirc-get-channel-next channel)))
+ (if (equal (lirc-get-channel-name channel) channel-name)
+ channel
+ nil))
+ nil))
+
+(defun lirc-add-channel-with-name (channel-name)
+ (lirc-add-channel (lirc-channel channel-name nil nil nil)))
+
+(defun lirc-add-channel-users (channel &rest users)
+ (lirc-set-channel-users channel (append users (lirc-get-channel-users channel))))
+
+(defun lirc-del-channel-users (channel &rest users)
+ (lirc-set-channel-users channel (cl-set-difference (lirc-get-channel-users channel) users)))
+
+(defun lirc-del-users (&rest users)
+ (lirc-channel-do
+ (lambda (channel)
+ (lirc-set-channel-users
+ channel
+ (cl-set-difference
+ (lirc-get-channel-users channel)
+ users
+ :test #'equal)))))
+
+(defun lirc-rename-user (old-nick new-nick)
+ (lirc-channel-do
+ (lambda (channel)
+ (lirc-set-channel-users
+ (cons new-nick (delete old-nick (lirc-get-channel-users channel)))))))
+
+(defun lirc-cycle-channels ()
+ (interactive)
+ (if lirc-current-channel
+ (progn
+ (setq lirc-current-channel (lirc-get-channel-next lirc-current-channel))
+ (lirc-render-prompt))
+ (lirc-display-error "No channels joined.")))
+