[Tkabber-dev] r1816 - trunk/tkabber

tkabber-svn at jabber.ru tkabber-svn at jabber.ru
Mon Jul 27 19:00:06 MSD 2009


Author: sergei
Date: 2009-07-27 19:00:05 +0400 (Mon, 27 Jul 2009)
New Revision: 1816

Modified:
   trunk/tkabber/ChangeLog
   trunk/tkabber/muc.tcl
Log:
	* muc.tcl: Changed affiliation and role list control interface. The
	  former one had insufficient performance on long lists (a few thousand
	  elements) because it created three entries and one combobox per
	  list item.


Modified: trunk/tkabber/ChangeLog
===================================================================
--- trunk/tkabber/ChangeLog	2009-07-25 19:38:32 UTC (rev 1815)
+++ trunk/tkabber/ChangeLog	2009-07-27 15:00:05 UTC (rev 1816)
@@ -1,3 +1,10 @@
+2009-07-27  Sergei Golovan  <sgolovan at nes.ru>
+
+	* muc.tcl: Changed affiliation and role list control interface. The
+	  former one had insufficient performance on long lists (a few thousand
+	  elements) because it created three entries and one combobox per
+	  list item.
+
 2009-07-25  Sergei Golovan  <sgolovan at nes.ru>
 
 	* plugins/general/xcommands.tcl: Made ad-hoc command window

Modified: trunk/tkabber/muc.tcl
===================================================================
--- trunk/tkabber/muc.tcl	2009-07-25 19:38:32 UTC (rev 1815)
+++ trunk/tkabber/muc.tcl	2009-07-27 15:00:05 UTC (rev 1816)
@@ -567,34 +567,123 @@
 	destroy $w
     }
 
-    Dialog $w -title [::msgcat::mc [format "Edit %s list" $val]] \
+    Dialog $w -title [::msgcat::mc "Edit %s list" $val] \
         -modal none -separator 1 -anchor e -default 0 -cancel 1 \
         -parent .
 
     set wf [$w getframe]
 
-    set sw [ScrolledWindow $wf.sw -scrollbar vertical]
-    set sf [ScrollableFrame $w.fields -constrainedwidth yes]
-    set f [$sf getframe]
-    $sw setwidget $sf
-    fill_list $sf $f $subels $attr $val
-    list_add_item $sf $f $attr $val
+    set sw [ScrolledWindow $wf.sw]
+
+    set lb [::mclistbox::mclistbox $sw.listbox \
+		    -exportselection 0 \
+		    -resizeonecolumn 1 \
+		    -labelanchor w \
+		    -width 90 \
+		    -height 16]
+
+    bind $lb <Destroy> [namespace code [list list_cleanup %W]]
+
+    bind $lb <<ListboxSelect>> [namespace code [list update_fields %W [double% $val] [double% $w.fr1]]]
+
+    $sw setwidget $lb
+    fill_list $lb $subels $attr $val
  
     $w add -text [::msgcat::mc "Send"] \
-	-command [list muc::send_list $chatid $attr $val $w $f]
+	-command [list muc::send_list $chatid $attr $val $w $lb]
     $w add -text [::msgcat::mc "Cancel"] -command [list destroy $w]
 
-    bind $f <Destroy> [list muc::list_cleanup %W]
 
-    frame $w.fr
-    pack $w.fr -side bottom -in $wf -fill x
+    frame $w.fr1
+    pack $w.fr1 -side bottom -in $wf -fill x -pady 1m
 
-    button $w.add -text [::msgcat::mc "Add new item"] \
-	-command [list muc::list_add_item $sf $f $attr $val]
-    pack $w.add -side right -in $w.fr -padx 1m -pady 1m
+    grid columnconfigure $w.fr1 3 -weight 1
 
+    label $w.fr1.lnick -text [::msgcat::mc "Nick"]
+    label $w.fr1.ljid -text [::msgcat::mc "JID"]
+    switch -- $attr {
+	role {
+	    label $w.fr1.lattr -text [::msgcat::mc "Role"]
+	}
+	affiliation {
+	    label $w.fr1.lattr -text [::msgcat::mc "Affiliation"]
+	}
+    }
+    label $w.fr1.lreason -text [::msgcat::mc "Reason"]
+
+    grid $w.fr1.lnick   -row 0 -column 0 -sticky w
+    grid $w.fr1.ljid    -row 0 -column 1 -sticky w
+    grid $w.fr1.lattr   -row 0 -column 2 -sticky w
+    grid $w.fr1.lreason -row 0 -column 3 -sticky w
+
+    entry $w.fr1.nick1 -takefocus 0 -highlightthickness 0
+    if {[catch {$w.fr1.nick1 configure -state readonly}]} {
+	$w.fr1.nick1 configure -state disabled
+    }
+    entry $w.fr1.jid1 -takefocus 0 -highlightthickness 0
+    if {[catch {$w.fr1.jid1 configure -state readonly}]} {
+	$w.fr1.jid1 configure -state disabled
+    }
+
+    switch -- $attr {
+	role {
+	    ComboBox $w.fr1.attr1 -text $val \
+		-values {moderator participant visitor none} \
+		-editable no \
+		-width 11
+	}
+	affiliation {
+	    ComboBox $w.fr1.attr1 -text $val \
+		-values {owner admin member none outcast} \
+		-editable no \
+		-width 7
+	}
+    }
+
+    entry $w.fr1.reason1
+
+    button $w.fr1.update -text [::msgcat::mc "Update item"] \
+	-command [list muc::list_update_item $lb $attr $w.fr1]
+
+    grid $w.fr1.nick1   -row 1 -column 0 -sticky ew
+    grid $w.fr1.jid1    -row 1 -column 1 -sticky ew
+    grid $w.fr1.attr1   -row 1 -column 2 -sticky ew
+    grid $w.fr1.reason1 -row 1 -column 3 -sticky ew
+    grid $w.fr1.update  -row 1 -column 4 -sticky ew
+
+    entry $w.fr1.nick2
+    entry $w.fr1.jid2
+
+    switch -- $attr {
+	role {
+	    ComboBox $w.fr1.attr2 -text $val \
+		-values {moderator participant visitor none} \
+		-editable no \
+		-width 11
+	}
+	affiliation {
+	    ComboBox $w.fr1.attr2 -text $val \
+		-values {owner admin member none outcast} \
+		-editable no \
+		-width 7
+	}
+    }
+
+    entry $w.fr1.reason2
+
+    button $w.fr1.add -text [::msgcat::mc "Add new item"] \
+	-command [list muc::list_add_item $lb $val $w.fr1]
+
+    grid $w.fr1.nick2   -row 2 -column 0 -sticky ew
+    grid $w.fr1.jid2    -row 2 -column 1 -sticky ew
+    grid $w.fr1.attr2   -row 2 -column 2 -sticky ew
+    grid $w.fr1.reason2 -row 2 -column 3 -sticky ew
+    grid $w.fr1.add     -row 2 -column 4 -sticky ew
+
+    frame $w.fr1.fr
+
     label $w.lall -text [::msgcat::mc "All items:"]
-    pack $w.lall -side left -in $w.fr -padx 1m -pady 1m
+    pack $w.lall -side left -in $w.fr1.fr -padx 1m -pady 1m
 
     switch -- $attr {
 	role {
@@ -602,90 +691,156 @@
 		-values {moderator participant visitor none} \
 		-editable no \
 		-width 11 \
-		-modifycmd [list muc::change_all_items $f $w.roleall $attr]
-	    pack $w.roleall -side left -anchor w -in $w.fr -pady 1m
+		-modifycmd [list muc::change_all_items $lb $w.roleall $attr]
+	    pack $w.roleall -side left -anchor w -in $w.fr1.fr -pady 1m
 	}
 	affiliation {
 	    ComboBox $w.affiliationall -text $val \
 		-values {owner admin member none outcast} \
 		-editable no \
 		-width 7 \
-		-modifycmd [list muc::change_all_items $f $w.affiliationall $attr]
-	    pack $w.affiliationall -side left -in $w.fr -pady 1m
+		-modifycmd [list muc::change_all_items $lb $w.affiliationall $attr]
+	    pack $w.affiliationall -side left -in $w.fr1.fr -pady 1m
 	}
     }
 
+    grid $w.fr1.fr -row 3 -column 0 -columnspan 5 -sticky w
+
     pack $sw -side top -expand yes -fill both
 
-    bindscroll $f $sf
+    bindscroll $sw $lb
 
-    set hf [frame $w.hf]
-    pack $hf -side top
-    set vf [frame $w.vf]
-    pack $vf -side left
+    $w draw
+}
 
-    update idletasks
-    $hf configure -width [expr {[winfo reqwidth $f] + [winfo pixels $f 1c]}]
+###############################################################################
 
-    set h [winfo reqheight $f]
-    set sh [winfo screenheight $w]
-    if {$h > $sh - 200} {
-	set h [expr {$sh - 200}]
+proc muc::trim {str} {
+    string range $str 1 end-1
+}
+
+proc muc::untrim {str} {
+    return " $str "
+}
+
+proc muc::update_fields {lb val fr} {
+    set selection [$lb curselection]
+    if {[llength $selection] == 0} {
+	set nick ""
+	set jid ""
+	set attr $val
+	set reason ""
+    } else {
+	set data [$lb get [lindex $selection 0]]
+	lassign $data n nick jid attr reason
     }
-    $vf configure -height $h
 
-    $w draw
-    $sf yview moveto 1.0
+    $fr.nick1 configure -state normal
+    $fr.nick1 delete 0 end
+    $fr.nick1 insert 0 [trim $nick]
+    if {[catch {$fr.nick1 configure -state readonly}]} {
+	$fr.nick1 configure -state disabled
+    }
+    $fr.jid1 configure -state normal
+    $fr.jid1 delete 0 end
+    $fr.jid1 insert 0 [trim $jid]
+    if {[catch {$fr.jid1 configure -state readonly}]} {
+	$fr.jid1 configure -state disabled
+    }
+    $fr.attr1 configure -text [trim $attr]
+    $fr.reason1 delete 0 end
+    $fr.reason1 insert 0 [trim $reason]
 }
 
-###############################################################################
+proc muc::list_update_item {lb attr fr} {
+    set selection [$lb curselection]
+    if {[llength $selection] == 0} {
+	return
+    }
+    set idx [lindex $selection 0]
+    set data [lrange [$lb get $idx] 0 0]
 
-proc muc::change_all_items {f combobox attr} {
-    variable listdata
-    variable origlistdata
+    lappend data [untrim [$fr.nick1 get]] \
+		 [untrim [$fr.jid1 get]] \
+		 [untrim [$fr.attr1 get]] \
+		 [untrim [$fr.reason1 get]]
 
+    incr idx
+    $lb insert $idx $data
+    incr idx -1
+    $lb delete $idx
+    $lb selection clear 0 end
+    $lb selection set $idx
+}
+
+proc muc::change_all_items {lb combobox attr} {
     set value [$combobox get]
 
-    for {set i 1} {$i <= $listdata($f,rows)} {incr i} {
-	set listdata($f,$attr,$i) $value
+    set yposition [lindex [$lb yview] 0]
+    set data [$lb get 0 end]
+    set result {}
+    set i 0
+    foreach row $data {
+	lappend result [lreplace $row 3 3 [untrim $value]]
     }
+    $lb delete 0 end
+    eval $lb insert end $result
+    $lb yview moveto $yposition
 }
 
 ###############################################################################
 
-proc muc::fill_list {sf f items attr val} {
+proc muc::fill_list {lb items attr val} {
     variable listdata
-    variable origlistdata
+    variable lastsort
 
-    grid columnconfigure $f 0 -weight 1
-    grid columnconfigure $f 1 -weight 1
-    grid columnconfigure $f 2 -weight 0
-    grid columnconfigure $f 3 -weight 2
+    set lastsort($lb) jid
 
-    label $f.lnick -text [::msgcat::mc "Nick"]
-    grid $f.lnick -row 0 -column 0 -sticky we -padx 1m
-    bindscroll $f.lnick $sf
-    label $f.ljid -text JID
-    grid $f.ljid -row 0 -column 1 -sticky we -padx 1m
-    bindscroll $f.ljid $sf
+    set width(0) 3
+    set name(0) n
+    $lb column add n -label [untrim [::msgcat::mc "#"]]
+
+    set width(1) [expr {[string length [::msgcat::mc "Nick"]] + 2}]
+    set name(1) nick
+    $lb column add nick -label [untrim [::msgcat::mc "Nick"]]
+    $lb label bind nick <ButtonPress-1> [namespace code [list Sort %W nick]]
+
+    set width(2) [expr {[string length [::msgcat::mc "JID"]] + 2}]
+    set name(2) jid
+    $lb column add jid -label [untrim [::msgcat::mc "JID"]]
+    $lb label bind jid <ButtonPress-1> [namespace code [list Sort %W jid]]
+
     switch -- $attr {
 	role {
-	    label $f.lrole -text [::msgcat::mc "Role"]
-	    grid $f.lrole -row 0 -column 2 -sticky we -padx 1m
-	    bindscroll $f.lrole $sf
+	    set width(3) [expr {[string length [::msgcat::mc "Role"]] + 2}]
+	    if {$width(3) < 13} {
+		# " participant "
+		set width(3) 13
+	    }
+	    set name(3) role
+	    $lb column add role -label [untrim [::msgcat::mc "Role"]]
+	    $lb label bind role <ButtonPress-1> [namespace code [list Sort %W role]]
 	}
 	affiliation {
-	    label $f.laffiliation -text [::msgcat::mc "Affiliation"]
-	    grid $f.laffiliation -row 0 -column 2 -sticky we -padx 1m
-	    bindscroll $f.laffiliation $sf
+	    set width(3) [expr {[string length [::msgcat::mc "Affiliation"]] + 2}]
+	    if {$width(3) < 9} {
+		# " outcast "
+		set width(3) 9
+	    }
+	    set name(3) affiliation
+	    $lb column add affiliation -label [untrim [::msgcat::mc "Affiliation"]]
+	    $lb label bind affiliation <ButtonPress-1> [namespace code [list Sort %W affiliation]]
 	}
     }
-    label $f.lreason -text [::msgcat::mc "Reason"]
-    grid $f.lreason -row 0 -column 3 -sticky we -padx 1m
-    bindscroll $f.lreason $sf
 
-    set row 1
+    set width(4) [expr {[string length [::msgcat::mc "Reason"]] + 2}]
+    set name(4) reason
+    $lb column add reason -label [untrim [::msgcat::mc "Reason"]]
+    $lb label bind reason <ButtonPress-1> [namespace code [list Sort %W reason]]
 
+    $lb column add lastcol -label "" -width 0
+    $lb configure -fillcolumn lastcol
+    
     set items2 {}
     foreach item $items {
 	::xmpp::xml::split $item tag xmlns attrs cdata subels
@@ -693,8 +848,14 @@
 	    item {
 		set nick [::xmpp::xml::getAttr $attrs nick]
 		set jid [::xmpp::xml::getAttr $attrs jid]
-		set role [::xmpp::xml::getAttr $attrs role]
-		set affiliation [::xmpp::xml::getAttr $attrs affiliation]
+		switch -- $attr {
+		    role {
+			set attribute [::xmpp::xml::getAttr $attrs role]
+		    }
+		    affiliation {
+			set attribute [::xmpp::xml::getAttr $attrs affiliation]
+		    }
+		}
 		set reason ""
 		foreach subitem $subels {
 		    ::xmpp::xml::split $subitem stag sxmlns sattrs scdata ssubels
@@ -702,180 +863,121 @@
 			set reason $scdata
 		    }
 		}
-		lappend items2 [list $nick $jid $role $affiliation $reason]
+		lappend items2 [list $nick $jid $attribute $reason]
 	    }
 	}
     }
 
-    foreach item [lsort -dictionary -index 1 $items2] {
-	lassign $item listdata($f,nick,$row) listdata($f,jid,$row) \
-		      role affiliation listdata($f,reason,$row)
-
-	entry $f.nick$row \
-	    -textvariable muc::listdata($f,nick,$row) \
-	    -takefocus 0 \
-	    -highlightthickness 0 \
-	    -width 20
-	if {[catch {$f.nick$row configure -state readonly}]} {
-	    $f.nick$row configure -state disabled
-	}
-	grid $f.nick$row -row $row -column 0 -sticky we -padx 1m
-	bindscroll $f.nick$row $sf
-
-	entry $f.jid$row \
-	    -textvariable muc::listdata($f,jid,$row) \
-	    -takefocus 0 \
-	    -highlightthickness 0 \
-	    -width 30
-	if {[catch {$f.jid$row configure -state readonly}]} {
-	    $f.jid$row configure -state disabled
-	}
-	grid $f.jid$row -row $row -column 1 -sticky we -padx 1m
-	bindscroll $f.jid$row $sf
-
-	switch -- $attr {
-	    role {
-		ComboBox $f.role$row -text $role \
-		    -values {moderator participant visitor none} \
-		    -editable no \
-		    -width 11 \
-		    -textvariable muc::listdata($f,role,$row)
-		grid $f.role$row -row $row -column 2 -sticky we -padx 1m
-		bindscroll $f.role$row $sf
+    set listdata($lb) [lsort -dictionary -index 1 $items2]
+    set row 1
+    foreach item $listdata($lb) {
+	set itemdata {}
+	set i 0
+	foreach data [linsert $item 0 $row] {
+	    set wd [string length [untrim $data]]
+	    if {$wd > $width($i)} {
+		if {$wd > 50} {
+		    set width($i) 50
+		} else {
+		    set width($i) $wd
+		}
 	    }
-	    affiliation {
-		ComboBox $f.affiliation$row -text $affiliation \
-		    -values {owner admin member none outcast} \
-		    -editable no \
-		    -width 7 \
-		    -textvariable muc::listdata($f,affiliation,$row)
-		grid $f.affiliation$row -row $row -column 2 -sticky we -padx 1m
-		bindscroll $f.affiliation$row $sf
-	    }
+	    lappend itemdata [untrim $data]
+	    incr i
 	}
+	lappend itemdata ""
+	$lb insert end $itemdata
 
-	entry $f.reason$row \
-	    -textvariable muc::listdata($f,reason,$row) \
-	    -width 40
-	grid $f.reason$row -row $row -column 3 -sticky we -padx 1m
-	bindscroll $f.reason$row $sf
-	
 	incr row
     }
 
-    set listdata($f,rows) [incr row -1]
-    array set origlistdata [array get listdata ${f}*]
+    for {set i 0} {$i < 5} {incr i} {
+	$lb column configure $name($i) -width $width($i)
+    }
 }
 
-###############################################################################
+proc muc::Sort {lb tag} {
+    variable lastsort
 
-proc muc::list_add_item {sf f attr val} {
-    variable listdata
+    set data [$lb get 0 end]
+    set index [lsearch -exact [$lb column names] $tag]
+    if {$lastsort($lb) != $tag} {
+	set result [lsort -dictionary -index $index $data]
+	set lastsort($lb) $tag
+    } else {
+	set result [lsort -decreasing -dictionary -index $index $data]
+	set lastsort($lb) ""
+    }
+    set result1 {}
+    set i 0
+    foreach row $result {
+	lappend result1 [lreplace $row 0 0 [untrim [incr i]]]
+    }
+    $lb delete 0 end
+    eval $lb insert end $result1
+}
 
-    set row [incr listdata($f,rows)]
+###############################################################################
 
-    entry $f.nick$row \
-	-textvariable muc::listdata($f,nick,$row) \
-	-width 20
-    grid $f.nick$row -row $row -column 0 -sticky we -padx 1m
-    bindscroll $f.nick$row $sf
-    
-    entry $f.jid$row \
-	-textvariable muc::listdata($f,jid,$row) \
-	-width 30
-    grid $f.jid$row -row $row -column 1 -sticky we -padx 1m
-    bindscroll $f.jid$row $sf
-    focus $f.jid$row
-
-    switch -- $attr {
-	role {
-	    ComboBox $f.role$row -text none \
-		-values {moderator participant visitor none} \
-		-editable no \
-		-width 11 \
-		-textvariable muc::listdata($f,role,$row)
-	    grid $f.role$row -row $row -column 2 -sticky we -padx 1m
-	    bindscroll $f.role$row $sf
-	}
-	affiliation {
-	    ComboBox $f.affiliation$row -text none \
-		-values {owner admin member none outcast} \
-		-editable no \
-		-width 7 \
-		-textvariable muc::listdata($f,affiliation,$row)
-	    grid $f.affiliation$row -row $row -column 2 -sticky we -padx 1m
-	    bindscroll $f.affiliation$row $sf
-	}
+proc muc::list_add_item {lb val fr} {
+    set n [trim [lindex [$lb get end] 0]]
+    if {[string equal $n ""]} {
+	set n 0
     }
 
-    entry $f.reason$row \
-	-textvariable muc::listdata($f,reason,$row) \
-	-width 40
-    grid $f.reason$row -row $row -column 3 -sticky we -padx 1m
-    bindscroll $f.reason$row $sf
+    set data [list [untrim [incr n]] \
+	     [untrim [$fr.nick2 get]] \
+	     [untrim [$fr.jid2 get]] \
+	     [untrim [$fr.attr2 get]] \
+	     [untrim [$fr.reason2 get]]]
 
-    set listdata($f,$attr,$row) $val
+    $lb insert end $data
+
+    $fr.nick2 delete 0 end
+    $fr.jid2 delete 0 end
+    $fr.attr2 configure -text $val
+    $fr.reason2 delete 0 end
 }
 
 ###############################################################################
 
-proc muc::send_list {chatid attr val w f} {
-    variable origlistdata
+proc muc::send_list {chatid attr val w lb} {
     variable listdata
 
+    foreach item $listdata($lb) {
+	set tmp([lrange $item 0 1]) $item
+    }
+
     set items {}
+    foreach item [$lb get 0 end] {
+	lassign $item n nick jid val reason
+	set nick [trim $nick]
+	set jid [trim $jid]
 
-    for {set i 1} {$i <= $origlistdata($f,rows)} {incr i} {
-	set vars {}
-	if {$listdata($f,$attr,$i) != $origlistdata($f,$attr,$i) || \
-		$listdata($f,reason,$i) != $origlistdata($f,reason,$i)} {
-	    lappend vars $attr $listdata($f,$attr,$i)
+	if {$nick == "" && $jid == ""} {
+	    continue
 	}
 
-	if {$vars != {}} {
-	    if {$origlistdata($f,nick,$i) != ""} {
-		lappend vars nick $origlistdata($f,nick,$i)
-	    }
-	    if {$origlistdata($f,jid,$i) != ""} {
-		lappend vars jid $origlistdata($f,jid,$i)
-	    }
-	    set itemsubtags {}
-	    set reason $listdata($f,reason,$i)
-	    if {$reason != ""} {
-	        lappend itemsubtags [::xmpp::xml::create reason \
-	        			 -cdata $reason]
-	    }
-	    lappend items [::xmpp::xml::create item \
-			       -attrs $vars \
-			       -subelements $itemsubtags]
-	}
-    }
+	set val [trim $val]
+	set reason [trim $reason]
 
-    for {} {$i <= $listdata($f,rows)} {incr i} {
-	set vars1 {}
-	set vars2 {}
-	if {$listdata($f,$attr,$i) != ""} {
-	    lappend vars1 $attr $listdata($f,$attr,$i)
+	if {[info exists tmp([list $nick $jid])] && \
+		$tmp([list $nick $jid]) == [list $nick $jid $val $reason]} continue
+
+	set attrs [list $attr $val]
+	if {$nick != ""} {
+	    lappend attrs nick $nick
 	}
-	if {$listdata($f,nick,$i) != ""} {
-	    lappend vars2 nick $listdata($f,nick,$i)
+	if {$jid != ""} {
+	    lappend attrs jid $jid
 	}
-	if {$listdata($f,jid,$i) != ""} {
-	    lappend vars2 jid $listdata($f,jid,$i)
+	set itemsubels {}
+	if {$reason != ""} {
+	    lappend itemsubels [::xmpp::xml::create reason -cdata $reason]
 	}
-
-	if {$vars1 != {} && $vars2 != {}} {
-	    set vars [concat $vars2 $vars1]
-	    set itemsubtags {}
-	    set reason $listdata($f,reason,$i)
-	    if {$reason != ""} {
-	        lappend itemsubtags [::xmpp::xml::create reason \
-	        			 -cdata $reason]
-	    }
-	    lappend items [::xmpp::xml::create item \
-			       -attrs $vars \
-			       -subelements $itemsubtags]
-	}
+	lappend items [::xmpp::xml::create item \
+				-attrs $attrs \
+				-subelements $itemsubels]
     }
 
     set xlib [chat::get_xlib $chatid]
@@ -894,16 +996,16 @@
     destroy $w
 }
 
-###############################################################################
-
 proc muc::list_cleanup {f} {
     variable listdata
-    variable origlistdata
+    variable lastsort
 
-    array unset listdata ${f},*
-    array unset origlistdata ${f},*
+    catch {unset listdata($f)}
+    catch {unset lastsort($f)}
 }
 
+###############################################################################
+
 proc muc::request_config_dialog {chatid} {
     variable winid
 



More information about the Tkabber-dev mailing list