Index: RosterTree.tcl =================================================================== --- RosterTree.tcl (revision 2778) +++ RosterTree.tcl (working copy) @@ -759,10 +759,11 @@ proc ::RosterTree::EditEnd {jid} { variable T - +::Debug 2 "::RosterTree::EditEnd jid: $jid" # Restore item with its original style. - set jid [::Jabber::Jlib roster getrosterjid $jid] - eval {::Roster::SetItem $jid} [::Jabber::Jlib roster getrosteritem $jid] + set rjid [::Jabber::Jlib roster getrosterjid $jid] +::Debug 2 "::RosterTree::EditEnd rosterjid: $rjid rosteritem: [::Jabber::Jlib roster getrosteritem $jid]" + eval {::Roster::SetItem $rjid} [::Jabber::Jlib roster getrosteritem $rjid] } proc ::RosterTree::EditTimerCancel {} { @@ -931,8 +932,15 @@ proc ::RosterTree::OnReturn {} { variable T - foreach jid [GetSelectedJID] { - ActionDoubleClick $jid + foreach tag [GetSelected] { + set type [lindex $tag 0] + set jid [lindex $tag 1] + if {$type eq "resource"} { + ActionDoubleClick resource $jid + } else { + jlib::splitjid $jid jid2 res + ActionDoubleClick $type $jid2 + } } } @@ -989,26 +997,31 @@ if {([lindex $id 0] eq "item") && ([llength $id] == 6)} { set item [lindex $id 1] set tags [GetTagOfItem $item] - if {[lindex $tags 0] eq "jid"} { + set type [lindex $tags 0] + if {$type eq "jid" || $type eq "resource"} { set jid [lindex $tags 1] - ActionDoubleClick $jid + ActionDoubleClick $type $jid } } } -proc ::RosterTree::ActionDoubleClick {jid} { + +proc ::RosterTree::ActionDoubleClick {type jid} { global jprefs - set jid2 [jlib::barejid $jid] if {[string equal $jprefs(rost,dblClk) "normal"]} { ::NewMsg::Build -to $jid2 } elseif {[string equal $jprefs(rost,dblClk) "chat"]} { if {[::Jabber::Jlib roster isavailable $jid]} { - # We let Chat handle this internally. - ::Chat::StartThread $jid2 + if {$type ne "resource"} { + ::Chat::StartThread $jid2 + } else { + ::Chat::StartThread $jid + } } else { + # always send messages to the two tier jid ::NewMsg::Build -to $jid2 } } @@ -1055,7 +1068,7 @@ set jidL [list] set tags [GetSelected] foreach tag $tags { - if {[lindex $tag 0] eq "jid"} { + if {[lindex $tag 0] eq "jid" || [lindex $tag 0] eq "resource"} { lappend jidL [lindex $tag 1] } } @@ -1137,9 +1150,16 @@ set jidL [concat $jidL [FindAllJIDInItem $item]] } } + resource { + set jid [lindex $tags 1] + lappend jidL $jid + } } } - ::Roster::DoPopup $jidL $groupL $x $y + if {![info exists mtag]} { + set mtag "" + } + ::Roster::DoPopup $mtag $jidL $groupL $x $y } proc ::RosterTree::FindAllJIDInItem {item} { @@ -1210,7 +1230,9 @@ variable tag2items if {[info exists tag2items($tag)]} { +parray tag2items foreach item $tag2items($tag) { +::Debug 2 "::RosterTree::DeleteWithTag item: $item" $T item delete $item } } @@ -1257,7 +1279,19 @@ } return $items } - + + proc ::RosterTree::FindWithMatchingTag {tag} { + variable tag2items + + # Note that we don't need escaping here since tag0 is guranteed to be free + # from any special chars. + set items [list] + foreach {key value} [array get tag2items "$tag*"] { + set items [concat $items $value] + } + return $items + } + # RosterTree::FindChildrenOfTag -- # # The caller MUST verify that the tag is actually unique. @@ -1410,6 +1444,7 @@ set istrpt [::Roster::IsTransportEx $jid] if {$istrpt} { if {!$jprefs(rost,showTrpts)} { + # do not show transports return } } else { @@ -1424,6 +1459,7 @@ } } else { if {!$jprefs(rost,showOffline)} { + # do not show offline users return } } @@ -1432,7 +1468,8 @@ set itemTagL [list] set mjid [jlib::jidmap $jid] - + set jid2 [jlib::barejid $jid] + set jlib [::Jabber::GetJlib] # Keep track of any dirs created. set dirtags [list] @@ -1457,7 +1494,8 @@ lappend dirtags [lindex $itemTagL 1] } } elseif {[info exists argsA(-groups)] && [llength $argsA(-groups)]} { - +::Debug 2 "::RosterTree::CreateItemBase a group is assigned" +parray argsA # Group(s): foreach group $argsA(-groups) { @@ -1472,18 +1510,77 @@ lappend dirtags $ptag lappend itemTagL $pitem $ptag } - set tag [list jid $mjid] - set item [CreateWithTag $tag $pitem] - lappend itemTagL $item $tag + # using jid2 below, makes IsCoccinella fail to detect a coccinella resource + set tag [list jid $jid] + set ctag [list jid $jid2] + set tagX [lindex [FindWithMatchingTag $ctag] 0] + if {$tagX eq ""} { + set item [CreateWithTag $tag $pitem] + lappend itemTagL $item $tag + } else { + # put a + marker in front of the contact + $T item configure $tagX -button 1 + # in case there are no children, we want to default the view + # to be closed + set numchildren [$T item numchildren $tagX] + if {$numchildren eq 0} { + $T item collapse $tagX + } + # add the contact to the list of directories + lappend dirtags $tagX + set resOnL [$jlib roster getresources $mjid -type available] + set pjid [FindWithTag $tag] + foreach resource $resOnL { + set tag [list resource $jid2/$resource] + # check whether the resource is already listed + # if more than three resources online, otherwise it will show each + # resource multiplied by the number of online resources times + set tagExists [FindWithTag $tag] + if {$tagExists eq ""} { + set item [CreateWithTag $tag $tagX] + lappend itemTagL $item $tag + } + } + } } } else { - +::Debug 2 "::RosterTree::CreateItemBase no group is assigned" +parray argsA # No groups associated with this item. - set tag [list jid $mjid] set ptag [list head $presence] set pitem [FindWithTag $ptag] - set item [CreateWithTag $tag $pitem] - lappend itemTagL $item $tag + # using jid2 below, makes IsCoccinella fail to detect a coccinella resource + set tag [list jid $jid] + set ctag [list jid $jid2] + set tagX [lindex [FindWithMatchingTag $ctag] 0] + if {$tagX eq ""} { + set item [CreateWithTag $tag $pitem] + lappend itemTagL $item $tag + } else { + # put a + marker in front of the contact + $T item configure $tagX -button 1 + set numchildren [$T item numchildren $tagX] + # in case there are no children, we want to default the view + # to be closed + if {$numchildren eq 0} { + $T item collapse $tagX + } + # add the contact to the list of directories + lappend dirtags $tagX + set resOnL [$jlib roster getresources $mjid -type available] + set pjid [FindWithTag $tag] + foreach resource $resOnL { + set tag [list resource $jid2/$resource] + # check whether the resource is already listed + # if more than three resources online, otherwise it will show each + # resource multiplied by the number of online resources times + set tagExists [FindWithTag $tag] + if {$tagExists eq ""} { + set item [CreateWithTag $tag $tagX] + lappend itemTagL $item $tag + } + } + } } # If we created a directory and that is on the closed item list. @@ -1529,20 +1626,20 @@ # with a jid. proc ::RosterTree::DeleteItemBase {jid} { - - # If have 3-tier jid: - # presence = 'available' => remove jid2 + jid3 - # presence = 'unavailable' => remove jid2 + jid3 - # Else if 2-tier jid: => remove jid2 - + global jprefs set mjid3 [jlib::jidmap $jid] jlib::splitjid $mjid3 mjid2 res - + # we need to delete the resource + # and the contact + if {$jid eq $mjid2} { + set tag [list jid $mjid2] + } else { + set tag [list resource $jid] + } + DeleteWithTag $tag + # also delete a remaining single resource jid set tag [list jid $mjid2] DeleteWithTag $tag - if {$res ne ""} { - DeleteWithTag [list jid $mjid3] - } } # RosterTree::BasePostProcessDiscoInfo -- @@ -1668,6 +1765,7 @@ array set argsA $args set mjid [jlib::jidmap $jid] + set jid2 [jlib::barejid $jid] # Design the balloon help window message. set msg [jlib::unescapejid $jid] @@ -1693,10 +1791,11 @@ } # Append any registered balloon messages. Both bare and full JIDs. + # there are only bare jids in the array if {[array exists balloon]} { set bnames [array names balloon *,[jlib::ESC $mjid]] if {[jlib::isfulljid $mjid]} { - set xnames [array names balloon *,[jlib::ESC [jlib::barejid $mjid]]] + set xnames [array names balloon *,[jlib::ESC [jlib::barejid $jid2]]] set bnames [concat $bnames $xnames] } foreach key [lsort $bnames] { @@ -1714,8 +1813,9 @@ # @@@ Better place is in ::Roster proc ::RosterTree::BalloonRegister {key jid msg} { +::CallTrace 1 variable balloon - +::Debug 2 "::RosterTree::BalloonRegister key: $key jid: $jid msg: $msg" set mjid [jlib::jidmap $jid] if {$msg eq ""} { puts "\t unset -nocomplain balloon($key,$mjid)" @@ -1815,8 +1915,10 @@ proc ::RosterTree::GetParent {item} { variable T - - return [$T item parent $item] + # in case resources are shown in the roster, + # the items given may be list, therefore + # only take the first, they have the same parent + return [$T item parent [lindex $item 0]] } # RosterTree::GetItemsHeadClass -- Index: RosterPlain.tcl =================================================================== --- RosterPlain.tcl (revision 2778) +++ RosterPlain.tcl (working copy) @@ -189,8 +189,9 @@ $T style layout $S eBorder -detach 1 -iexpand xy -indent 0 set S [$T style create styAvailable] - $T style elements $S {eBorder eNotify eImage eText eAltImage1 eAltImage0} - $T style layout $S eText -squeeze x -iexpand xy -sticky w + $T style elements $S {eBorder eNotify eImage eText eNumText eAltImage1 eAltImage0} + $T style layout $S eText -squeeze x -expand ns -sticky w + $T style layout $S eNumText -expand ns -iexpand xy -sticky w $T style layout $S eImage -expand ns -minheight $minH $T style layout $S eAltImage0 -expand ns -sticky e $T style layout $S eAltImage1 -expand ns -sticky e @@ -207,7 +208,7 @@ $T style layout $S eNotify -detach 1 -iexpand xy -indent 0 -padx 2 -pady 2 set S [$T style create styEntry] - $T style elements $S {eBorder eImage eWindow} + $T style elements $S {eBorder eImage eWindow eNumText eAltImage1 eAltImage0} $T style layout $S eImage -expand ns $T style layout $S eWindow -iexpand x -expand ns $T style layout $S eBorder -detach 1 -iexpand xy -indent 0 @@ -335,6 +336,8 @@ variable tmpEdit ::RosterTree::EditEnd $tmpEdit(jid) +::Debug 2 "::RosterPlain::EditEnd" +parray tmpEdit destroy $tmpEdit(entry) unset tmpEdit } @@ -429,10 +432,12 @@ set jimage [eval {GetPresenceIcon $jid $presence} $args] set items [list] set jitems [list] + set array jitemsA + # Creates a list {item tag ?item tag? ...} for items. - set itemTagList [eval {::RosterTree::CreateItemBase $jid $presence} $args] - + set itemTagList [eval {::RosterTree::CreateItemBase [jlib::barejid $jid] $presence} $args] +::Debug 2 "::RosterPlain::CreateItem: itemTagList: $itemTagList HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH" foreach {item tag} $itemTagList { set tag0 [lindex $tag 0] set tag1 [lindex $tag 1] @@ -444,6 +449,9 @@ jid { set style $styleMap($presence) lappend jitems $item + set jitemsA($item,jid) $tag1 + set jitemsA($item,args) $args + set jitemsA($item,presence) $presence } group { set style styFolder @@ -455,15 +463,25 @@ set text [::RosterTree::MCHead $tag1] set image [::Rosticons::ThemeGet application/group-$tag1] } + resource { + set style $styleMap($presence) + jlib::splitjid $tag1 jid2 res + set text $res + set itemAttr [Jabber::Jlib roster getrosteritem $tag1] + array set presA [Jabber::Jlib roster getpresence $jid2 -resource $res] + lappend jitems $item + set jitemsA($item,jid) $tag1 + set jitemsA($item,args) $itemAttr + set jitemsA($item,presence) $presA(-type) + } } ConfigureItem $item $style $text $image } - ConfigureChildNumbersAtIdle # Design the balloon help window message. foreach item $jitems { - eval {Balloon $jid $presence $item} $args + eval {Balloon $jitemsA($item,jid) $jitemsA($item,presence) $item} $jitemsA($item,args) } return $items } @@ -483,6 +501,7 @@ # Add an extra "(#)" to each directory that shows the content. proc ::RosterPlain::ConfigureChildNumbers {} { + global jprefs variable T variable pendingChildNumbers @@ -500,9 +519,16 @@ # Update any groups. foreach item [::RosterTree::FindWithFirstTag group] { - set n [llength [$T item children $item]] + set n [$T item numchildren $item] $T item element configure $item cTree eNumText -text "($n)" } + # there may be multiple resources for a contact + foreach item [::RosterTree::FindWithFirstTag jid] { + set n [$T item numchildren $item] + if {$n > 0} { + $T item element configure $item cTree eNumText -text "($n)" + } + } } proc ::RosterPlain::ConfigureItem {item style text image} { @@ -519,7 +545,8 @@ # It is also responsible for cleaning up empty dirs etc. proc ::RosterPlain::DeleteItem {jid} { - +::CallTrace 1 +::Debug 2 "::RosterPlain::DeleteItem jid: $jid" # Sibling of '::RosterTree::CreateItemBase'. ::RosterTree::DeleteItemBase $jid @@ -558,18 +585,19 @@ # Since it makes assumptions about the elements: 'eAltImage*'. proc ::RosterPlain::SetAltImage {jid key image} { + global jprefs variable T variable altImageKeyToElem # altImageKeyToElem maps: key -> element name # # We use a static mapping: BAD? - set mjid [jlib::jidmap $jid] set tag [list jid $mjid] set item [FindWithTag $tag] + if {$item eq ""} { - return + return } if {[info exists altImageKeyToElem($key)]} { @@ -586,8 +614,6 @@ set altImageKeyToElem($key) $elem } $T item element configure $item cTree $elem -image $image - - return [list $T $item cTree $elem] } proc ::RosterPlain::FreeAltCache {} { Index: RosterTwo.tcl =================================================================== --- RosterTwo.tcl (revision 2778) +++ RosterTwo.tcl (working copy) @@ -190,17 +190,17 @@ # Defaults: set name [$jlib roster getname $jid2] - set ujid [jlib::unescapejid $jid] if {$name ne ""} { - set jtext "$name ($ujid)" + set jtext "$name ($jid2)" } else { - set jtext $ujid + set jtext $jid2 } set status [$jlib roster getstatus $jid] set since [$jlib roster availablesince $jid] set jimage [eval {GetPresenceIcon $jid $presence} $args] set items [list] set jitems [list] + set array jitemsA # Creates a list {item tag ?item tag? ...} for items. set itemTagList [eval {::RosterTree::CreateItemBase $jid $presence} $args] @@ -209,7 +209,7 @@ set tag0 [lindex $tag 0] set tag1 [lindex $tag 1] set text $jtext - set text2 "No status message" + set text2 [mc "No status message"] set image $jimage lappend items $item @@ -228,6 +228,9 @@ } } lappend jitems $item + set jitemsA($item,jid) $tag1 + set jitemsA($item,args) $args + set jitemsA($item,presence) $presence } group { set style styStd @@ -239,6 +242,24 @@ set text [::RosterTree::MCHead $tag1] set image [::Rosticons::ThemeGet application/group-$tag1] } + resource { + set style styStd + jlib::splitjid $tag1 jid2 res + # the time since the resources are available may be different + set since [$jlib roster availablesince $jid2/$res] + set time [::Utils::SmartClockFormat $since -showsecs 0] + set text $res + set text2 "($time)" + if {$status ne ""} { + append text2 " $status" + } + set itemAttr [Jabber::Jlib roster getrosteritem $tag1] + array set presA [Jabber::Jlib roster getpresence $jid2 -resource $res] + lappend jitems $item + set jitemsA($item,jid) $tag1 + set jitemsA($item,args) $itemAttr + set jitemsA($item,presence) $presA(-type) + } } ConfigureItem $item $style $text $text2 $image } @@ -247,7 +268,7 @@ # Design the balloon help window message. foreach item $jitems { - eval {Balloon $jid $presence $item} $args + eval {Balloon $jitemsA($item,jid) $jitemsA($item,presence) $item} $jitemsA($item,args) } return $items } @@ -267,6 +288,7 @@ # Add an extra "(#)" to each directory that shows the content. proc ::RosterTwo::ConfigureChildNumbers {} { + global jprefs variable T variable pendingChildNumbers @@ -286,10 +308,23 @@ # Update any groups. foreach item [::RosterTree::FindWithFirstTag group] { - set n [llength [$T item children $item]] - set htext "$n users" + set n [$T item numchildren $item] + if {$n == 1} { + set htext [mc "%s user" $n] + } else { + set htext [mc "%s users" $n] + } $T item element configure $item cTree eText2 -text $htext } + # there may be multiple resources for a contact + foreach item [::RosterTree::FindWithFirstTag jid] { + set n [$T item numchildren $item] + if {$n > 0} { + # in case resources are shown, there are always more than one + set htext [mc "%s resources" $n] + $T item element configure $item cTree eText2 -text $htext + } + } } proc ::RosterTwo::ConfigureItem {item style text text2 image} { Index: RosterAvatar.tcl =================================================================== --- RosterAvatar.tcl (revision 2778) +++ RosterAvatar.tcl (working copy) @@ -927,6 +927,10 @@ # Defaults: set jtext [eval {MakeDisplayText $jid $presence} $args] + jlib::splitjid $jid jid2 res + if {$res ne ""} { + append jtext " ($res)" + } set jimage [eval {GetPresenceIcon $jid $presence} $args] set items [list] Index: Roster.tcl =================================================================== --- Roster.tcl (revision 2778) +++ Roster.tcl (working copy) @@ -99,12 +99,6 @@ set timer(msg,ms) 10000 set timer(exitroster,secs) 0 set timer(pres,secs) 4 - - # How to display multiple available resources. - # highest-prio : only the one with highest priority - # all : all - set ::config(roster,multi-resources) "highest-prio" - #set ::config(roster,multi-resources) "all" } proc ::Roster::EarlyInitHook {} { @@ -118,7 +112,7 @@ # Standard popup menu. set mDefs { - {command mChat... {[mc "Cha&t"]...} {::Chat::StartThreadJIDList $jidL} } + {command mChat... {[mc "Cha&t"]...} {::Chat::StartThreadJIDList $type $jidL} } {command mMessage... {[mc "&Message"]...} {::NewMsg::Build -to $jid -tolist $jid2L} } {command mSendFile... {[mc "Send &File"]...} {::FTrans::SendJIDList $jidL} } {separator} @@ -449,18 +443,18 @@ # Handle popup menu in roster. # # Arguments: +# type type, one of: group, head, jid, resource # jidL this is a list of actual jid's, can be any form # # Results: # popup menu displayed -proc ::Roster::DoPopup {jidL groupL x y} { +proc ::Roster::DoPopup {type jidL groupL x y} { global wDlgs variable popMenuDefs variable regPopMenuDef variable regPopMenuType variable wtree - ::Debug 2 "::Roster::DoPopup jidL=$jidL, groupL=$groupL" # We always get a list of jids, often with only one element. @@ -507,29 +501,6 @@ set mType [concat $mType $regPopMenuType] } - # Trick to handle multiple online resources. - if {[llength $jidL] == 1} { - set resOnL [::Jabber::Jlib roster getresources $jid2 -type available] - set idx [lsearch -glob $mDef *mChat...*] - if {$idx >= 0 && [llength $resOnL] > 1} { - - set mSub [list] - set str $jid2 - append str " (" - append str [mc "Default"] - append str ")" - lappend mSub [list command test $str [list ::Chat::StartThread $jid2]] - lappend mSub [list separator] - foreach res $resOnL { - set xjid $jid2/$res - lappend mSub [list command $xjid $xjid [list ::Chat::StartThread $xjid]] - } - set mChatM [list cascade mChat... {[mc "Cha&t"]} $mSub] - set mDef [lreplace $mDef $idx $idx $mChatM] - } - } - - # Make the appropriate menu. set m $wDlgs(jpopuproster) set i 0 @@ -538,7 +509,7 @@ -postcommand [list ::Roster::PostMenuCmd $m $mType $clicked $jidL $presL] ::AMenu::Build $m $mDef \ - -varlist [list jid $jid jidL $jidL jid3 $jid3 jid2L $jid2L \ + -varlist [list type $type jid $jid jidL $jidL jid3 $jid3 jid2L $jid2L \ clicked $clicked group $groupL] # This one is needed on the mac so the menu is built before it is posted. @@ -553,6 +524,7 @@ proc ::Roster::FindClickTypesFromJIDList {jidL} { set clicked [list] +::Debug 2 "::Roster::FindClickTypesFromJIDList jidL: $jidL" foreach jid $jidL { if {[::Roster::IsTransportEx $jid]} { lappend clicked trpt @@ -742,6 +714,7 @@ # @@@ So far we preprocess the presence element to an option list. # In the future it is better not to. set opts [list -from $from -type $type -resource $res -xmldata $xmldata] +::Debug 2 "::Roster::PresenceEvent: opts: $opts" set x [list] set extras [list] foreach E [wrapper::getchildren $xmldata] { @@ -940,10 +913,10 @@ # If any available resource then put set jlib [::Jabber::GetJlib] - set rjid [$jlib roster getrosterjid $jid] +# set rjid [$jlib roster getrosterjid $jid] + set rjid $jid #set jid2 $rjid set jid2 [jlib::barejid $jid] - # Must remove all resources, and jid2 if no resources. # NB: this gets us also unavailable presence stanzas. # We MUST have the bare JID else we wont get any resources! @@ -951,9 +924,10 @@ ::RosterTree::StyleDeleteItem $rjid #set resL [$jlib roster getresources $jid2] set resL [$jlib roster getresources $rjid] - foreach res $resL { - ::RosterTree::StyleDeleteItem $jid2/$res - } +# foreach res $resL { + #::RosterTree::StyleDeleteItem $jid2/$res + ::RosterTree::StyleDeleteItem $jid +# } set items [list] set isavailable [$jlib roster isavailable $rjid] @@ -987,8 +961,10 @@ } # This minimizes the cost of sorting. + # commented out because the GetParent produced an exception + # when multiple resources per client are enabled in the roster + # the exception only showed up when there are groups in the roster if {[llength $items]} { - # If more than one item pick the parent of the first (group). set pitem [::RosterTree::GetParent [lindex $items 0]] ::RosterTree::SortAtIdle $pitem $jprefs(rost,sort) @@ -1009,50 +985,29 @@ # list of item ids added. proc ::Roster::NewAvailableItem {jid} { - global config + global jprefs + variable icons ::Debug 4 "::Roster::NewAvailableItem jid=$jid" set jlib [::Jabber::GetJlib] - + set jid2 [jlib::barejid $jid] # This gets a list '-name ... -groups ...' etc. from our roster. - set itemAttr [$jlib roster getrosteritem $jid] - - switch -- $config(roster,multi-resources) { - - "highest-prio" { - - # Add only the one with highest priority. - set jid2 [jlib::barejid $jid] - set res [$jlib roster gethighestresource $jid2] - array set presA [$jlib roster getpresence $jid2 -resource $res] - - # For online users we replace the actual resource with max priority one. - # NB1: do not duplicate resource for jid3 roster items! - # NB2: treat case with available empty resource (transports). - if {$res ne ""} { - set jid $jid2/$res - } - - set items [eval { - ::RosterTree::StyleCreateItem $jid "available" - } $itemAttr [array get presA]] - } - "all" { - - set items [list] - set resOnL [$jlib roster getresources $jid2 -type available] - foreach res $resOnL { - if {$res ne ""} { - set jid $jid2/$res - } - array unset presA - array set presA [$jlib roster getpresence $jid2 -resource $res] - lappend items [eval { - ::RosterTree::StyleCreateItem $jid "available" - } $itemAttr [array get presA]] - } - } + # group associations and the like are only related to the two-tier jid + set itemAttr [$jlib roster getrosteritem $jid2] +::Debug 2 "::Roster::NewAvailableItem: jid $jid: itemAttr: $itemAttr TTTTTTTTTTTTTTTTTTTTTTTTTT" + # Add all online resources of a contact + set items [list] + set resOnL [$jlib roster getresources $jid2 -type available] + foreach res $resOnL { + if {$res ne ""} { + set jid $jid2/$res + } + array unset presA + array set presA [$jlib roster getpresence $jid2 -resource $res] + lappend items [eval { + ::RosterTree::StyleCreateItem $jid "available" + } $itemAttr [array get presA]] } return $items } @@ -1621,13 +1576,14 @@ ttk::checkbutton $wc.showsubno -text [mc "Show contacts without any subscription"] \ -variable [namespace current]::tmpJPrefs(rost,showSubNone) - grid $wc.rmifunsub -sticky w - grid $wc.clrout -sticky w - grid $wc.dblclk -sticky w - grid $wc.rmifunsub -sticky w - grid $wc.showoff -sticky w - grid $wc.showtrpt -sticky w - grid $wc.showsubno -sticky w + grid $wc.rmifunsub -sticky w + grid $wc.clrout -sticky w + grid $wc.dblclk -sticky w + grid $wc.rmifunsub -sticky w + grid $wc.showoff -sticky w + grid $wc.showtrpt -sticky w + grid $wc.showsubno -sticky w + grid $wc.showallresources -sticky w ::balloonhelp::balloonforwindow $wc.rmifunsub [mc "You can see your contact's presence, but your contact can't see yours."] } @@ -1639,10 +1595,16 @@ #::Avatar::PrefsSave # Need to repopulate the roster? + set repopulatetree 0 if {$jprefs(rost,showOffline) != $tmpJPrefs(rost,showOffline)} { set jprefs(rost,showOffline) $tmpJPrefs(rost,showOffline) - RepopulateTree + set repopulatetree 1 } + if {$jprefs(rost,showTrpts) != $tmpJPrefs(rost,showTrpts)} { + set jprefs(rost,showTrpts) $tmpJPrefs(rost,showTrpts) + set repopulatetree 1 + } + RepopulateTree array set jprefs [array get tmpJPrefs] unset tmpJPrefs } Index: Chat.tcl =================================================================== --- Chat.tcl (revision 2778) +++ Chat.tcl (working copy) @@ -249,34 +249,41 @@ } proc ::Chat::OnMenu {} { - if {[llength [grab current]]} { return } if {[::JUI::GetConnectState] eq "connectfin"} { - set jidL [::RosterTree::GetSelectedJID] - if {[llength $jidL]} { - foreach jid $jidL { + set tagL [::RosterTree::GetSelected] + if {[llength $tagL]} { + foreach tag $tagL { + set type [lindex $tag 0] + set jid [lindex $tag 1] if {[::Jabber::RosterCmd isavailable $jid]} { - set jid2 [jlib::barejid $jid] - StartThread $jid2 + if {$type eq "resource"} { + StartThread $jid + } else { + jlib::splitjid $jid jid2 res + StartThread $jid2 + } } else { - if {[llength $jidL] == 1} { + if {[llength $tagL] == 1} { StartThreadDlg -jid $jid } } } - } else { - StartThreadDlg } } } -proc ::Chat::StartThreadJIDList {jidL} { +proc ::Chat::StartThreadJIDList {type jidL} { foreach jid $jidL { if {[::Jabber::RosterCmd isavailable $jid]} { - set jid2 [jlib::barejid $jid] - StartThread $jid2 + if {$type ne "resource"} { + set jid2 [jlib::barejid $jid] + StartThread $jid2 + } else { + StartThread $jid + } } } } @@ -442,7 +449,6 @@ proc ::Chat::StartThread {jid args} { global config jprefs - ::Debug 2 "::Chat::StartThread jid=$jid, args=$args" array set argsA $args @@ -597,9 +603,6 @@ # Try to respect any full JID so that we may chat with two separate # resources simultaneously. set chattoken [GetTokenFrom chat jid $mjid] - if {$chattoken eq ""} { - set chattoken [GetTokenFrom chat jid [jlib::ESC $mjid2]*] - } if {$chattoken eq ""} { Index: JUI.tcl =================================================================== --- JUI.tcl (revision 2778) +++ JUI.tcl (working copy) @@ -1500,7 +1500,7 @@ set tags [::RosterTree::GetSelected] if {[llength $tags] == 1} { lassign [lindex $tags 0] mtag jid - if {$mtag eq "jid"} { + if {$mtag eq "jid" || $mtag eq "resource"} { if {[::Jabber::RosterCmd isavailable $jid]} { if {![::Roster::IsTransportEx $jid]} { set state normal Index: FTrans.tcl =================================================================== --- FTrans.tcl (revision 2778) +++ FTrans.tcl (working copy) @@ -359,12 +359,22 @@ } } +# FTrans::SendHighestPrio -- +# +# Send to highest available resource with highest priority +# The highest resource may not have file transfer feature +proc ::FTrans::SendPrio {jid2} { + set res [::Jabber::Jlib roster gethighestresource $jid2] + if {$res ne ""} { + Send $jid2/$res + } +} + # FTrans::Send -- # # Initiator function. Must be 3-tier jid. proc ::FTrans::Send {jid args} { - if {[::Jabber::Jlib disco isdiscoed info $jid]} { set feature [DiscoGetFeature $jid] if {$feature eq ""} {