;;;
;;; $Id: irchat-commands.el,v 1.9 1993/07/15 17:31:37 tmo Exp $
;;;
;;; see file irchat-copyright.el for change log and copyright info

(provide 'irchat-commands)
(require 'gnus-caesar)
(require 'irchat-inlines)
(require 'irchat-globals)

(defun irchat-Command-describe-briefly ()
  (message (substitute-command-keys "Type \\[describe-mode] for help")))


(defun irchat-Command-redisplay (&optional center)
  "Un-freezes and re-selects the Dialogue buffer in another window.
   With argument, recenter with that argument."
  (interactive "P")
  (setq irchat-freeze nil)
  (setq irchat-freeze-indicator "-")
  (if (get-buffer-window irchat-Dialogue-buffer)
      nil
    (if (one-window-p)
	(irchat-configure-windows)
      (display-buffer irchat-Dialogue-buffer)))
  (set-buffer irchat-Dialogue-buffer)
  (set-window-point (get-buffer-window irchat-Dialogue-buffer) (point-max)))


(defun irchat-Command-send-message (message)
  "Send MESSAGE to current chat partner of current channel."
  (if (eq irchat-command-buffer-mode 'chat)
      (if irchat-current-chat-partner
	  (progn
	    (irchat-send "PRIVMSG %s :%s" irchat-current-chat-partner message)
	    (irchat-own-message (format (format "%s %%s"
						irchat-format-string)
					irchat-current-chat-partner message)))
	(message 
	 (substitute-command-keys 
	  "Type \\[irchat-Command-join] to start private conversation")))
    (if (not irchat-current-channel)
	(progn
	  (beep t)
	  (message 
	   (substitute-command-keys 
	    "Type \\[irchat-Command-join] to join a channel")))
      (irchat-send "PRIVMSG %s :%s" irchat-current-channel message)
      (irchat-own-message (concat "> " message)))))


(defun irchat-Command-enter-message ()
  "Enter the current line as an entry in the IRC dialogue on the
current channel."
  (interactive)
  (let (message start)
    (beginning-of-line)
    (setq start (point))
    (end-of-line)
    (setq message (buffer-substring start (point)))
    (next-line 1)
    (irchat-Command-send-message message)))


(defun irchat-Dialogue-enter-message ()
  "Ask for a line as an entry in the IRC dialogue on the current channel."
  (interactive)
  (let ((message "x"))
    (while (not (string= message ""))
      (setq message (read-string "> "))
      (if (not (string= message ""))
	  (irchat-Command-send-message message)))))


(defun irchat-Command-debug ()
  "Start debugging irchat."
  (interactive)
  (if irchat-debug-buffer
      (progn
	(setq irchat-debug-buffer nil)
	(other-window 1)
	(delete-window)
	(other-window -1))
    (if irchat-use-full-window
	(delete-other-windows))
    (irchat-configure-windows)
    (split-window-horizontally)
    (other-window 1)
    (setq irchat-debug-buffer (get-buffer-create "*IRC Debugging*"))
    (switch-to-buffer irchat-debug-buffer)
    (other-window -1)))


(defun irchat-Command-inline ()
  "Send current line as a message to the IRC server."
  (interactive)
  (let (message start stop)
    (beginning-of-line)
    (setq start (point))
    (end-of-line)
    (setq stop (point))
    (setq message (buffer-substring start stop))
    (newline)
    (irchat-send message)))


(defun irchat-Command-join (join-channel-var)
  "Join a channel or private conversation.
If user nicname is given, join the same set of channels as 
the specified user. 
If Command-buffer is in chat-mode, start private conversation 
with specified user."

  (interactive (let (join-channel-var (completion-ignore-case t))
		 (setq join-channel-var 
		       (if (eq irchat-command-buffer-mode 'chat)
			   (irchat-completing-default-read
			    "Start private conversation with: "
			    irchat-nick-alist
			    '(lambda (s) t) nil irchat-privmsg-partner)
			 (irchat-completing-default-read
			  "Join channel: "
			  (append irchat-channel-alist
				  irchat-nick-alist)
			  '(lambda (s) t) nil irchat-invited-channel)))
		 (list join-channel-var)))

  (if (eq irchat-command-buffer-mode 'chat)
      (progn
	(setq irchat-current-chat-partners (append 
					    (list join-channel-var)
					    (string-list-ci-delete
					     join-channel-var
					     irchat-current-chat-partners))
	      irchat-current-chat-partner join-channel-var
	      irchat-chat-partner-alist (list-to-assoclist 
					 irchat-current-chat-partners)
	      irchat-channel-indicator (if irchat-current-chat-partner
					   (format "Chatting with %s" 
						   irchat-current-chat-partner)
					 "No partner")))
    (progn
      (let ((nicks irchat-nick-alist)
	    (found nil))
	(while (and (not found)	nicks)
	  (if (and (car (car nicks))
		   (string= (upcase join-channel-var) 
			    (upcase (car (car nicks)))))
	      (setq join-channel-var
		    (or (car (get (intern (car (car nicks))) 'chnl))
			join-channel-var)
		    found t))
	  (setq nicks (cdr nicks))))
      (let ((found nil))
	(mapcar 
	 '(lambda (elem)
	    (if (string= (upcase join-channel-var) (upcase elem))
		(setq irchat-current-channel elem
		      found t)))
	 irchat-current-channels)
	(setq irchat-channel-indicator
	      (if irchat-current-channel
		  (format "Channel %s" irchat-current-channel)
		"No channel"))
	(setq irchat-invited-channel nil)
	(or found (irchat-send "JOIN %s" join-channel-var))))))


(defun irchat-Command-part (part-channel-var)
  "Part a channel or private conversation."
  (interactive (let (part-channel-var (completion-ignore-case t))
		 (setq part-channel-var 
		       (if (eq irchat-command-buffer-mode 'chat)
			   (irchat-completing-default-read	
			    "End private conversation with: "
			    irchat-chat-partner-alist
			    '(lambda (s) t) nil 
			    irchat-current-chat-partner)
			 (irchat-completing-default-read	
			  "Part channel: "
			  (list-to-assoclist irchat-current-channels)
			  '(lambda (s) t) nil 
			  irchat-current-channel)))
		 (list part-channel-var)))
  (if (eq irchat-command-buffer-mode 'chat)
      (setq irchat-current-chat-partners (string-list-ci-delete
					  part-channel-var
					  irchat-current-chat-partners)
	    irchat-current-chat-partner (car irchat-current-chat-partners)
	    irchat-chat-partner-alist (list-to-assoclist 
				       irchat-current-chat-partners)
	    irchat-channel-indicator (if irchat-current-chat-partner
					 (format "Chatting with %s" 
						 irchat-current-chat-partner)
				       "No partner"))
    (progn
      (if (string-list-ci-memberp part-channel-var irchat-current-channels)
	  (setq irchat-current-channel part-channel-var)) ; just refocusing
      (irchat-send "PART %s" part-channel-var))))


(defun irchat-Command-kill (kill-nickname-var)
  "Ignore messages from this user.  If already ignoring him/her, toggle."
  (interactive (let (kill-nickname-var (completion-ignore-case t))
		 (setq kill-nickname-var 
		       (completing-read 
			"Ignore nickname: " 
			irchat-nick-alist
			'(lambda (s) t) nil nil))
		 (list kill-nickname-var)))
  (if (string= "" kill-nickname-var)
      (let ((buf (current-buffer)))
	(set-buffer irchat-Dialogue-buffer)
	(setq buffer-read-only nil)
	(goto-char (point-max))
	(insert "*** Currently ignored people:")
	(let ((mylist irchat-kill-nickname))
	  (while mylist
	    (insert (format " %s" (car mylist)))
	    (setq mylist (cdr mylist))))
	(newline)
	(setq buffer-read-only t)
	(set-buffer buf)))
  (if (memq (intern kill-nickname-var) irchat-kill-nickname)
      (setq irchat-kill-nickname 
	    (delq (intern kill-nickname-var) irchat-kill-nickname))
    (setq irchat-kill-nickname 
	  (cons (intern kill-nickname-var) irchat-kill-nickname))))


(defun irchat-Command-kick (kick-nickname-var)
  "Kick this user out."
  (interactive (let (kick-nickname-var (completion-ignore-case t))
		 (setq kick-nickname-var 
		       (completing-read 
			"Kick out nickname: " 
			irchat-nick-alist
			'(lambda (s) t) nil nil))
		 (list kick-nickname-var)))
  (irchat-send "KICK %s %s" irchat-current-channel kick-nickname-var))


(defun irchat-Command-list (&optional channel)
  "List the given channel and its topics.
If you enter only Control-U as argument, list the current channel.
With - as argument, list all channels."
  (interactive
   (if current-prefix-arg
       (if (eq current-prefix-arg '-)
	   (list current-prefix-arg)
	 nil)
     (list
      (let ((completion-ignore-case t))
	(completing-read 
	 "LIST channel: " 
	 irchat-channel-alist
	 '(lambda (s) t) nil nil)))))
  (if (not channel)
      (irchat-send "LIST %s" irchat-current-channel)
    (if (eq channel '-)
	(irchat-send "LIST")
      (irchat-send "LIST %s" channel))))


(defun irchat-Command-lusers ()
  "List the number of users and servers"
  (interactive)
  (irchat-send "LUSERS"))


(defun irchat-Command-modec (change)
  "Send a MODE command"
  (interactive "sMode for this channel: ")
  (irchat-send "MODE %s %s"
	       irchat-current-channel
	       change))


(defun irchat-Command-message (message-nick-var message)
  "Send a private message to another user."
  (interactive (let (message-nick-var (completion-ignore-case t))
		 (setq message-nick-var 
		       (irchat-completing-default-read 
			"Private message to: "
			(append irchat-nick-alist irchat-channel-alist)
			'(lambda (s) t) nil irchat-privmsg-partner))
		 (list message-nick-var 
		       (read-string 
			(format "Private message to %s: " message-nick-var)))))
  (setq irchat-privmsg-partner message-nick-var)
  (irchat-send "PRIVMSG %s :%s" message-nick-var message)
  (irchat-own-message 
   (format (format "%s %%s" irchat-format-string) message-nick-var message)))


;; Added at mta@tut.fi's request...

(defun irchat-Command-mta-private ()
  "Send a private message (current line) to another user."
  (interactive)
  (let ((completion-ignore-case t) message start stop)
    (setq irchat-privmsg-partner
	  (irchat-completing-default-read 
	   "To whom: "
	   (append irchat-nick-alist irchat-channel-alist)
	   '(lambda (s) t) 
	   nil irchat-privmsg-partner))
    (beginning-of-line)
    (setq start (point))
    (end-of-line)
    (setq stop (point))
    (setq message (buffer-substring start stop))
    (next-line 1)
    (irchat-send "PRIVMSG %s :%s" irchat-privmsg-partner message)
    (irchat-own-message (format (format "%s %%s" irchat-format-string) 
				irchat-privmsg-partner message))))


(defun irchat-Command-names (&optional channel)
  "List the nicknames of the current IRC users on given channel.
With an Control-U as argument, only the current channel is listed.
With - as argument, list all channels."
  (interactive
   (if current-prefix-arg
       (if (eq current-prefix-arg '-)
	   (list current-prefix-arg)
	 nil)
     (list
      (let ((completion-ignore-case t))
	(completing-read 
	 "Names on channel: " 
	 irchat-channel-alist
	 '(lambda (s) t) nil nil)))))
  (if (not channel)
      (irchat-send "NAMES %s" irchat-current-channel)
    (if (eq channel '-)
	(irchat-send "NAMES")
      (irchat-send "NAMES %s" channel))))


(defun irchat-Command-nickname (nick)
  "Set your nickname."
  (interactive "sEnter your nickname: ")
  (setq irchat-old-nickname irchat-nickname)
  (setq irchat-nickname nick)
  (irchat-send "NICK %s" nick))


(defun irchat-Command-who (&optional expr)
  "Lists tue users that match the given expression.
If you enter only Control-U as argument, list the current channel.
With - as argument, list all users."
  (interactive 
   (if current-prefix-arg
       (if (eq current-prefix-arg '-)
	   (list current-prefix-arg)
	 nil)
     (list
      (let ((completion-ignore-case t))
	(completing-read 
	 "WHO expression: " 
	 irchat-channel-alist
	 '(lambda (s) t) nil nil)))))
  (if (not expr)
      (irchat-send "WHO %s" irchat-current-channel)
    (if (eq expr '-)
	(irchat-send "WHO")
      (irchat-send "WHO %s" expr))))


(defun irchat-Command-wait (nick &optional greeting)
  "Wait for NICK to enter IRC.  When this person appears, you will
be informed. If the optional argument GREETING is non-nil, it should 
be a string to send NICK upon entering."
  (interactive 
   (progn (setq nick (read-string "Wait for: ")
		greeting (read-string 
			  (format "Message to send %s upon entering: " nick)))
	  (if (string= greeting "")
	      (setq greeting nil))
	  (list nick greeting)))
  (put (intern nick) 'irchat-waited-for t)
  (if greeting 
      (put (intern nick) 'irchat-greeting greeting)))


(defun irchat-Command-finger (finger-nick-var)
  "Get information about a specific user."
  (interactive (let (finger-nick-var (completion-ignore-case t))
		 (setq finger-nick-var 
		       (completing-read 
			"Finger whom: " irchat-nick-alist
			'(lambda (s) t) nil nil))
		 (list finger-nick-var)))
  (irchat-send "WHOIS %s" finger-nick-var))


(defun irchat-Command-topic (topic)
  "Change topic of channel."
  (interactive "sTopic: ")
  (irchat-send "TOPIC %s :%s" irchat-current-channel topic))


(defun irchat-Command-invite (&optional invite-channel-var invite-nick-var)
  "Invite user to channel."
  (interactive 
   (list
    (if current-prefix-arg
	(let ((completion-ignore-case t))
	  (completing-read 
	   "Invite channel: "
	   (mapcar '(lambda (x)
		      (list x))
		   irchat-current-channels)
	   '(lambda (s) t) nil nil)
	  nil))
    (let ((completion-ignore-case t)) 
      (completing-read "Invite whom: " 
		       irchat-nick-alist
		       '(lambda (s) t) nil nil))))
  (if (not invite-channel-var)
      (setq invite-channel-var irchat-current-channel))
  (irchat-send "INVITE %s %s" invite-nick-var invite-channel-var))


(defun irchat-Command-away (awaymsg)
  "Mark/unmark yourself as being away."
  (interactive "sAway message: ")
  (irchat-send "AWAY :%s" awaymsg))


(defun irchat-Command-scroll-down ()
  "Scroll Dialogue-buffer down from Command-buffer."
  (interactive)
  (pop-to-buffer irchat-Dialogue-buffer)
  (if (pos-visible-in-window-p (point-min))
      (message "Beginning of buffer")
    (scroll-down))
  (pop-to-buffer irchat-Command-buffer))


(defun irchat-Command-scroll-up ()
  "Scroll Dialogue-buffer up from Command-buffer."
  (interactive)
  (pop-to-buffer irchat-Dialogue-buffer)
  (if (pos-visible-in-window-p (point-max))
      (progn
	(goto-char (point-max))
	(recenter 1))
    (scroll-up))
  (pop-to-buffer irchat-Command-buffer))


(defun irchat-Command-freeze ()
  "Toggle the automatic scrolling of the Dialogue window."
  (interactive)
  (if irchat-freeze
      (setq irchat-freeze-indicator "-")
    (setq irchat-freeze-indicator "F"))
  (switch-to-buffer (current-buffer))
  (setq irchat-freeze (not irchat-freeze)))


(defun irchat-Command-quit (&optional quit-msg)
  "Quit IRCHAT."
  (interactive "P")
  (if (or (not (irchat-server-opened))
	  quit-msg
	  (y-or-n-p "Quit IRCHAT? "))
      (progn
	(message "")
	(if (get-buffer-process irchat-server-buffer)
	    (if (and (irchat-server-opened)
		     quit-msg)
		(let ((quit-string (read-string "Signoff message: ")))
		  (irchat-send "QUIT :%s" quit-string))
	      (irchat-send "QUIT :%s" (or irchat-signoff-msg ""))))
	(irchat-clear-system)
	(if irchat-use-full-window
	    (delete-other-windows))
	(irchat-close-server)
	(run-hooks 'irchat-Exit-hook)
	(setq irchat-polling 'start)
	(setq irchat-current-channel nil)
	(setq irchat-current-channels nil))))


(defun irchat-Command-generic (message)
  "Enter a generic IRC message, which is sent to the server.
 A ? lists the useful generic messages."
  (interactive "sIRC Command: ")
  (if (string= message "?")
      (with-output-to-temp-buffer "*IRC Help*"
	(princ "The following generic IRC messages may be of interest to you:
TOPIC <new topic>		set the topic of your channel
INVITE <nickname>		invite another user to join your channel
LINKS				lists the currently reachable IRC servers
SUMMON <user@host>		invites an user not currently in IRC
USERS <host>			lists the users on a host
AWAY <reason>			marks you as not really actively using IRC
				(an empty reason clears it)
WALL <message>			send to everyone on IRC
NAMES <channel>			lists users per channel
")
	(message 
	 (substitute-command-keys 
	  "Type \\[irchat-Command-redisplay] to continue")))
    (irchat-send "%s" message)))


(defun irchat-Command-irc-compatible ()
  "If entered at column 0, allows you to enter a generic IRC message to
be sent to the server.  For a list of messages, see irchat-Command-generic."
  (interactive)
  (if (eq (current-column) 0)
      (call-interactively (function irchat-Command-generic))
    (self-insert-command 1)))


(defun irchat-Command-exec (command)
  "Execute command, stdout to dialogue."
  (interactive "sShell Command: ")
  (shell-command command t)
  (let ((opoint (point)))
    (while (< (point) (mark))
      (progn
	(irchat-Command-enter-message)
	(set-buffer irchat-Command-buffer)))
    (push-mark opoint t)))

;;;
;;; client-to-client queries
;;;
(defun irchat-Command-client-version (client-version-nick-var)
  "Ask about someones client version."
  (interactive (let (client-version-nick-var (completion-ignore-case t))
		 (setq client-version-nick-var 
		       (irchat-completing-default-read 
			"Whose client: " irchat-nick-alist
			'(lambda (s) t) nil irchat-query-client-nick))
		 (list client-version-nick-var)))
  (setq irchat-query-client-nick client-version-nick-var)
  (irchat-send "PRIVMSG %s :%s" 
	       client-version-nick-var irchat-query-client-version))


(defun irchat-Command-client-userinfo (client-userinfo-nick-var)
  "Ask about someones client userinfo."
  (interactive (let (client-userinfo-nick-var (completion-ignore-case t))
		 (setq client-userinfo-nick-var 
		       (irchat-completing-default-read 
			"Whose client: " irchat-nick-alist
			'(lambda (s) t) nil irchat-query-client-nick))
		 (list client-userinfo-nick-var)))
  (setq irchat-query-client-nick client-userinfo-nick-var)
  (irchat-send "PRIVMSG %s :%s"
	       client-userinfo-nick-var irchat-query-client-userinfo))


(defun irchat-Command-client-help (client-help-nick-var)
  "Ask about someones client help."
  (interactive (let (client-help-nick-var (completion-ignore-case t))
		 (setq client-help-nick-var 
		       (irchat-completing-default-read 
			"Whose client: " irchat-nick-alist
			'(lambda (s) t) nil irchat-query-client-nick))
		 (list client-help-nick-var)))
  (setq irchat-query-client-nick client-help-nick-var)
  (irchat-send "PRIVMSG %s :%s" 
	       client-help-nick-var irchat-query-client-help))


(defun irchat-Command-client-clientinfo (client-clientinfo-nick-var)
  "Ask about someones client clientinfo."
  (interactive (let (client-clientinfo-nick-var (completion-ignore-case t))
		 (setq client-clientinfo-nick-var 
		       (irchat-completing-default-read 
			"Whose client: " irchat-nick-alist
			'(lambda (s) t) nil irchat-query-client-nick))
		 (list client-clientinfo-nick-var)))
  (setq irchat-query-client-nick client-clientinfo-nick-var)
  (irchat-send "PRIVMSG %s :%s" 
	       client-clientinfo-nick-var irchat-query-client-clientinfo))


(defun irchat-Command-client-generic (client-generic-nick-var)
  "Ask about someones client clientinfo."
  (interactive (let (client-generic-nick-var (completion-ignore-case t))
		 (setq client-generic-nick-var 
		       (irchat-completing-default-read 
			"Whose client: " irchat-nick-alist
			'(lambda (s) t) nil irchat-query-client-nick))
		 (list client-generic-nick-var)))
  (setq irchat-query-client-nick client-generic-nick-var
	irchat-query-client-lastcommand
	(irchat-completing-default-read 
	 "What info: " 
	 irchat-query-client-alist '(lambda (s) t) nil 
	 irchat-query-client-lastcommand))
  (irchat-send "PRIVMSG %s :%s%s"
	       client-generic-nick-var
	       irchat-query-client-lastcommand
	       irchat-query-client-insert-to-generic))


(defun irchat-Command-client-userinfo-from-minibuffer ()
  "Ask about someones client clientinfo."
  (interactive)
  (setq irchat-client-userinfo
	(read-from-minibuffer "New userinfo: "
			      irchat-client-userinfo)))

(defun irchat-Command-client-userinfo-from-commandbuffer ()
  "Ask about someones client clientinfo."
  (interactive)
  (beginning-of-line)
  (setq start (point))
  (end-of-line)
  (setq stop (point))
  (setq irchat-client-userinfo (buffer-substring start stop))
  (next-line 1))

;;;
;;; sending files (any files actually)
;;;
(defun irchat-Command-send-file (name to-who)
  "Send a file to given  user"
  (interactive "fFile name: \nsTo who: ")
  (save-excursion 
    (set-buffer (get-buffer-create (format "*IRC S_FILE_%s*" name)))
    (delete-region (point-min) (point-max))
    (insert-file name)
    (let (str)
      (setq str (buffer-string))
      (delete-region (point-min) (point-max))
      (insert (irchat-quote-encode str)))
    (goto-char (point-min))
    (irchat-send "NOTICE %s :FILE START %s :%s" to-who name
		 (buffer-substring (point)
				   (min (point-max)
					(+ 80 (point)))))
    (goto-char (min (point-max) (+ 80 (point))))
    (while (< (point) (point-max))
      (progn
	(if (=  1 (mod (point) 800))
	    (sleep-for 1))
	(irchat-send "NOTICE %s :FILE CONT %s :%s" to-who name
		     (buffer-substring (point)
				       (min (point-max) (+ 80 (point)))))
	(goto-char (min (point-max) (+ 80 (point))))))
    (irchat-send "NOTICE %s :FILE END %s : " to-who name)
    (kill-buffer (get-buffer-create (format "*IRC S_FILE_%s*" name)))))


;;;
;;; send text in kill-buffer
;;;
(defun irchat-Command-yank-send (&optional howmany)
  (interactive)
  (let ((beg (point)) end)
    (insert (car kill-ring-yank-pointer))
    (setq end (point))
    (goto-char beg)
    (while (< (point) end)
      (progn
	(irchat-Command-enter-message)
	(set-buffer irchat-Command-buffer)))))

;;;
;;; send rot-13 encrypted data
;;;
(defun irchat-Command-caesar-line (&optional n)
  "*Caesar encrypt current line. Rotate optional N characters."
  (interactive)
  (beginning-of-line nil)
  (push-mark (point))
  (end-of-line)
  (gnus-caesar-region n))


;;;
;;;
;;;
(defun get-word-left ()
  "Return word left from point."
  (save-excursion
    (let (point-now)
      (setq point-now (point))
      (backward-word 1)
      (buffer-substring (point) point-now))))


(defun irchat-Command-complete ()
  "Complete word before point from userlist."
  (interactive)
  (insert
   (save-excursion
     (let ((completion-ignore-case t) point-now word result)
       (setq point-now (point)
	     word (get-word-left)
	     result (try-completion word irchat-nick-alist))
       (backward-word 1)
       (delete-region (point) point-now)
       (if (or (eq result t) (eq result nil))
           word
         result)))))


(defun irchat-Command-load-vars ()
  "Load configuration from irchat-variables-file."
  (interactive)
  (let ((file (expand-file-name irchat-variables-file)))
    (if (file-exists-p file)
	(progn
	  (load-file file)
	  (irchat-Command-reconfigure-windows)))))


(defun irchat-Command-reconfigure-windows ()
  (interactive)
  (let ((command-window (get-buffer-window irchat-Command-buffer))
	(dialogue-window (get-buffer-window irchat-Dialogue-buffer))
	(old-buffer (current-buffer)))
    (if (and command-window dialogue-window)
	(let ((c-height (window-height command-window))
	      (d-height (window-height dialogue-window)))
	  (delete-window command-window)
	  (pop-to-buffer irchat-Dialogue-buffer)
	  (enlarge-window (+ c-height d-height
			     (- (window-height dialogue-window)))))
      (pop-to-buffer irchat-Dialogue-buffer))
    (irchat-configure-windows)
    (if irchat-one-buffer-mode
	(pop-to-buffer irchat-Dialogue-buffer)
      (pop-to-buffer old-buffer))))

;;;
;;; command to get end of the Dialogue buffer
;;;
(defun irchat-Command-eod-buffer ()
  (interactive)
  (let ((saved-buffer (current-buffer)))
    (set-buffer irchat-Dialogue-buffer)
    (goto-char (point-max))
    (set-buffer saved-buffer)))

;;;
;;; commands to manage channel/conversation rings
;;;
(defun irchat-Command-private-conversation (arg)
  "Toggle between private conversation mode and channel mode. 
User can then join and part to a private conversation as he would 
join or part to a channel. 

If there are no private conversations or argument is given user is 
prompted the partner/channel (return as partner/channel means toggle 
mode, the current channel and current chat partner are not altered)"

  (interactive
   (list (if current-prefix-arg
       ;; prefixed, ask where to continue
       (if (eq irchat-command-buffer-mode 'chat)
	   (irchat-completing-default-read "Return to channel: "
					   (append irchat-channel-alist 
						   irchat-nick-alist) 
					   '(lambda (s) t) nil 
					   irchat-current-channel)
	 (completing-read "Start private conversation with: "
			  irchat-nick-alist '(lambda (s) t) nil))
     ;; no prefix, see if going to chat
     (if (eq irchat-command-buffer-mode 'channel)
	 ;; and if we have chat partner, select that
	 (if irchat-current-chat-partner
	     irchat-current-chat-partner
	   (completing-read "Start private conversation with: "
			    irchat-nick-alist '(lambda (s) t) nil)
	   )))))

  (progn
    (setq irchat-command-buffer-mode (if (eq irchat-command-buffer-mode 'chat)
					 'channel
				       'chat))
    (if arg
	(irchat-Command-join arg))
    (setq irchat-channel-indicator (if (eq irchat-command-buffer-mode 'chat)
				       (if irchat-current-chat-partner
					   (format "Chatting with %s" 
						   irchat-current-chat-partner)
					 "No partner")
				     (if irchat-current-channel
					 (format "Channel %s" 
						 irchat-current-channel)
				       "No channel")))
    ;; refresh mode line
    (set-buffer-modified-p (buffer-modified-p))))


(defun irchat-Command-push ()
  "Select next channel or chat partner."
  (interactive)
  (if (eq irchat-command-buffer-mode 'chat)
    (if irchat-current-chat-partners
	(let ((chat-partner (nth (1- (length irchat-current-chat-partners))
				 irchat-current-chat-partners)))
	  (if (string-list-ci-memberp chat-partner irchat-current-chat-partners)
	      (progn
		(setq irchat-current-chat-partner chat-partner
		      irchat-current-chat-partners
		      (cons chat-partner
			    (string-list-ci-delete 
			     chat-partner
			     irchat-current-chat-partners)))
		(setq irchat-channel-indicator
		      (if irchat-current-chat-partner
			  (format "Chatting with %s" 
				  irchat-current-chat-partner)
			"No partner"))))
	  (set-buffer-modified-p (buffer-modified-p))))
    (if irchat-current-channels
	(let ((channel (nth (1- (length irchat-current-channels))
			    irchat-current-channels)))
	  (if (string-list-ci-memberp channel irchat-current-channels)
	      (progn
		(setq irchat-current-channel channel
		      irchat-current-channels
		      (cons channel
			    (string-list-ci-delete channel 
						   irchat-current-channels)))
		(setq irchat-channel-indicator
		      (if irchat-current-channel
			  (format "Channel %s" irchat-current-channel)
			"No channel"))))
	  (set-buffer-modified-p (buffer-modified-p))))))


(defun irchat-Command-pop ()
  "Select previous channel or chat partner."
  (interactive)
  (if (eq irchat-command-buffer-mode 'chat)
      (let ((chat-partner irchat-current-chat-partner))
	(progn
	  (setq irchat-current-chat-partners (append
					      (string-list-ci-delete 
					       chat-partner 
					       irchat-current-chat-partners)
					      (list chat-partner))
		irchat-current-chat-partner (car irchat-current-chat-partners)
		irchat-channel-indicator 
		(if irchat-current-chat-partner
		    (format "Chatting with %s" 
			    irchat-current-chat-partner)
		  "No partner"))
	  (set-buffer-modified-p (buffer-modified-p))))

    (let ((channel irchat-current-channel))
      (progn
	(setq irchat-current-channels (append 
				       (string-list-ci-delete 
					channel 
					irchat-current-channels)
				       (list channel))
	      irchat-current-channel (car irchat-current-channels)
	      irchat-channel-indicator (format "Channel %s" 
					       irchat-current-channel))
	(set-buffer-modified-p (buffer-modified-p))))))

;;;
;;; Cannot use completing read, user may want to query many names
;;;
(defun irchat-Command-ison (nick)
  "IsON user."
  (interactive "sIsON: ")
  (irchat-send "ISON %s" nick))


(defun irchat-Command-userhost (nick)
  "Ask for userhost."
  (interactive "sUserhost nick(s): ")
  (irchat-send "USERHOST %s" nick))


;;;
;;; dig last kill from KILLS and show it
;;;
(defun irchat-Command-show-last-kill ()
  (interactive)
  (save-excursion
    (let ((buf (current-buffer))
	  str)
      (set-buffer irchat-KILLS-buffer)
      (goto-char (point-max))
      (forward-line -1)
      (setq str (buffer-substring (point) (point-max)))
      (goto-char (point-max))
      (set-buffer irchat-Dialogue-buffer)
      (goto-char (point-max))
      (setq buffer-read-only nil)
      (insert str)
      (goto-char (point-max))
      (setq buffer-read-only t)
      (set-window-point (get-buffer-window irchat-Dialogue-buffer)
			(point-max))
      (set-buffer buf))))

;;;
;;; eof
;;;
