# OpenVerse Text Chat Module
# 
# This module contains all the functions needed for the
# text chat window.
#
# Module Name		- Text Chat Module
# Current Maintainter 	- Cruise <cruise@openverse.org>
# Sourced By		- InitMainWindow
#
# Copyright (C) 1999 David Gale <cruise@openverse.org>
# For more information visit http://OpenVerse.org/
#
# Updated: 2/24/2000  Jack <jack@openverse.org>
#	   Command (no push) and Quit buttons were added.
#	   Thanks in part to John Doe.
#	   
# Updated: 2/25/2000 Jack <jack@openverse.org>
#	   Added Bubbles to the buttons.	
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
# USA.

# NOTE: 
# Now using string compare for increased performance
# Now using curley braces around functions for greater speed

#
# Images we will use in this module.
#
image create photo OpenVerse_Image_SCRLK -file "$MV(icondir)/locked.gif"
image create photo OpenVerse_Image_SCRULK -file "$MV(icondir)/unlocked.gif"
image create photo OpenVerse_Image_LOG -file "$MV(icondir)/log.gif"
image create photo OpenVerse_Image_RUBBER -file "$MV(icondir)/rubber.gif"
#
# Images for the hide-away toolbar in the Chat Window.
#
image create bitmap OpenVerse_Image_vhandle -file "$MV(icondir)/vhandle.xbm" -maskfile "$MV(icondir)/vhandle.mask" -background gray90
image create bitmap OpenVerse_Image_hhandle -file "$MV(icondir)/hhandle.xbm" -maskfile "$MV(icondir)/hhandle.mask" -background gray90

#
# Turns the text chat window on or off.
# When turning on, it fills it with the last bunch of lines.
#
proc ToggleText {} {
	global MV

	set MV(TCCommand) 0
	if $MV(textwindow) {
		destroy .chat
		set MV(textwindow) 0
	} else {
		set MV(textwindow) 1
		toplevel .chat
		wm title .chat [Trns openverse_text_chat]
		wm geometry .chat 646x149 

		frame .chat.chat
		frame .chat.bottom -relief sunken -borderwidth 2
		text .chat.chat.text -height 1 -width 0  -relief raised \
			-borderwidth 2 -yscrollcommand ".chat.chat.scrolly set" \
			-spacing1 1 -wrap word -state disabled
		scrollbar .chat.chat.scrolly -command ".chat.chat.text yview"

		# Added activeforeground red -JACK-
		button .chat.bottom.send -text [Trns send] -activeforeground red \
			-command {SendFromWindow}
		
		frame .chat.bottom.buttons
		label .chat.bottom.buttons.handle -image OpenVerse_Image_vhandle -relief \
			raised -bd 1
		update idletasks
		frame .chat.bottom.buttons.frame -relief raised -bd 1
                pack propagate .chat.bottom.buttons.frame 0
		pack .chat.bottom.buttons.handle -side left -fill y
		pack .chat.bottom.buttons.frame .chat.bottom.buttons -fill both -expand 1
		bind .chat.bottom.buttons.handle <ButtonRelease-1> "ChtButShowHide"
		set MV(ChtButState) show
		set bframe ".chat.bottom.buttons.frame"
		# "$bframe" is all over the place do a search to see where.
		#################################################################
		
		entry .chat.bottom.chat
                button .chat.bottom.rubber -image OpenVerse_Image_RUBBER -command EraseChat
                if $MV(log) {
                        button .chat.bottom.log -image OpenVerse_Image_LOG -command LogTog \
                                -bg red -activebackground pink
                } else {
                        button .chat.bottom.log -image OpenVerse_Image_LOG -command LogTog \
                                -bg $MV(defbg) -activebackground $MV(defhl)
                }
                if $MV(textwindow.lock) {
                        button .chat.bottom.scrlk -image OpenVerse_Image_SCRLK -command ToggleChatLock
                } else {
                        button .chat.bottom.scrlk -image OpenVerse_Image_SCRULK -command ToggleChatLock
                }

                ###############################################################
		# Added command buttons; moved bottom ones to $bframe. -JACK-
		#  ? Maybe could toggle, but too much code?
		label $bframe.label -text [Trns commands]
		
		# Depends upon text entered...
		# Order: wink, smile, frown, idea, love, sing, steam
		button $bframe.1 -image OpenVerse_Image_CHAT_wink \
		   	-command {SetSCHATcmd 1} -width 20 -height 20
		button $bframe.2 -image OpenVerse_Image_CHAT_smile \
			-command {SetSCHATcmd 2} -width 20 -height 20
		button $bframe.3 -image OpenVerse_Image_CHAT_frown \
			-command {SetSCHATcmd 3} -width 20 -height 20
		button $bframe.4 -image OpenVerse_Image_CHAT_idea \
			-command {SetSCHATcmd 4} -width 20 -height 20
		button $bframe.5 -image OpenVerse_Image_CHAT_love \
			-command {SetSCHATcmd 5} -width 20 -height 20
		button $bframe.6 -image OpenVerse_Image_CHAT_notes \
			-command {SetSCHATcmd 6} -width 20 -height 20
		button $bframe.7 -image OpenVerse_Image_CHAT_steam \
			-command {SetSCHATcmd 7} -width 20 -height 20
		
		button $bframe.jump -image OpenVerse_Image_CHAT_jump \
			-command { SendToServer "EFFECT jump"} -width 20 -height 20
		button $bframe.shiver -image OpenVerse_Image_CHAT_shiver \
			-command { SendToServer "EFFECT shiver"} -width 20 -height 20
		button $bframe.quit -text [Trns close] -width 20 -height 20 \
			-command {destroy .chat}
		button $bframe.quit_ov -image OpenVerse_Image_CHAT_quit \
			-command { 
				if ![tk_dialog .chat.quitQuestion [Trns really_quit] \
				[Trns quit_question] \
				"" 1 [Trns quit] [Trns cancel]] {
					exit
				}
			}
		# 11/05/2001 -Unununium- Moved the quit button away from the others
		pack $bframe.label \
		 	$bframe.1 $bframe.2 $bframe.3 $bframe.4 $bframe.5 \
			$bframe.6 $bframe.7 $bframe.jump $bframe.shiver \
			$bframe.quit -side left -fill both -padx 1
		pack $bframe.quit_ov -fill both -side right
		###############################################################
		# 2/25/2000 -JACK- 
		# Added Bubbles to the command buttons
		if $MV(tooltips) {
			Bubble::initBubble $bframe.jump [Trns cht_jump_bubble]
			Bubble::initBubble $bframe.shiver [Trns cht_shiver_bubble]
			Bubble::initBubble $bframe.quit [Trns cht_close_bubble]
			Bubble::initBubble $bframe.quit_ov [Trns cht_quit_bubble]
			Bubble::initBubble $bframe.1 [Trns cht_wink_bubble]
			Bubble::initBubble $bframe.2 [Trns cht_smile_bubble]
			Bubble::initBubble $bframe.3 [Trns cht_frown_bubble]
			Bubble::initBubble $bframe.4 [Trns cht_idea_bubble]
			Bubble::initBubble $bframe.5 [Trns cht_love_bubble]
			Bubble::initBubble $bframe.6 [Trns cht_sing_bubble]
			Bubble::initBubble $bframe.7 [Trns cht_steam_bubble]
		}	
		pack .chat.chat -fill both -expand y
		pack .chat.chat.text -side left -fill both -expand y
		pack .chat.chat.scrolly -side left -fill y 
		pack .chat.bottom -fill x -expand n
		pack .chat.bottom.buttons -side top
		pack .chat.bottom.send -side left -expand n
		pack .chat.bottom.chat -side left -fill x -expand y
		pack .chat.bottom.log .chat.bottom.rubber \
			.chat.bottom.scrlk -side left

		focus .chat.bottom.chat
		QuickKeys ".chat"
		bind .chat <Return> SendFromWindow
		bind .chat <Destroy> "set MV(textwindow) 0"
		bind .chat <Pause> "ToggleChatLock"
		bind .chat <Up> "ShowPrev .chat.bottom.chat"
		bind .chat <Down> "ShowNext .chat.bottom.chat"
		bind .chat <Control-k> ".chat.bottom.chat insert end \x03"
		# These next binds enable cut and 
		# paste for Windows users. (BUG FIX, DG)
		bind .chat <Control-c> {}
		bind .chat <Control-v> {}
		bind .chat <KeyRelease> {focus .chat.bottom.chat}
		bind .chat.chat.text <ButtonPress> {.chat.chat.text configure -state normal}
		bind .chat.chat.text <ButtonRelease> {.chat.chat.text configure -state disabled}
		set hp [llength $MV(chats)]
		for {set c 0} {$c < $hp} {incr c} {
			InsertIntoChat 0 [lindex $MV(chats) $c]
		}
		# Colors (damn, why did I do this)
		#	1=Black
		#	2=Navy Blue
		#	3=Dark Green 
		#	4=Bright Red 
		#	5=Brown
		#	6=Magenta 
		#	7=Orange 
		#	8=Yellow 
		#	9=Bright Green
		#	10=Bluish-Green 
		#	11=Cyan 
		#	12=Blue
		#	13=Hot Pink 
		#	14=Dark Grey 
		#	15=Light Gray 
		#	0,16=White
		#	99=normal
		#
		set w .chat.chat.text
		$w tag configure B
		$w tag configure F
		$w tag configure B99
		$w tag configure F99
		$w tag configure F0 -foreground white
		$w tag configure F1 -foreground black
		$w tag configure F2 -foreground "navy blue"
		$w tag configure F3 -foreground "dark green"
		$w tag configure F4 -foreground "red"
		$w tag configure F5 -foreground "brown"
		$w tag configure F6 -foreground "magenta"
		$w tag configure F7 -foreground "orange"
		$w tag configure F8 -foreground "yellow"
		$w tag configure F9 -foreground "green"
		$w tag configure F00 -foreground white
		$w tag configure F01 -foreground black
		$w tag configure F02 -foreground "navy blue"
		$w tag configure F03 -foreground "dark green"
		$w tag configure F04 -foreground "red"
		$w tag configure F05 -foreground "brown"
		$w tag configure F06 -foreground "magenta"
		$w tag configure F07 -foreground "orange"
		$w tag configure F08 -foreground "yellow"
		$w tag configure F09 -foreground "green"
		$w tag configure F10 -foreground "#008080"
		$w tag configure F11 -foreground "cyan"
		$w tag configure F12 -foreground "blue"
		$w tag configure F13 -foreground "hot pink"
		$w tag configure F14 -foreground "dark grey"
		$w tag configure F15 -foreground "light grey"
		$w tag configure F16 -foreground "white"
		$w tag configure B0 -background white
		$w tag configure B1 -background black
		$w tag configure B2 -background "navy blue"
		$w tag configure B3 -background "dark green"
		$w tag configure B4 -background "red"
		$w tag configure B5 -background "brown"
		$w tag configure B6 -background "magenta"
		$w tag configure B7 -background "orange"
		$w tag configure B8 -background "yellow"
		$w tag configure B9 -background "green"
		$w tag configure B00 -background white
		$w tag configure B01 -background black
		$w tag configure B02 -background "navy blue"
		$w tag configure B03 -background "dark green"
		$w tag configure B04 -background "red"
		$w tag configure B05 -background "brown"
		$w tag configure B06 -background "magenta"
		$w tag configure B07 -background "orange"
		$w tag configure B08 -background "yellow"
		$w tag configure B09 -background "green"
		$w tag configure B10 -background "#008080"
		$w tag configure B11 -background "cyan"
		$w tag configure B12 -background "blue"
		$w tag configure B13 -background "hot pink"
		$w tag configure B14 -background "dark grey"
		$w tag configure B15 -background "light grey"
		$w tag configure B16 -background "white"
	}
}

proc LogTog {} {
	global MV

	if $MV(log) {
		.chat.bottom.log configure -bg $MV(defbg) -activebackground $MV(defhl)
		StopLog
	} else {
		.chat.bottom.log configure -bg red -activebackground pink
		StartLog
	}
}

proc ChtButShowHide {} {
	global MV
	switch $MV(ChtButState) {
		show {
			pack forget .chat.bottom.buttons.frame
			.chat.bottom.buttons.handle configure -image OpenVerse_Image_hhandle
			set MV(ChtButState) hide
			return
		}
		hide {
			.chat.bottom.buttons.handle configure -image OpenVerse_Image_vhandle
			pack .chat.bottom.buttons.frame -fill both -expand 1
			set MV(ChtButState) show
			return
		}
	}
}

#
# Toggles the background color on emotion buttons.
#
# 11/05/2001 -Unununium- Fixed button background colors
#
proc SetSCHATcmd {idx} {
	global MV

	set MV(TCCommand) 0
	for {set c 1} {$c < 8} {incr c} {
		if {$idx == $c && [string compare [.chat.bottom.buttons.frame.$idx cget -bg] "red"]} {
			.chat.bottom.buttons.frame.$idx configure -bg red -activebackground pink
			set MV(TCCommand) $idx
		} else {
			.chat.bottom.buttons.frame.$c configure -bg $MV(defbg) -activebackground $MV(defhl)
		}
	}
}
#
# Sends text from the chat window.
# TODO: Use a more generic base function for this.
#       make this a wrapper to it.
#
proc SendFromWindow {} {
	global MV

	set getChat "[.chat.bottom.chat get]"	;# JACK
	
	###################################################
	# Do a little switch-a-roo, from command buttons
	# Order: wink, smile, frown, idea, love, sing, steam.
	switch $MV(TCCommand) {
		1 {	set MV(TCCommand) ""
			set stuff "/wink $getChat"}
		2 { 	set MV(TCCommand) ""
			set stuff "/smile $getChat"}
		3 {	set MV(TCCommand) ""
			set stuff "/frown $getChat"}
		4 {     set MV(TCCommand) ""
			set stuff "/idea $getChat"}
		5 {	set MV(TCCommand) ""
			set stuff "/love $getChat"}
		6 {	set MV(TCCommand) ""
			set stuff "/sing $getChat"}
		7 {	set MV(TCCommand) ""
			set stuff "/steam $getChat"}
		default { set stuff $getChat}
	}
	.chat.bottom.chat delete 0 end	
	SetSCHATcmd 0
	lappend MV(prev) $stuff
	if {[llength $MV(prev)] > $MV(prevsave)} {
		set MV(prev) [lreplace $MV(prev) 0 0]
	}
	set MV(curprev) -1

	#
        # Process Plugins!
        #
        foreach plugin $MV(plugin.traps.SendText) {
                if ![$MV(plugin.traps.SendText.$plugin) $stuff] {return}
        }

	
	if {[string range $stuff 0 0] == "/"} {
		ProcessCommand $stuff
	} else {
		if $MV(rot13) {set stuff [Rot13 $stuff]}
		SendToServer "CHAT $stuff"
	}
	
	
}

#
# Toggles the scroll lock on the text chat window
#
proc ToggleChatLock {} {
	global MV

	if $MV(textwindow.lock) {
		set MV(textwindow.lock) 0
		.chat.bottom.scrlk configure -image OpenVerse_Image_SCRULK
	} else {
		set MV(textwindow.lock) 1
		.chat.bottom.scrlk configure -image OpenVerse_Image_SCRLK
	}
}


#
# CRUISE - 11/04/2001 - Fixed a problem which would display multiple lines when
# users had color codes with no numbers. EW
#
proc InsertIntoChat {log what} {
	global MV

	set text $what
	set color 0
	set newtext ""
	set FG ""
	set BG ""
	if {$MV(timestamp) && [winfo exists .chat]} {
		.chat.chat.text conf -state normal
		.chat.chat.text insert end "\[[clock format [clock seconds] -format "%T"]\] "
	}
	while {[set tb [string first \x03 $text]] != -1} {
		#
		# Fixes problem with color code without a numeric.
		#
		if {[TestPosNum [string range $text [expr $tb +1] [expr $tb +1]]]} {
			# We need to ignore this color code because it has not number to go with it
			set string [string range $text 0 [expr $tb -1]]
			set text [string range $text [expr $tb +1] end]
			if {[winfo exists .chat.chat]} {
				.chat.chat.text conf -state normal
				.chat.chat.text insert end $string
				if !$MV(textwindow.lock) {.chat.chat.text see end}
			}
			continue
		}
		set string [string range $text 0 [expr $tb -1]]
		set text [string range $text [expr $tb +1] end]
		if {[regexp {^([0-9][0-9]?)(,([0-9][0-9]?))?(.*)} $text m fg bl bg text]} {
			if {[winfo exists .chat.chat]} {
				.chat.chat.text conf -state normal
				.chat.chat.text insert end $string "$FG $BG"
				set FG "F$fg"
				set BG "B$bg"
				if !$MV(textwindow.lock) {.chat.chat.text see end}
			}
			set color 1
		} else {
			if {[winfo exists .chat.chat]} {
				.chat.chat.text conf -state normal
				.chat.chat.text insert end $string "$FG $BG"
				if !$MV(textwindow.lock) {.chat.chat.text see end}
			}
		}
		append newtext $text
	}
	if { $color && [winfo exists .chat.chat] } {
		set parms [split $text \n]
		.chat.chat.text conf -state normal
		.chat.chat.text insert end [lindex $parms 0] "$FG $BG"
		.chat.chat.text insert end "\n"
		if !$MV(textwindow.lock) {.chat.chat.text see end}
	}
	if {![string compare $newtext ""]} {set newtext $text}
	if {[winfo exists .chat.chat.text] && !$color} {
		.chat.chat.text conf -state normal
		.chat.chat.text insert end $newtext
		if !$MV(textwindow.lock) {.chat.chat.text see end}
	}
	if {[winfo exists .chat.chat.text]} {
		.chat.chat.text conf -state disabled
	}
	if $log {
		lappend MV(chats) "$what"
		if {[llength $MV(chats)] > $MV(chatsave)} {
			set MV(chats) [lreplace $MV(chats) 0 0]
		}
	}
	if {$MV(log)} {
		LogThis "$newtext"
	}
}

proc RotTextChat {} {
	global MV
	EraseChat
	set hp [llength $MV(chats)]
	for {set c 0} {$c < $hp} {incr c} {
		set stuff [lindex $MV(chats) $c]
		set chat [string range $stuff 0 [expr [string first " " $stuff] -1]]
		append chat [Rot13 [string range $stuff [string first " " $stuff] end]]
		InsertIntoChat 0 $chat
	}
}

#
# Modified by PJ7 to work correctly not that the state of the window is
# disabled to prevent it from taking focus during cut-n-paste.
#
proc EraseChat {} {
	if {![winfo exists .chat.chat.text]} {return}
	.chat.chat.text conf -state normal
	.chat.chat.text delete 0.0 end
	.chat.chat.text see end
	.chat.chat.text conf -state disabled
}

