uplevel #0 [list source [file join [file dirname [info script]] svgrender.tcl]]

package require msgcat

::msgcat::mcload [file join [file dirname [info script]] msgs]

namespace eval wb {
    set id_base [pid]	;# used in proc create_id
}

proc wb::add_whiteboard_menu_item {m connid jid} {
    $m add command -label [::msgcat::mc "Whiteboard"] \
	-command [list [namespace current]::open_wb $connid $jid -raise 1]
}

hook::add chat_create_user_menu_hook \
    [namespace current]::wb::add_whiteboard_menu_item 47
hook::add chat_create_conference_menu_hook \
    [namespace current]::wb::add_whiteboard_menu_item 47
hook::add roster_jid_popup_menu_hook \
    [namespace current]::wb::add_whiteboard_menu_item 47

proc wb::open_wb {connid jid args} {
    global dofill

    set raise 0
    foreach {key val} $args {
	switch -- $key {
	    -raise { set raise $val }
	}
    }

    set chatid [chat::chatid $connid $jid]

    set w [win_id whiteboard $chatid]
    if {[winfo exists $w]} {
    	if {$raise} {
    	    raise_win $w
    	}
	return
    }

    set jid [chat::get_jid $chatid]

    set title [format [::msgcat::mc "%s whiteboard"] $jid]
    add_win $w -title $title -tabtitle $title \
	-class Whiteboard -raise $raise


    set sw [ScrolledWindow $w.sw]
    pack $sw -side right -fill both -expand yes
    set c [canvas $w.c -background white]
    $sw setwidget $c
    #pack $c -side right -fill both -expand yes

    bindscroll $c

    set tb [frame $w.tb]
    pack $tb -side left -fill y

    set tbpolyline [radiobutton $w.tb.line -text [::msgcat::mc "PolyLine"] \
			-variable [namespace current]::tool($chatid) \
			-value polyline \
			-command [list [namespace current]::line_bind $c $chatid]]
    
    set tbfreehand [radiobutton $w.tb.freehand -text [::msgcat::mc "FreeHand"] \
			-variable [namespace current]::tool($chatid) \
			-value freehand \
			-command [list [namespace current]::freehand_bind \
				      $c $chatid]]

    set tbcircle [radiobutton $w.tb.circle -text [::msgcat::mc "Circle"] \
			-variable [namespace current]::tool($chatid) \
			-value circle \
			-command [list [namespace current]::circle_bind \
				      $c $chatid]]

    set tbpolygon [radiobutton $w.tb.polygon -text [::msgcat::mc "Polygon"] \
			-variable [namespace current]::tool($chatid) \
			-value polygon \
			-command [list [namespace current]::polygon_bind \
				      $c $chatid]]

    set tbtext [radiobutton $w.tb.text -text [::msgcat::mc "Text"] \
		      -variable [namespace current]::tool($chatid) \
		      -value text \
		      -command [list [namespace current]::text_bind \
				    $c $chatid]]

    set tbmove [radiobutton $w.tb.move -text [::msgcat::mc "Move"] \
		    -variable [namespace current]::tool($chatid) \
		    -value move \
		    -command [list [namespace current]::move_bind \
				  $c $chatid]]

    set tbremove [radiobutton $w.tb.remove -text [::msgcat::mc "Remove"] \
		      -variable [namespace current]::tool($chatid) \
		      -value remove \
		      -command [list [namespace current]::remove_bind \
				    $c $chatid]]

    pack $tbpolyline $tbfreehand $tbcircle $tbpolygon $tbtext $tbmove $tbremove \
	 -anchor w

    button $w.tb.clear -text [::msgcat::mc "Clear"] \
	-command [list [namespace current]::send_clear $chatid]
    pack $w.tb.clear -side bottom -anchor w -fill x

    button $w.tb.save -text [::msgcat::mc "Save..."] \
	-command [list [namespace current]::save_wb $chatid]
    pack $w.tb.save -side bottom -anchor w -fill x

    #frame $w.tb.spacer1 -relief sunken -bd 1 -height 2 -highlightthickness 0
    #pack $w.tb.spacer1 -side bottom -anchor w -fill x -pady 1m

    set [namespace current]::text_set_fr($chatid) $w.tb
    label $w.tb.example_char -text A
    pack $w.tb.example_char -side bottom -fill x

    button $w.tb.seltextcol -text [::msgcat::mc "Text color"] \
	-command [list [namespace current]::select_text_color \
		      $w.tb.seltextcol $w.tb.example_char]
    pack $w.tb.seltextcol -side bottom -anchor w -fill x

    button $w.tb.selfont -text [::msgcat::mc "Text font"] \
	-command [list [namespace current]::select_font \
		      $w.tb.selfont $w.tb.example_char]
    pack $w.tb.selfont -side bottom -anchor w -fill x

    #frame $w.tb.spacer2 -relief sunken -bd 1 -height 2 -highlightthickness 0
    #pack $w.tb.spacer2 -side bottom -anchor w -fill x -pady 1m

    frame $w.tb.fill

    checkbutton $w.tb.dofill -text [::msgcat::mc "Fill"] -variable dofill
    pack $w.tb.dofill -side left -in $w.tb.fill

    canvas $w.tb.fillcolor -background \#FFFFFF -height 5m -width 5m
    pack $w.tb.fillcolor -side left -padx 3m -in $w.tb.fill

    pack $w.tb.fill -side bottom -anchor w -fill x

    button $w.tb.selfillcol -text [::msgcat::mc "Fill color"] \
	-command [list [namespace current]::select_color \
		      $w.tb.selfillcol $w.tb.fillcolor]
    pack $w.tb.selfillcol -side bottom -anchor w -fill x

    #frame $w.tb.spacer3 -relief sunken -bd 1 -height 2 -highlightthickness 0
    #pack $w.tb.spacer3 -side bottom -anchor w -fill x -pady 1m

    canvas $w.tb.color -background \#000000 -height 0.5c -width 1
    pack $w.tb.color -side bottom

    frame $w.tb.linewidth

    label $w.tb.lwidth -text [::msgcat::mc "Line width: "]
    pack $w.tb.lwidth -side left -in $w.tb.linewidth

    SpinBox $w.tb.width -width 4 -range {1 100} \
	-textvariable [namespace current]::width($chatid)
    pack $w.tb.width -side left -in $w.tb.linewidth

    pack $w.tb.linewidth -side bottom -anchor w -fill x

    button $w.tb.selcol -text [::msgcat::mc "Line color"] \
	-command [list [namespace current]::select_color \
		      $w.tb.selcol $w.tb.color]
    pack $w.tb.selcol -side bottom -anchor w -fill x

    variable balloon
    set balloon($chatid) 1
    checkbutton $w.tb.balloon -text [::msgcat::mc "Show balloons"] \
			      -variable [namespace current]::balloon($chatid)
    pack $w.tb.balloon -side bottom -anchor w -fill x


    $c bind all <Any-Enter>  \
	[list [namespace current]::balloon $chatid $c enter  %X %Y]
    $c bind all <Any-Motion> \
	[list [namespace current]::balloon $chatid $c motion %X %Y]
    $c bind all <Any-Leave>  \
	[list [namespace current]::balloon $chatid $c leave  %X %Y]

    trace variable [namespace current]::width($chatid) w \
	[list [namespace current]::change_width \
	     $w.tb.color [namespace current]::width($chatid)]

    variable tool
    set tool($chatid) polyline
    line_bind $c $chatid
}

proc wb::balloon {chatid c action X Y} {
    variable balloon

    if {!$balloon($chatid)} return

    set id [$c find withtag current]
    set tags {}
    foreach t [$c gettags $id] {
	if {[llength $t] == 2} {
	    lappend tags $t
	}
    }

    set msgs {}
    foreach t [lsort -index 0 -integer $tags] {
	lappend msgs [lindex $t 1]
    }

    balloon::default_balloon $c:$id $action $X $Y -text [join $msgs "\n"]
}

proc wb::select_color {but col} {
    set color [SelectColor::menu $col.color [list below $but] \
		   -color [$col cget -background]]

    if {[string length $color]} {
        $col configure -background $color
    }
}

proc wb::select_font {chatid col} {
    variable app_font
    set font_desc [SelectFont .s -type dialog]

    if {[string length $font_desc] == 0} return

    if {![info exists app_font($font_desc)]} {
        set app_font($font_desc) \
	    [eval font create [list $font_desc] [font actual $font_desc]]
    }
    $col configure -font $app_font($font_desc)
}

proc wb::select_text_color {but col} {
    set color [SelectColor::menu $col.color [list below $but] \
		   -color [$col cget -foreground]]

    if {[string length $color]} {
        $col configure -foreground $color
    }
}

proc wb::get_text_color {chatid} {
    [set [namespace current]::text_set_fr($chatid)].example_char cget -foreground
}

proc wb::get_text_font {chatid} {
    [set [namespace current]::text_set_fr($chatid)].example_char cget -font
}

proc wb::get_fill_color {chatid} {
    set w [win_id whiteboard $chatid]
    $w.tb.fillcolor cget -background
}

proc wb::get_color {chatid} {
    set w [win_id whiteboard $chatid]
    $w.tb.color cget -background
}

proc wb::change_width {col widthvar args} {
    set width [set $widthvar]
    $col configure -width $width
}

proc wb::get_width {chatid} {
    set w [win_id whiteboard $chatid]
    $w.tb.color cget -width
}

proc wb::save_wb {chatid} {
    set w [win_id whiteboard $chatid]

    set filepath [tk_getSaveFile -defaultextension .eps \
				 -filetypes {{{Encapsulated PostScript files} *.eps}
					     {{All files}        *}}]

    if {$filepath == ""} return
    $w.c postscript -file $filepath
}

###############################################################################

proc wb::create_id {} {
    # Unseeded random number is not good enough, because remote clients
    # are likely to produce the same numbers.
    return [rand 10000][clock seconds][set [namespace current]::id_base]
}

proc wb::send_svg {chatid tag} {
    if {[chat::is_groupchat $chatid]} {
	set type groupchat
    } else {
	set type chat
    }
    set connid [chat::get_connid $chatid]
    set jid [chat::get_jid $chatid]
    jlib::send_msg $jid \
	-connection $connid \
	-type $type \
	-xlist [list [jlib::wrapper:createtag x \
			  -vars {xmlns tkabber:whiteboard} \
			  -subtags [list [jlib::wrapper:createtag svg \
					      -subtags [list $tag]]]]]
}

proc wb::send_clear {chatid} {
    if {[chat::is_groupchat $chatid]} {
	set type groupchat
    } else {
	set type chat
        [win_id whiteboard $chatid].c delete all
    }
    set connid [chat::get_connid $chatid]
    set jid [chat::get_jid $chatid]
    jlib::send_msg $jid -type $type \
	-connection $connid \
	-xlist [list [jlib::wrapper:createtag x \
			  -vars {xmlns tkabber:whiteboard} \
			  -subtags [list [jlib::wrapper:createtag clear]]]]
}

proc wb::handle_wb {chatid from type body x} {
    set seconds [jlib::x_delay $x]

    foreach xelem $x {
	jlib::wrapper:splitxml $xelem tag vars isempty chdata children
	
	if {[cequal [jlib::wrapper:getattr $vars xmlns] tkabber:whiteboard]} {
	    open_wb [chat::get_connid $chatid] [chat::get_jid $chatid]
	    set w [win_id whiteboard $chatid]
	    foreach child $children {
		parse_item $chatid $from $seconds $child
	    }
	    tab_set_updated $w 1 message

	    $w.c configure -scrollregion [$w.c bbox all]
	}
    }
}
hook::add draw_message_hook [namespace current]::wb::handle_wb 1

proc wb::parse_item {chatid from seconds item} {
    set w [win_id whiteboard $chatid]
    jlib::wrapper:splitxml $item tag vars isempty chdata children

    switch -- $tag {
	svg {
	    foreach child $children {
		set id [svg::parse_svg_item $w.c $child]
		if {$id != ""} {
		    $w.c addtag [time_tag created $from $seconds] withtag $id
		}
	    }
	}
	move {
	    set id [jlib::wrapper:getattr $vars id]
	    set dx [jlib::wrapper:getattr $vars dx]
	    set dy [jlib::wrapper:getattr $vars dy]
	    if {![string is double $dx] || $dx == ""} {set dx 0}
	    if {![string is double $dy] || $dy == ""} {set dy 0}
	    $w.c addtag [time_tag moved $from $seconds] withtag id$id
	    $w.c move id$id $dx $dy
	}
	remove {
	    $w.c delete "id[jlib::wrapper:getattr $vars id]"
	}
	clear {
	    $w.c delete all
	}
    }
}

###############################################################################

proc wb::time_tag {type jid {seconds ""}} {
    set seconds_now [clock seconds]
    set format $::plugins::options(timestamp_format)

    set seconds_day_before [clock scan "-23 hours 59 minutes" -base $seconds_now]
    if {$seconds == ""} {
	set seconds $seconds_now
    }
    if {$seconds <= $seconds_day_before} {
	set format $::plugins::options(delayed_timestamp_format)
    }
    set time [clock format $seconds -format $format]
    switch -- $type {
	created {
	    return [list $seconds [::msgcat::mc "%s created: %s" $time $jid]]
	}
	moved {
	    return [list $seconds [::msgcat::mc "%s moved: %s" $time $jid]]
	}
	default {
	    return ""
	}
    }
}

###############################################################################
# Line

proc wb::line_bind {c jid} {
    bind $c <ButtonPress-1> \
	[list [namespace current]::line_b1 [double% $c] [double% $jid] %x %y]
    bind $c <B1-Motion> {}
    bind $c <Motion> [list [namespace current]::line_b1m [double% $c] %x %y]
    bind $c <ButtonRelease-1> {}
    bind $c <Button-3> [list [namespace current]::line_b3 \
			    [double% $c] [double% $jid]]
}

proc wb::line_b1 {c jid x y} {
    variable line

    set x [$c canvasx $x]
    set y [$c canvasy $y]
    #puts "$x $y"

    if {[info exists line(drawed)]} {
	lappend line(coords) $x $y

	catch {$c delete $line(temp)}
	set line(temp) [eval $c create line $line(coords) $line(options)]
    } else {
	set line(drawed) 1
	set line(coords) "$x $y"
	set line(options) [list -fill [get_color $jid] \
			       -width [get_width $jid] \
			       -joinstyle miter]
    }
}

proc wb::line_b1m {c x y} {
    variable line

    set x [$c canvasx $x]
    set y [$c canvasy $y]

    if {[info exists line(drawed)]} {
	#lappend line(coords) $x $y

	catch {$c delete $line(temp)}
	set line(temp) [eval $c create line $line(coords) $x $y $line(options)]
    }
}


proc wb::line_b3 {c chatid} {
    variable line

    catch {
	unset line(drawed)

	set id [create_id]
	catch {$c delete $line(temp)}
	set line(temp) [eval $c create line $line(coords) $line(options) \
				-tag id$id]

	if {[chat::is_groupchat $chatid]} {
	    $c delete $line(temp)
	} else {
	    set jid [jlib::connection_jid [chat::get_connid $chatid]]
	    $c addtag [time_tag created $jid] withtag $line(temp)
	}

	lappend vars points $line(coords)
	if {[set color [get_color $chatid]] != "#000000"} {
	    lappend vars stroke $color
	}
	if {[set width [get_width $chatid]] != 1} {
	    lappend vars stroke-width $width
	}

	lappend vars id $id

	send_svg $chatid [jlib::wrapper:createtag polyline -vars $vars]

	set line(coords) {}
	set line(temp) {}
    }
}

###############################################################################

###############################################################################
# Polygon

proc wb::polygon_bind {c jid} {
    bind $c <ButtonPress-1> \
	[list [namespace current]::polygon_b1 [double% $c] [double% $jid] %x %y]
    bind $c <B1-Motion> {}
    bind $c <Motion> [list [namespace current]::polygon_m [double% $c] %x %y]
    bind $c <ButtonRelease-1> {}
    bind $c <Button-3> [list [namespace current]::polygon_b3 \
			    [double% $c] [double% $jid]]
}

proc wb::polygon_b1 {c jid x y} {
    variable polygon
    variable line1
    variable line2
    global dofill

    set x [$c canvasx $x]
    set y [$c canvasy $y]

    if {[info exists polygon(drawed)]} {
	lappend polygon(coords) $x $y

	catch {$c delete $line1(temp)}
	catch {$c delete $line2(temp)}
	catch {$c delete $polygon(temp)}
	if {$dofill == 1} {
	    set polygon(temp) [eval $c create polygon $polygon(coords) $polygon(options)]
	} else {
	    set polygon(temp) [eval $c create line $polygon(coords) \
				       [lindex $polygon(coords) 0] \
				       [lindex $polygon(coords) 1] $polygon(line_options)]
	}
    } else {
	set polygon(drawed) 1
	set polygon(coords) "$x $y"
	set polygon(line_options) [list -fill [get_color $jid] \
			       -width [get_width $jid] \
			       -joinstyle miter]
	set polygon(options) [list -fill [get_fill_color $jid] \
			       -outline [get_color $jid] \
			       -width [get_width $jid] \
			       -joinstyle miter]
	
    }
}

proc wb::polygon_m {c x y} {
    variable polygon
    variable line1
    variable line2

    set x [$c canvasx $x]
    set y [$c canvasy $y]

    if {[info exists polygon(drawed)]} {
	set x1 [lindex $polygon(coords) 0]
	set y1 [lindex $polygon(coords) 1]
	set xn [lindex $polygon(coords) end-1]
	set yn [lindex $polygon(coords) end]

	catch {$c delete $line1(temp)}
	catch {$c delete $line2(temp)}
	set line1(temp) [eval $c create line $x1 $y1 $x $y $polygon(line_options)]
	set line2(temp) [eval $c create line $xn $yn $x $y $polygon(line_options)]
    }
}


proc wb::polygon_b3 {c chatid} {
    variable polygon
    variable line1
    variable line2
    global dofill

    catch {
	unset polygon(drawed)

	set id [create_id]
	catch {$c delete $line1(temp)}
	catch {$c delete $line2(temp)}
	catch {$c delete $polygon(temp)}
	if {[llength $polygon(coords)] > 4} {
	    if {$dofill == 1} {
		set polygon(temp) \
		    [eval $c create polygon $polygon(coords) $polygon(options) \
			     -tag id$id]
	    } else {
	    	set polygon(temp) \
		    [eval $c create line $polygon(coords) \
			     [lindex $polygon(coords) 0] \
			     [lindex $polygon(coords) 1] \
			     $polygon(line_options) \
		             -tag id$id]
	    }

	    if {[chat::is_groupchat $chatid]} {
		$c delete $polygon(temp)
	    } else {
		set jid [jlib::connection_jid [chat::get_connid $chatid]]
		$c addtag [time_tag created $jid] withtag $polygon(temp)
	    }

	    lappend vars points $polygon(coords)
	    if {$dofill == 1} {
		lappend vars fill [get_fill_color $chatid]
	    }
	    lappend vars stroke [get_color $chatid]
	    if {[set width [get_width $chatid]] != 1} {
		lappend vars stroke-width $width
	    }

	    lappend vars id $id

	    send_svg $chatid [jlib::wrapper:createtag polygon -vars $vars]
	}
	set polygon(coords) {}
	set polygon(temp) {}
    }
}

###############################################################################

###############################################################################
# Circle

proc wb::circle_bind {c jid} {
    bind $c <ButtonPress-1> \
	[list [namespace current]::circle_b1 [double% $c] [double% $jid] %x %y]
    bind $c <B1-Motion> \
 	[list [namespace current]::circle_b1m [double% $c] %x %y]
    bind $c <Motion> {}
    bind $c <ButtonRelease-1> \
	[list [namespace current]::circle_b1r [double% $c] [double% $jid] %x %y]
    bind $c <Button-3> {}
}

proc wb::circle_b1 {c jid x y} {
    variable circle
    global dofill

    set x [$c canvasx $x]
    set y [$c canvasy $y]

    set circle(drawed) 1
    set circle(center) "$x $y"
    set circle(options) [list -outline [get_color $jid] \
			       -width [get_width $jid] ]
    if {$dofill == 1} {
	lappend circle(options) -fill [get_fill_color $jid]
    }
}

proc wb::circle_b1r {c chatid x y} {
    variable circle
    global dofill

    if {[info exists circle(drawed)]} {
        unset circle(drawed)
	set cx [lindex $circle(center) 0]
	set cy [lindex $circle(center) 1]
	set x [$c canvasx $x]
	set y [$c canvasy $y]
	set r [expr hypot($cx-$x,$cy-$y)]
	set x1 [expr $cx-$r]
	set x2 [expr $cx+$r]
	set y1 [expr $cy-$r]
	set y2 [expr $cy+$r]

        set id [create_id]
        lappend vars cx $cx
	lappend vars cy $cy
	lappend vars r $r
        if {[set color [get_color $chatid]] != "#000000"} {
	   lappend vars stroke $color
	}
	if {$dofill == 1} {
	   lappend vars fill [get_fill_color $chatid]
	}
	if {[set width [get_width $chatid]] != 1} {
	   lappend vars stroke-width $width
	}

        lappend vars id $id

        catch {$c delete $circle(temp)}
        set circle(temp) [eval $c create oval $x1 $y1 $x2 $y2 $circle(options) \
				  -tag id$id]
	    
	if {[chat::is_groupchat $chatid]} {
	    $c delete $circle(temp)
	} else {
	    set jid [jlib::connection_jid [chat::get_connid $chatid]]
	    $c addtag [time_tag created $jid] withtag $circle(temp)
	}

	send_svg $chatid [jlib::wrapper:createtag circle -vars $vars]

        set circle(center) {}
        set circle(temp) {}
    }
}

proc wb::circle_b1m {c x y} {
    variable circle

    if {[info exists circle(drawed)]} {
	set cx [lindex $circle(center) 0]
	set cy [lindex $circle(center) 1]
	set x [$c canvasx $x]
	set y [$c canvasy $y]
	set r [expr hypot($cx-$x,$cy-$y)]
	set x1 [expr $cx-$r]
	set x2 [expr $cx+$r]
	set y1 [expr $cy-$r]
	set y2 [expr $cy+$r]
		

	catch {$c delete $circle(temp)}
	set circle(temp) [eval $c create oval $x1 $y1 $x2 $y2 $circle(options)]
    }
}



###############################################################################

###############################################################################
# Freehand

proc wb::freehand_bind {c jid} {
    bind $c <ButtonPress-1> \
	[list [namespace current]::freehand_b1p \
	     [double% $c] [double% $jid] %x %y]
    bind $c <B1-Motion> [list [namespace current]::freehand_b1m \
			     [double% $c] %x %y]
    bind $c <ButtonRelease-1> \
	[list [namespace current]::freehand_b1r [double% $c] [double% $jid]]
    bind $c <Button-3> {}
}

proc wb::freehand_b1p {c jid x y} {
    variable line

    set x [$c canvasx $x]
    set y [$c canvasy $y]
    #puts "$x $y"

    if {0 && [info exists line(drawed)]} {
	lappend line(coords) $x $y

	catch {$c delete $line(temp)}
	set line(temp) [eval $c create line $line(coords)]
    } else {
	set line(drawed) 1
	set line(coords) "$x $y"
	set line(options) [list -fill [get_color $jid] \
			       -width [get_width $jid] \
			       -joinstyle round]
    }
}

proc wb::freehand_b1m {c x y} {
    variable line

    set x [$c canvasx $x]
    set y [$c canvasy $y]

    if {[info exists line(drawed)]} {
	lappend line(coords) $x $y

	catch {$c delete $line(temp)}
	set line(temp) [eval $c create line $line(coords) $x $y $line(options)]
    }
}


proc wb::freehand_b1r {c chatid} {
    variable line

    catch {
	unset line(drawed)

	set id [create_id]
	catch {$c delete $line(temp)}
	set line(temp) [eval $c create line $line(coords) $line(options) \
			    -tag id$id]

	if {[chat::is_groupchat $chatid]} {
	    $c delete $line(temp)
	} else {
	    set jid [jlib::connection_jid [chat::get_connid $chatid]]
	    $c addtag [time_tag created $jid] withtag $line(temp)
	}

	lappend vars points $line(coords)
	if {[set color [get_color $chatid]] != "#000000"} {
	    lappend vars stroke $color
	}
	if {[set width [get_width $chatid]] != 1} {
	    lappend vars stroke-width $width
	}

	lappend vars id $id

	send_svg $chatid [jlib::wrapper:createtag polyline \
			   -vars $vars]

	set line(coords) {}
	set line(temp) {}
    }
}

###############################################################################

###############################################################################
# Remove

proc wb::remove_bind {c jid} {
    bind $c <ButtonPress-1> \
	[list [namespace current]::remove_b1p \
	     [double% $c] [double% $jid]]
    bind $c <B1-Motion> {}
    bind $c <ButtonRelease-1> {}
    bind $c <Button-3> {}
}

proc wb::remove_b1p {c chatid} {
    set tags [$c gettags current]
    set id ""
    foreach t $tags {
	if {[crange $t 0 1] == "id"} {
	    set id [crange $t 2 end]
	    break
	}
    }
    set connid [chat::get_connid $chatid]
    set jid [chat::get_jid $chatid]
    if {[chat::is_groupchat $chatid]} {
	set type groupchat
    } else {
	set type chat
	$c delete id$id
    }
    if {$id != ""} {
	jlib::send_msg $jid \
	    -connection $connid \
	    -type $type \
	    -xlist [list [jlib::wrapper:createtag x \
			      -vars {xmlns tkabber:whiteboard} \
			      -subtags [list [jlib::wrapper:createtag remove \
						  -vars [list id $id]]]]]
	
    }
}


###############################################################################

###############################################################################
# Move

proc wb::move_bind {c jid} {
    bind $c <ButtonPress-1> \
	[list [namespace current]::move_b1p \
	     [double% $c] [double% $jid] %x %y]
    bind $c <B1-Motion> [list [namespace current]::move_b1m \
			     [double% $c] %x %y]
    bind $c <ButtonRelease-1> \
	[list [namespace current]::move_b1r [double% $c] [double% $jid]]
    bind $c <Button-3> {}
}

proc wb::move_b1p {c jid x y} {
    variable move

    set tags [$c gettags current]
    set id ""
    foreach t $tags {
	if {[crange $t 0 1] == "id"} {
	    set id [crange $t 2 end]
	    break
	}
    }
    if {$id != ""} {
	set x [$c canvasx $x]
	set y [$c canvasy $y]

	set move(startx) $x
	set move(starty) $y
        set move(lastx) $x
	set move(lasty) $y

	set move(id) $id
    } else {
	catch {unset move(id)}
    }
}

proc wb::move_b1m {c x y} {
    variable move

    if {[info exists move(id)]} {
	set id $move(id)
	set x [$c canvasx $x]
	set y [$c canvasy $y]

	$c move id$id [expr {$x - $move(lastx)}] [expr {$y - $move(lasty)}]

	set move(lastx) $x
	set move(lasty) $y
    }
}


proc wb::move_b1r {c chatid} {
    variable move

    if {[info exists move(id)]} {
	set id $move(id)
	set x $move(lastx)
	set y $move(lasty)

	if {[chat::is_groupchat $chatid]} {
	    set type groupchat
	    $c move id$id \
		[expr {$move(startx) - $x}] [expr {$move(starty) - $y}]
	} else {
	    set type chat
	    set jid [jlib::connection_jid [chat::get_connid $chatid]]
	    $c addtag [time_tag moved $jid] withtag id$id
	}

	set vars [list id $id \
		      dx [expr {$x - $move(startx)}] \
		      dy [expr {$y - $move(starty)}]]

	set connid [chat::get_connid $chatid]
	set jid [chat::get_jid $chatid]
	jlib::send_msg $jid \
	    -connection $connid \
	    -type $type \
	    -xlist [list [jlib::wrapper:createtag x \
			      -vars {xmlns tkabber:whiteboard} \
			      -subtags [list [jlib::wrapper:createtag move \
						  -vars $vars]]]]
    }
}

###############################################################################
# Text

proc wb::text_bind {c chatid} {
    bind $c <ButtonPress-1> {}
    bind $c <B1-Motion> {}
    bind $c <ButtonRelease-1> \
	    [list [namespace current]::text_b1 [double% $c] [double% $chatid] %x %y]
    bind $c <Button-3> {}
}

proc wb::text_b1 {c chatid x y} {
    variable text_info
    set text_info(x) $x
    set text_info(y) $y
    set w [win_id whiteboard $chatid]
    set wt $w.text_dialog
    if {[winfo exists $wt]} {
	wm deiconify $wt
    } else {
	Dialog $wt -anchor e \
		   -separator yes \
		   -title [::msgcat::mc "Enter text"] \
		   -side bottom \
		   -modal none \
		   -default 0 \
		   -cancel 1
	$wt add -text [::msgcat::mc "OK"] \
	    -command [list [namespace current]::text_ok $wt $c $chatid]
	$wt add -text [::msgcat::mc "Cancel"] \
	    -command [list wm withdraw $wt]

	set en [entry $wt.text -width 80 \
		    -textvariable [namespace current]::text_entered($chatid)]
	pack $en -side top -in [$wt getframe]
	$wt draw $en
    }
}

proc wb::text_ok {wt c chatid} {
    variable app_font
    variable text_info
    set id [create_id]

    set text [set [namespace current]::text_entered($chatid)]
    if {[chat::is_groupchat $chatid]} {
	set type groupchat
    } else {
	set type chat
	$c create text $text_info(x) $text_info(y) -tag id$id \
	    -text $text \
	    -fill [get_text_color $chatid]
	set font [get_text_font $chatid]
	if {[info exists app_font($font)]} {
	    $c itemconfigure id$id -font $font
	}
	set jid [jlib::connection_jid [chat::get_connid $chatid]]
	$c addtag [time_tag created $jid] withtag id$id
    }
    set vars [list id $id x $text_info(x) y $text_info(y) \
		   fill [get_text_color $chatid]]
    set font [get_text_font $chatid]
    if {[info exists app_font($font)]} {
	array set font_opt [font configure $font]
	lappend vars font-size $font_opt(-size) \
		     font-family $font_opt(-family)
	if {$font_opt(-underline) || $font_opt(-overstrike)} {
	    set dec {}
	    if {$font_opt(-underline)} {
		lappend dec underline
	    }
	    if {$font_opt(-overstrike)} {
		lappend dec line-through
	    }
	    lappend vars text-decoration $dec
	}
	if {[string equal $font_opt(-slant) italic]} {
	    lappend vars font-style italic
	}
	if {[string equal $font_opt(-weight) bold]} {
	    lappend vars font-weight bold
	}
	unset font_opt
    }

    send_svg $chatid [jlib::wrapper:createtag text -vars $vars -chdata $text]
    wm withdraw $wt
}


###############################################################################

