[Tkabber-dev] r707 - in trunk/tkabber: . ifacetk jabberlib-tclxml pixmaps/amibulb pixmaps/default pixmaps/default/services pixmaps/gabber pixmaps/gush pixmaps/jajc pixmaps/kroc pixmaps/psi plugins plugins/chat plugins/general plugins/roster plugins/unix

tkabber-svn at jabber.ru tkabber-svn at jabber.ru
Sat Sep 9 14:24:35 MSD 2006


Author: sergei
Date: 2006-09-09 14:24:10 +0400 (Sat, 09 Sep 2006)
New Revision: 707

Added:
   trunk/tkabber/pixmaps/default/services/mrim_away.gif
   trunk/tkabber/pixmaps/default/services/mrim_offline.gif
   trunk/tkabber/pixmaps/default/services/mrim_online.gif
   trunk/tkabber/plugins/roster/
   trunk/tkabber/plugins/roster/annotations.tcl
   trunk/tkabber/plugins/roster/cache_categories.tcl
   trunk/tkabber/plugins/roster/conferenceinfo.tcl
   trunk/tkabber/plugins/roster/conferences.tcl
   trunk/tkabber/plugins/roster/roster_delimiter.tcl
   trunk/tkabber/plugins/roster/rosterx.tcl
Removed:
   trunk/tkabber/plugins/general/annotations.tcl
   trunk/tkabber/plugins/general/conferenceinfo.tcl
   trunk/tkabber/plugins/general/conferences.tcl
   trunk/tkabber/plugins/general/roster_delimiter.tcl
   trunk/tkabber/plugins/general/rosterx.tcl
Modified:
   trunk/tkabber/ChangeLog
   trunk/tkabber/browser.tcl
   trunk/tkabber/custom.tcl
   trunk/tkabber/disco.tcl
   trunk/tkabber/ifacetk/iroster.tcl
   trunk/tkabber/itemedit.tcl
   trunk/tkabber/jabberlib-tclxml/jabberlib.tcl
   trunk/tkabber/messages.tcl
   trunk/tkabber/pixmaps/amibulb/icondef.xml
   trunk/tkabber/pixmaps/default/icondef.xml
   trunk/tkabber/pixmaps/gabber/icondef.xml
   trunk/tkabber/pixmaps/gush/icondef.xml
   trunk/tkabber/pixmaps/jajc/icondef.xml
   trunk/tkabber/pixmaps/kroc/icondef.xml
   trunk/tkabber/pixmaps/psi/icondef.xml
   trunk/tkabber/plugins/chat/logger.tcl
   trunk/tkabber/plugins/general/headlines.tcl
   trunk/tkabber/plugins/general/jitworkaround.tcl
   trunk/tkabber/plugins/unix/wmdock.tcl
   trunk/tkabber/roster.tcl
   trunk/tkabber/tkabber.tcl
Log:
	* browser.tcl, disco.tcl: Removed hardcoded icon names
	  for disco/browser services.

	* pixmaps/*/icondef.xml: Changed browser/* icon names to
	  match services categories and types.

	* pixmaps/default/services/mrim_*.gif,
	  pixmaps/default/icondef.xml: Added Mail.ru Instant Messenger
	  icons.

	* plugins/unix/wmdock.tcl, plugins/general/headlines.tcl:
	  Changed displayed icon names.

	* plugins/chat/logger.tcl: Made Tkabber more responsible while
	  converting or displaying chatlogs.

	* plugins/roster/, tkabber.tcl: Added new plugins directory.

	* plugins/general/annotations.tcl, plugins/general/conferenceinfo.tcl,
	  plugins/general/conferences.tcl, plugins/general/rosterx.tcl,
	  plugins/general/roster_delimiter.tcl: Moved to plugins/roster/
	  directory.

	* custom.tcl: Added store_vars procedure for convenience.

	* jabberlib-tclxml/jabberlib.tcl, roster.tcl,
	  plugins/general/jitworkaround.tcl, plugins/roster/conferences.tcl,
	  ifacetk/iroster.tcl: Don't use nonstandard way of getting
	  item category in the roster.

	* roster.tcl, messages.tcl, ifacetk/iroster.tcl: Removed
	  roster::is_user function. Forced usage of
	  roster::configure instead.

	* itemedit.tcl, plugins/roster/conferences.tcl: Made sure that
	  nickname or properties editing frame is the topmost frame of
	  the item edit window.

	* plugins/roster/cache_categories.tcl: Added new plugin, which
	  uses disco#info queries to retrieve services categories and
	  types, caches them locally and makes roster using the cached
	  information for displaying JIDs icons, menus etc.


Modified: trunk/tkabber/ChangeLog
===================================================================
--- trunk/tkabber/ChangeLog	2006-09-05 20:19:00 UTC (rev 706)
+++ trunk/tkabber/ChangeLog	2006-09-09 10:24:10 UTC (rev 707)
@@ -1,3 +1,48 @@
+2006-09-09  Sergei Golovan  <sgolovan at nes.ru>
+
+	* browser.tcl, disco.tcl: Removed hardcoded icon names
+	  for disco/browser services.
+
+	* pixmaps/*/icondef.xml: Changed browser/* icon names to
+	  match services categories and types.
+
+	* pixmaps/default/services/mrim_*.gif,
+	  pixmaps/default/icondef.xml: Added Mail.ru Instant Messenger
+	  icons.
+
+	* plugins/unix/wmdock.tcl, plugins/general/headlines.tcl:
+	  Changed displayed icon names.
+
+	* plugins/chat/logger.tcl: Made Tkabber more responsible while
+	  converting or displaying chatlogs.
+
+	* plugins/roster/, tkabber.tcl: Added new plugins directory.
+
+	* plugins/general/annotations.tcl, plugins/general/conferenceinfo.tcl,
+	  plugins/general/conferences.tcl, plugins/general/rosterx.tcl,
+	  plugins/general/roster_delimiter.tcl: Moved to plugins/roster/
+	  directory.
+
+	* custom.tcl: Added store_vars procedure for convenience.
+
+	* jabberlib-tclxml/jabberlib.tcl, roster.tcl,
+	  plugins/general/jitworkaround.tcl, plugins/roster/conferences.tcl,
+	  ifacetk/iroster.tcl: Don't use nonstandard way of getting
+	  item category in the roster.
+
+	* roster.tcl, messages.tcl, ifacetk/iroster.tcl: Removed
+	  roster::is_user function. Forced usage of
+	  roster::configure instead.
+
+	* itemedit.tcl, plugins/roster/conferences.tcl: Made sure that
+	  nickname or properties editing frame is the topmost frame of
+	  the item edit window.
+
+	* plugins/roster/cache_categories.tcl: Added new plugin, which
+	  uses disco#info queries to retrieve services categories and
+	  types, caches them locally and makes roster using the cached
+	  information for displaying JIDs icons, menus etc.
+
 2006-09-05  Sergei Golovan  <sgolovan at nes.ru>
 
 	* ifacetk/iface.tcl: Added conventional quit on closing

Modified: trunk/tkabber/browser.tcl
===================================================================
--- trunk/tkabber/browser.tcl	2006-09-05 20:19:00 UTC (rev 706)
+++ trunk/tkabber/browser.tcl	2006-09-09 10:24:10 UTC (rev 707)
@@ -227,35 +227,21 @@
 
 proc browser::item_icon {category type} {
     switch -- $category {
-	service {
-	    switch -- $type {
-		jud        { return browser/jud }
-		aim        { return browser/aim }
-		icq        { return browser/icq }
-		msn        { return browser/msn }
-		x-gadugadu { return browser/gg }
-		x-weather  { return browser/weather }
-		yahoo      { return browser/yahoo }
-		default    { return "" }
-	    }
-	}
+	service -
+	gateway -
 	application {
-	    switch -- $type {
-		x-weather { return browser/weather }
-		default   { return "" }
+	    if {[lsearch -exact [image names] browser/$type] >= 0} {
+		return browser/$type
+	    } else {
+		return ""
 	    }
 	}
-	conference {
-	    return browser/conference
-	}
-	user {
-	    return browser/user
-	}
-	headline {
-	    return browser/message
-	}
 	default {
-	    return ""
+	    if {[lsearch -exact [image names] browser/$category] >= 0} {
+		return browser/$category
+	    } else {
+		return ""
+	    }
 	}
     }
 }

Modified: trunk/tkabber/custom.tcl
===================================================================
--- trunk/tkabber/custom.tcl	2006-09-05 20:19:00 UTC (rev 706)
+++ trunk/tkabber/custom.tcl	2006-09-09 10:24:10 UTC (rev 707)
@@ -661,6 +661,16 @@
     catch {file attributes ~/.tkabber/custom.tcl -permissions 00600}
 }
 
+proc custom::store_vars {args} {
+    variable saved
+
+    foreach varname $args {
+	set saved($varname) [set $varname]
+    }
+
+    store
+}
+
 proc custom::restore {} {
     variable var
     variable saved

Modified: trunk/tkabber/disco.tcl
===================================================================
--- trunk/tkabber/disco.tcl	2006-09-05 20:19:00 UTC (rev 706)
+++ trunk/tkabber/disco.tcl	2006-09-09 10:24:10 UTC (rev 707)
@@ -839,49 +839,21 @@
 
 proc disco::browser::item_icon {category type} {
     switch -- $category {
-	gateway {
-	    switch -- $type {
-		aim        { return browser/aim }
-		icq        { return browser/icq }
-		msn        { return browser/msn }
-		yahoo      { return browser/yahoo }
-		x-gadugadu { return browser/gg }
-		default    { return ""}
-	    }
-	}
-	service {
-	    switch -- $type {
-		jud        { return browser/jud }
-		aim        { return browser/aim }
-		icq        { return browser/icq }
-		msn        { return browser/msn }
-		x-gadugadu { return browser/gg }
-		x-weather  { return browser/weather }
-		yahoo      { return browser/yahoo }
-		default    { return "" }
-	    }
-	}
+	service -
+	gateway -
 	application {
-	    switch -- $type {
-		x-weather { return browser/weather }
-		default   { return "" }
+	    if {[lsearch -exact [image names] browser/$type] >= 0} {
+		return browser/$type
+	    } else {
+		return ""
 	    }
 	}
-	conference {
-	    return browser/conference
-	}
-	user -
-	client {
-	    return browser/user
-	}
-	directory {
-	    return browser/jud
-	}
-	headline {
-	    return browser/message
-	}
 	default {
-	    return ""
+	    if {[lsearch -exact [image names] browser/$category] >= 0} {
+		return browser/$category
+	    } else {
+		return ""
+	    }
 	}
     }
 }

Modified: trunk/tkabber/ifacetk/iroster.tcl
===================================================================
--- trunk/tkabber/ifacetk/iroster.tcl	2006-09-05 20:19:00 UTC (rev 706)
+++ trunk/tkabber/ifacetk/iroster.tcl	2006-09-09 10:24:10 UTC (rev 707)
@@ -203,7 +203,7 @@
 
 hook::add predisconnected_hook [namespace current]::roster::set_group_lists
 
-proc roster::process_item {connid jid name groups subsc ask category subtype} {
+proc roster::process_item {connid jid name groups subsc ask} {
     after cancel [namespace parent]::update_chat_titles
     after idle [namespace parent]::update_chat_titles
 }
@@ -1187,7 +1187,7 @@
 }
 
 proc roster::is_online {connid jid} {
-    if {[::roster::is_user $connid $jid]} {
+    if {[::roster::itemconfig $connid $jid -isuser]} {
 	switch -- [get_user_aliases_status $connid $jid] {
 	    unavailable {return 0}
 	    default {return 1}

Modified: trunk/tkabber/itemedit.tcl
===================================================================
--- trunk/tkabber/itemedit.tcl	2006-09-05 20:19:00 UTC (rev 706)
+++ trunk/tkabber/itemedit.tcl	2006-09-09 10:24:10 UTC (rev 707)
@@ -22,10 +22,11 @@
     pack $f.gr -side top -expand yes -fill both
 
 
-    TitleFrame $g.available -text [::msgcat::mc "Available groups"]
-    pack $g.available -side left -expand yes -fill both
-    set ga [$g.available getframe]
+    set ga [frame $g.available]
+    pack $ga -side left -expand yes -fill both
 
+    label $ga.title -text [::msgcat::mc "Available groups"]
+    pack $ga.title -side top -anchor w
     frame $ga.gr
     label $ga.gr.lab -text [::msgcat::mc "Group:"]
     set gae [entry $ga.gr.oup]
@@ -39,10 +40,11 @@
     pack $gasw -side top -expand yes -fill both
 
 
-    TitleFrame $g.current -text [::msgcat::mc "Current groups"]
-    pack $g.current -side right -expand yes -fill both
-    set gc [$g.current getframe]
+    set gc [frame $g.current]
+    pack $gc -side right -expand yes -fill both
 
+    label $gc.title -text [::msgcat::mc "Current groups"]
+    pack $gc.title -side top -anchor w
     set gcsw [ScrolledWindow $gc.grouplist_sw]
     set gcl [listbox $gc.grouplist]
     $gcsw setwidget $gcl
@@ -83,7 +85,12 @@
     variable gra_name
 
     set tf [TitleFrame $f.name -text [format [::msgcat::mc "Edit nickname for %s"] $jid]]
-    pack $tf -side top -expand yes -fill both
+    set slaves [pack slaves $f]
+    if {$slaves == ""} {
+	pack $tf -side top -expand yes -fill both
+    } else {
+	pack $tf -side top -expand yes -fill both -before [lindex $slaves 0]
+    }
     set g [$tf getframe]
 
     label $g.lname -text [::msgcat::mc "Nickname:"]

Modified: trunk/tkabber/jabberlib-tclxml/jabberlib.tcl
===================================================================
--- trunk/tkabber/jabberlib-tclxml/jabberlib.tcl	2006-09-05 20:19:00 UTC (rev 706)
+++ trunk/tkabber/jabberlib-tclxml/jabberlib.tcl	2006-09-09 10:24:10 UTC (rev 707)
@@ -1147,12 +1147,6 @@
 		set name  [wrapper:getattr $cvars name]
 		set subsc [wrapper:getattr $cvars subscription]
 		set ask   [wrapper:getattr $cvars ask]
-		if {$ctag != {item}} {
-		    set category $ctag
-		} else {
-		    set category [wrapper:getattr $cvars category]
-		}
-		set subtype [wrapper:getattr $cvars type]
 		
 		foreach subchild $cchildren {
 		    wrapper:splitxml $subchild subtag tmp tmp subchdata tmp
@@ -1184,10 +1178,10 @@
 		}
 		if $ispush {
 		    eval [list client roster_push $connid $jid $name $groups \
-			       $subsc $ask $category $subtype] $param
+			       $subsc $ask] $param
 		} else {
 		    eval [list client roster_item $connid $jid $name $groups \
-			       $subsc $ask $category $subtype] $param
+			       $subsc $ask] $param
 		}
 	    }
 	}
@@ -1744,5 +1738,5 @@
 # Now that we're done...
 #
 
-package provide jabberlib 0.9.0
+package provide jabberlib 0.9.1
 

Modified: trunk/tkabber/messages.tcl
===================================================================
--- trunk/tkabber/messages.tcl	2006-09-05 20:19:00 UTC (rev 706)
+++ trunk/tkabber/messages.tcl	2006-09-09 10:24:10 UTC (rev 707)
@@ -502,7 +502,7 @@
     set body [$mw.body get 1.0 {end -1 chars}]
 
     foreach jid $jids {
-	if {!$group || [roster::is_user $connid $jid]} {
+	if {!$group || [::roster::itemconfig $connid $jid -isuser]} {
 	    send_msg $jid -type normal \
 		-subject $subj -body $body \
 		-connection $connid
@@ -680,7 +680,7 @@
 
 ###############################################################################
 
-proc message::destroy_subscription_dialogs {connid jid name groups subsc ask category subtype} {
+proc message::destroy_subscription_dialogs {connid jid name groups subsc ask} {
     switch -- $subsc {
 	both -
 	from {}

Modified: trunk/tkabber/pixmaps/amibulb/icondef.xml
===================================================================
--- trunk/tkabber/pixmaps/amibulb/icondef.xml	2006-09-05 20:19:00 UTC (rev 706)
+++ trunk/tkabber/pixmaps/amibulb/icondef.xml	2006-09-09 10:24:10 UTC (rev 707)
@@ -29,6 +29,10 @@
   </icon>
   <!-- Browser and Disco icons -->
   <icon>
+    <image xmlns='tkimage'>browser/client</image>
+    <object mime="image/gif">roster/available.gif</object>
+  </icon>
+  <icon>
     <image xmlns='tkimage'>browser/user</image>
     <object mime="image/gif">roster/available.gif</object>
   </icon>

Modified: trunk/tkabber/pixmaps/default/icondef.xml
===================================================================
--- trunk/tkabber/pixmaps/default/icondef.xml	2006-09-05 20:19:00 UTC (rev 706)
+++ trunk/tkabber/pixmaps/default/icondef.xml	2006-09-09 10:24:10 UTC (rev 707)
@@ -65,6 +65,10 @@
   </icon>
   <!-- Browser and Disco icons -->
   <icon>
+    <image xmlns='tkimage'>browser/client</image>
+    <object mime="image/gif">roster/available.gif</object>
+  </icon>
+  <icon>
     <image xmlns='tkimage'>browser/user</image>
     <object mime="image/gif">roster/available.gif</object>
   </icon>
@@ -73,10 +77,14 @@
     <object mime="image/gif">roster/conference-available.gif</object>
   </icon>
   <icon>
-    <image xmlns='tkimage'>browser/message</image>
+    <image xmlns='tkimage'>browser/headline</image>
     <object mime="image/gif">services/rss_online.gif</object>
   </icon>
   <icon>
+    <image xmlns='tkimage'>browser/directory</image>
+    <object mime="image/gif">services/jud.gif</object>
+  </icon>
+  <icon>
     <image xmlns='tkimage'>browser/jud</image>
     <object mime="image/gif">services/jud.gif</object>
   </icon>
@@ -89,6 +97,10 @@
     <object mime="image/gif">services/icq_online.gif</object>
   </icon>
   <icon>
+    <image xmlns='tkimage'>browser/mrim</image>
+    <object mime="image/gif">services/mrim_online.gif</object>
+  </icon>
+  <icon>
     <image xmlns='tkimage'>browser/msn</image>
     <object mime="image/gif">services/msn_online.gif</object>
   </icon>
@@ -97,11 +109,11 @@
     <object mime="image/gif">services/yahoo_online.gif</object>
   </icon>
   <icon>
-    <image xmlns='tkimage'>browser/gg</image>
+    <image xmlns='tkimage'>browser/x-gadugadu</image>
     <object mime="image/gif">services/gg_online.gif</object>
   </icon>
   <icon>
-    <image xmlns='tkimage'>browser/weather</image>
+    <image xmlns='tkimage'>browser/x-weather</image>
     <object mime="image/gif">services/weather_online.gif</object>
   </icon>
   <!-- Docking icons -->
@@ -392,6 +404,31 @@
     <image xmlns='tkimage'>services/yahoo/xa</image>
     <object mime="image/gif">services/yahoo_xa.gif</object>
   </icon>
+  <!-- MRIM -->
+  <icon>
+    <image xmlns='tkimage'>services/mrim/away</image>
+    <object mime="image/gif">services/mrim_away.gif</object>
+  </icon>
+  <icon>
+    <image xmlns='tkimage'>services/mrim/chat</image>
+    <object mime="image/gif">services/mrim_online.gif</object>
+  </icon>
+  <icon>
+    <image xmlns='tkimage'>services/mrim/dnd</image>
+    <object mime="image/gif">services/mrim_away.gif</object>
+  </icon>
+  <icon>
+    <image xmlns='tkimage'>services/mrim/unavailable</image>
+    <object mime="image/gif">services/mrim_offline.gif</object>
+  </icon>
+  <icon>
+    <image xmlns='tkimage'>services/mrim/available</image>
+    <object mime="image/gif">services/mrim_online.gif</object>
+  </icon>
+  <icon>
+    <image xmlns='tkimage'>services/mrim/xa</image>
+    <object mime="image/gif">services/mrim_away.gif</object>
+  </icon>
   <!-- Chat window bookmark -->
   <icon>
     <image xmlns='tkimage'>chat/bookmark</image>

Added: trunk/tkabber/pixmaps/default/services/mrim_away.gif
===================================================================
(Binary files differ)


Property changes on: trunk/tkabber/pixmaps/default/services/mrim_away.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/tkabber/pixmaps/default/services/mrim_offline.gif
===================================================================
(Binary files differ)


Property changes on: trunk/tkabber/pixmaps/default/services/mrim_offline.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/tkabber/pixmaps/default/services/mrim_online.gif
===================================================================
(Binary files differ)


Property changes on: trunk/tkabber/pixmaps/default/services/mrim_online.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Modified: trunk/tkabber/pixmaps/gabber/icondef.xml
===================================================================
--- trunk/tkabber/pixmaps/gabber/icondef.xml	2006-09-05 20:19:00 UTC (rev 706)
+++ trunk/tkabber/pixmaps/gabber/icondef.xml	2006-09-09 10:24:10 UTC (rev 707)
@@ -29,6 +29,10 @@
   </icon>
   <!-- Browser and Disco icons -->
   <icon>
+    <image xmlns='tkimage'>browser/client</image>
+    <object mime="image/gif">roster/available.gif</object>
+  </icon>
+  <icon>
     <image xmlns='tkimage'>browser/user</image>
     <object mime="image/gif">roster/available.gif</object>
   </icon>
@@ -37,10 +41,14 @@
     <object mime="image/gif">roster/conference-available.gif</object>
   </icon>
   <icon>
-    <image xmlns='tkimage'>browser/message</image>
+    <image xmlns='tkimage'>browser/headline</image>
     <object mime="image/gif">services/rss_online.gif</object>
   </icon>
   <icon>
+    <image xmlns='tkimage'>browser/directory</image>
+    <object mime="image/gif">services/jud.gif</object>
+  </icon>
+  <icon>
     <image xmlns='tkimage'>browser/jud</image>
     <object mime="image/gif">services/jud.gif</object>
   </icon>

Modified: trunk/tkabber/pixmaps/gush/icondef.xml
===================================================================
--- trunk/tkabber/pixmaps/gush/icondef.xml	2006-09-05 20:19:00 UTC (rev 706)
+++ trunk/tkabber/pixmaps/gush/icondef.xml	2006-09-09 10:24:10 UTC (rev 707)
@@ -29,6 +29,10 @@
   </icon>
   <!-- Browser and Disco icons -->
   <icon>
+    <image xmlns='tkimage'>browser/client</image>
+    <object mime="image/gif">roster/available.gif</object>
+  </icon>
+  <icon>
     <image xmlns='tkimage'>browser/user</image>
     <object mime="image/gif">roster/available.gif</object>
   </icon>

Modified: trunk/tkabber/pixmaps/jajc/icondef.xml
===================================================================
--- trunk/tkabber/pixmaps/jajc/icondef.xml	2006-09-05 20:19:00 UTC (rev 706)
+++ trunk/tkabber/pixmaps/jajc/icondef.xml	2006-09-09 10:24:10 UTC (rev 707)
@@ -29,6 +29,10 @@
   </icon>
   <!-- Browser and Disco icons -->
   <icon>
+    <image xmlns='tkimage'>browser/client</image>
+    <object mime="image/gif">roster/available.gif</object>
+  </icon>
+  <icon>
     <image xmlns='tkimage'>browser/user</image>
     <object mime="image/gif">roster/available.gif</object>
   </icon>
@@ -37,6 +41,10 @@
     <object mime="image/gif">roster/conference-available.gif</object>
   </icon>
   <icon>
+    <image xmlns='tkimage'>browser/directory</image>
+    <object mime="image/gif">services/jud.gif</object>
+  </icon>
+  <icon>
     <image xmlns='tkimage'>browser/jud</image>
     <object mime="image/gif">services/jud.gif</object>
   </icon>

Modified: trunk/tkabber/pixmaps/kroc/icondef.xml
===================================================================
--- trunk/tkabber/pixmaps/kroc/icondef.xml	2006-09-05 20:19:00 UTC (rev 706)
+++ trunk/tkabber/pixmaps/kroc/icondef.xml	2006-09-09 10:24:10 UTC (rev 707)
@@ -58,6 +58,10 @@
   </icon>
   <!-- Browser and Disco icons -->
   <icon>
+    <image xmlns='tkimage'>browser/client</image>
+    <object mime="image/gif">roster/available.gif</object>
+  </icon>
+  <icon>
     <image xmlns='tkimage'>browser/user</image>
     <object mime="image/gif">roster/available.gif</object>
   </icon>
@@ -66,10 +70,14 @@
     <object mime="image/gif">roster/conference-available.gif</object>
   </icon>
   <icon>
-    <image xmlns='tkimage'>browser/message</image>
+    <image xmlns='tkimage'>browser/headline</image>
     <object mime="image/gif">services/rss_online.gif</object>
   </icon>
   <icon>
+    <image xmlns='tkimage'>browser/directory</image>
+    <object mime="image/gif">services/jud.gif</object>
+  </icon>
+  <icon>
     <image xmlns='tkimage'>browser/jud</image>
     <object mime="image/gif">services/jud.gif</object>
   </icon>
@@ -90,11 +98,11 @@
     <object mime="image/gif">services/yahoo_online.gif</object>
   </icon>
   <icon>
-    <image xmlns='tkimage'>browser/gg</image>
+    <image xmlns='tkimage'>browser/x-gadugadu</image>
     <object mime="image/gif">services/gg_online.gif</object>
   </icon>
   <icon>
-    <image xmlns='tkimage'>browser/weather</image>
+    <image xmlns='tkimage'>browser/x-weather</image>
     <object mime="image/gif">services/weather_online.gif</object>
   </icon>
   <!-- Docking icons -->

Modified: trunk/tkabber/pixmaps/psi/icondef.xml
===================================================================
--- trunk/tkabber/pixmaps/psi/icondef.xml	2006-09-05 20:19:00 UTC (rev 706)
+++ trunk/tkabber/pixmaps/psi/icondef.xml	2006-09-09 10:24:10 UTC (rev 707)
@@ -29,6 +29,10 @@
   </icon>
   <!-- Browser and Disco icons -->
   <icon>
+    <image xmlns='tkimage'>browser/client</image>
+    <object mime="image/gif">roster/available.gif</object>
+  </icon>
+  <icon>
     <image xmlns='tkimage'>browser/user</image>
     <object mime="image/gif">roster/available.gif</object>
   </icon>

Modified: trunk/tkabber/plugins/chat/logger.tcl
===================================================================
--- trunk/tkabber/plugins/chat/logger.tcl	2006-09-05 20:19:00 UTC (rev 706)
+++ trunk/tkabber/plugins/chat/logger.tcl	2006-09-09 10:24:10 UTC (rev 707)
@@ -257,7 +257,6 @@
 	    $l insert end "\n"
 	}
     }
-    $l see end
     $l configure -state disabled
 }
 
@@ -269,11 +268,13 @@
 	draw_messages $l {} $mynick
 	foreach m [lsort -increasing [get_subdirs $logfile]] {
 	    add_messages $l [read_hist_from_file $logfile $m] $mynick
+	    update
 	}
 	add_messages $l [read_hist_from_file $logfile [::msgcat::mc "Current"]] $mynick
     } else {
 	draw_messages $l [read_hist_from_file $logfile $month] $mynick
     }
+    $l see end
 }
 
 proc ::logger::read_hist_from_file {logfile month} {
@@ -329,6 +330,7 @@
 	    puts $fd [list $vars]
 	}
 	close $fd
+	update
     }
 
     set fd [open $logfile w]

Deleted: trunk/tkabber/plugins/general/annotations.tcl
===================================================================
--- trunk/tkabber/plugins/general/annotations.tcl	2006-09-05 20:19:00 UTC (rev 706)
+++ trunk/tkabber/plugins/general/annotations.tcl	2006-09-09 10:24:10 UTC (rev 707)
@@ -1,310 +0,0 @@
-# $Id$
-
-# JEP-0145 Annotations support
-
-namespace eval annotations {
-    # variable to store roster notes
-    array set notes {}
-
-    variable NS
-    set NS(private) "jabber:iq:private"
-    set NS(rosternotes) "storage:rosternotes"
-}
-
-proc annotations::free_notes {connid} {
-    variable notes
-
-    array unset notes $connid,*
-}
-
-hook::add disconnected_hook [namespace current]::annotations::free_notes
-
-proc annotations::request_notes {connid} {
-    variable NS
-    variable notes
-
-    jlib::send_iq get \
-	[jlib::wrapper:createtag query \
-	     -vars [list xmlns $NS(private)] \
-	     -subtags [list [jlib::wrapper:createtag storage \
-				 -vars [list xmlns $NS(rosternotes)]]]] \
-	-command [list [namespace current]::process_notes $connid] \
-	-connection $connid
-}
-
-hook::add connected_hook [namespace current]::annotations::request_notes
-
-proc annotations::process_notes {connid res child} {
-    variable NS
-    variable notes
-
-    if {$res != "OK"} return
-
-    array set notes {}
-
-    jlib::wrapper:splitxml $child tag vars isempty cdata children
-
-    foreach ch $children {
-	jlib::wrapper:splitxml $ch tag1 vars1 isempty1 cdata1 children1
-
-	if {[jlib::wrapper:getattr $vars1 xmlns] == $NS(rosternotes)} {
-	    foreach note $children1 {
-		jlib::wrapper:splitxml $note ntag nvars nisempty ncdata nchildren
-
-		set jid [jlib::wrapper:getattr $nvars jid]
-		set cdate [jlib::wrapper:getattr $nvars cdate]
-		set mdate [jlib::wrapper:getattr $nvars mdate]
-		set notes($connid,jid,$jid) $jid
-		if {![catch { scan_time $cdate } cdate]} {
-		    set notes($connid,cdate,$jid) $cdate
-		}
-		if {![catch { scan_time $mdate } mdate]} {
-		    set notes($connid,mdate,$jid) $mdate
-		}
-		set notes($connid,note,$jid) $ncdata
-	    
-	    }
-	}
-    }
-}
-
-proc annotations::scan_time {timestamp} {
-    if {[regexp {(.*)T(.*)Z} $timestamp -> date time]} {
-	return [clock scan "$date $time" -gmt true]
-    } else {
-	return [clock scan $timestamp -gmt true]
-    }
-}
-
-proc annotations::cleanup_and_store_notes {connid} {
-    variable notes
-
-    set roster_jids {}
-    foreach rjid [roster::get_jids $connid] {
-	lappend roster_jids [node_and_server_from_jid $rjid]
-    }
-
-    foreach idx [array names notes $connid,jid,*] {
-	set jid $notes($idx)
-	if {[lsearch -exact $roster_jids $jid] < 0 || \
-		![info exists notes($connid,note,$jid)] || \
-		$notes($connid,note,$jid) == ""} {
-	    catch { unset notes($connid,jid,$jid) }
-	    catch { unset notes($connid,cdate,$jid) }
-	    catch { unset notes($connid,mdate,$jid) }
-	    catch { unset notes($connid,note,$jid) }
-	}
-    }
-
-    store_notes $connid
-}
-
-proc annotations::store_notes {connid} {
-    variable NS
-    variable notes
-
-    set notelist {}
-    foreach idx [array names notes $connid,jid,*] {
-	set jid $notes($idx)
-
-	set vars [list jid $jid]
-	if {[info exists notes($connid,cdate,$jid)]} {
-	    set cdate [clock format $notes($connid,cdate,$jid) \
-			     -format "%Y-%m-%dT%TZ" -gmt true]
-	}
-	lappend vars cdate $cdate
-	if {[info exists notes($connid,mdate,$jid)]} {
-	    set mdate [clock format $notes($connid,mdate,$jid) \
-			     -format "%Y-%m-%dT%TZ" -gmt true]
-	}
-	lappend vars mdate $mdate
-	if {[info exists notes($connid,note,$jid)] && \
-		$notes($connid,note,$jid) != ""} {
-	    lappend notelist \
-		[jlib::wrapper:createtag note \
-		     -vars $vars \
-		     -chdata $notes($connid,note,$jid)]
-	}
-    }
-
-    jlib::send_iq set \
-	[jlib::wrapper:createtag query \
-	     -vars [list xmlns $NS(private)] \
-	     -subtags [list [jlib::wrapper:createtag storage \
-				 -vars [list xmlns $NS(rosternotes)] \
-				 -subtags $notelist]]] \
-	-command [list [namespace current]::store_notes_result $connid] \
-	-connection $connid
-}
-
-proc annotations::store_notes_result {connid res child} {
-
-    if {$res == "OK"} return
-
-    if {[winfo exists .store_notes_error]} {
-	destroy .store_notes_error
-    }
-    MessageDlg .store_notes_error -aspect 50000 -icon error \
-	-message [format [::msgcat::mc "Storing roster notes failed: %s"] \
-			 [error_to_string $child]] \
-	-type user -buttons ok -default 0 -cancel 0
-}
-
-proc annotations::add_user_popup_info {infovar connid jid} {
-    variable notes
-    upvar 0 $infovar info
-
-    set jid [node_and_server_from_jid $jid]
-
-    if {[info exists notes($connid,note,$jid)] && \
-	    $notes($connid,note,$jid) != ""} {
-	append info "\n\tNote:\t"
-	append info [string map [list "\n" "\n\t\t"] "$notes($connid,note,$jid)"]
-
-	if {0} {
-	    if {[info exists notes($connid,cdate,$jid)]} {
-		append info [format "\n\tNote created: %s" \
-				 [clock format $notes($connid,cdate,$jid) \
-					-format "%Y-%m-%d %T" -gmt false]]
-	    }
-	    if {[info exists notes($connid,mdate,$jid)]} {
-		append info [format "\n\tNote modified: %s" \
-				 [clock format $notes($connid,mdate,$jid) \
-					-format "%Y-%m-%d %T" -gmt false]]
-	    }
-	}
-    }
-}
-
-hook::add roster_user_popup_info_hook \
-    [namespace current]::annotations::add_user_popup_info 80
-
-proc annotations::show_dialog {connid jid} {
-    variable notes
-    global font
-
-    set jid [node_and_server_from_jid $jid]
-
-    set allowed_name [jid_to_tag $jid]
-    set w .note_edit_${connid}_$allowed_name
-
-    if {[winfo exists $w]} {
-	destroy $w
-    }
-
-    Dialog $w -title [format [::msgcat::mc "Edit roster notes for %s"] $jid] \
-	-modal none -separator 1 -anchor e \
-	-default 0 -cancel 1
-
-    $w add -text [::msgcat::mc "Store"] \
-	-command [list [namespace current]::commit_changes $w $connid $jid]
-    $w add -text [::msgcat::mc "Cancel"] -command [list destroy $w]
-
-    set f [$w getframe]
-
-    if {[info exists notes($connid,cdate,$jid)]} {
-	label $f.cdate -text [format [::msgcat::mc "Created: %s"] \
-				     [clock format $notes($connid,cdate,$jid) \
-					    -format "%Y-%m-%d %T" -gmt false]]
-	pack $f.cdate -side top -anchor w
-    }
-
-    if {[info exists notes($connid,mdate,$jid)]} {
-	label $f.mdate -text [format [::msgcat::mc "Modified: %s"] \
-				     [clock format $notes($connid,mdate,$jid) \
-					    -format "%Y-%m-%d %T" -gmt false]]
-	pack $f.mdate -side top -anchor w
-    }
-
-    ScrolledWindow $f.sw
-    pack $f.sw -side top -expand yes -fill both
-    textUndoable $f.note -width 50 -height 5 -wrap word -font $font
-    if {[info exists notes($connid,note,$jid)]} {
-	$f.note insert 0.0 $notes($connid,note,$jid)
-    }
-    $f.sw setwidget $f.note
-
-    bind $f.note <Control-Key-Return> "$w invoke default
-				       break"
-    bind $w <Key-Return> { }
-    bind $w <Control-Key-Return> "$w invoke default
-				  break"
-
-    $w draw $f.note
-}
-
-proc annotations::commit_changes {w connid jid} {
-    variable notes
-
-    set text [$w getframe].note
-
-    set date [clock seconds]
-
-    set notes($connid,jid,$jid) $jid
-    if {![info exists notes($connid,cdate,$jid)]} {
-	set notes($connid,cdate,$jid) $date
-    }
-    set notes($connid,mdate,$jid) $date
-    set notes($connid,note,$jid) [$text get 0.0 "end -1 char"]
-
-    cleanup_and_store_notes $connid
-
-    destroy $w
-}
-
-proc annotations::prefs_user_menu {m connid jid} {
-    set rjid [roster::find_jid $connid $jid]
-    $m add command -label [::msgcat::mc "Edit item notes..."] \
-	-command [list [namespace current]::show_dialog $connid $rjid]
-}
-
-hook::add chat_create_user_menu_hook \
-    [namespace current]::annotations::prefs_user_menu 76
-hook::add roster_conference_popup_menu_hook \
-    [namespace current]::annotations::prefs_user_menu 76
-hook::add roster_service_popup_menu_hook \
-    [namespace current]::annotations::prefs_user_menu 76
-hook::add roster_jid_popup_menu_hook \
-    [namespace current]::annotations::prefs_user_menu 76
-
-proc annotations::note_page {tab connid jid editable} {
-    variable notes
-    global font
-
-    if {$editable} return
-
-    set jid [node_and_server_from_jid $jid]
-
-    if {![info exists notes($connid,note,$jid)] || \
-	    $notes($connid,note,$jid) == ""} {
-	return
-    }
-
-    set notestab [$tab insert end notes -text [::msgcat::mc "Notes"]]
-    set n [userinfo::pack_frame $notestab.notes [::msgcat::mc "Roster Notes"]]
-
-    if {[info exists notes($connid,cdate,$jid)]} {
-	label $n.cdate -text [format [::msgcat::mc "Created: %s"] \
-				     [clock format $notes($connid,cdate,$jid) \
-					    -format "%Y-%m-%d %T" -gmt false]]
-	pack $n.cdate -side top -anchor w
-    }
-
-    if {[info exists notes($connid,mdate,$jid)]} {
-	label $n.mdate -text [format [::msgcat::mc "Modified: %s"] \
-				     [clock format $notes($connid,mdate,$jid) \
-					    -format "%Y-%m-%d %T" -gmt false]]
-	pack $n.mdate -side top -anchor w
-    }
-
-    set sw [ScrolledWindow $n.sw -scrollbar vertical]
-    text $n.text -font $font -height 12 -wrap word
-    $sw setwidget $n.text
-    $n.text insert 0.0 $notes($connid,note,$jid)
-    $n.text configure -state disabled
-    pack $sw -side top -fill both -expand yes
-    pack $n -fill both -expand yes
-}
-
-hook::add userinfo_hook [namespace current]::annotations::note_page 40
-

Deleted: trunk/tkabber/plugins/general/conferenceinfo.tcl
===================================================================
--- trunk/tkabber/plugins/general/conferenceinfo.tcl	2006-09-05 20:19:00 UTC (rev 706)
+++ trunk/tkabber/plugins/general/conferenceinfo.tcl	2006-09-09 10:24:10 UTC (rev 707)
@@ -1,175 +0,0 @@
-# $Id$
-
-namespace eval conferenceinfo {
-    custom::defgroup ConferenceInfo \
-	[::msgcat::mc "Options for Conference Info module, that allows you to see list of\
-participants in roster popup, regardless of whether you are currently joined\
-with the conference."] \
-	-group Tkabber \
-	-tag "Conference Info"
-
-    custom::defvar options(autoask) 0 \
-	[::msgcat::mc "Use this module"] -group ConferenceInfo -type boolean \
-	-command [namespace current]::ask
-    custom::defvar options(interval) 2 \
-	[::msgcat::mc "Interval (in minutes) between requests of participants list."] \
-	-type integer -group ConferenceInfo
-    custom::defvar options(err_interval) 60 \
-	[::msgcat::mc "Interval (in minutes) after error reply on request of participants list."] \
-	-type integer -group ConferenceInfo
-}
-
-
-# TODO: connid
-proc conferenceinfo::add_user_popup_info {infovar connid jid} {
-    variable data
-    variable options
-    upvar 0 $infovar info
-
-    if {!$options(autoask)} return
-    if {[info exists chat::opened([chat::chatid $connid $jid])]} return
-
-    if {![info exists data(error_browse,$jid)] || \
-	    ![info exists data(error_disco,$jid)]} return
-
-    if {$data(error_disco,$jid) != "" && $data(error_browse,$jid) != ""} {
-	if {$data(error_browse_code,$jid) != "feature-not-implemented"} {
-	    set errstr $data(error_browse,$jid)
-	} else {
-	    set errstr $data(error_disco,$jid)
-	}
-	append info [format [::msgcat::mc "\n\tCan't browse: %s"] $errstr]
-    } else {
-	if {$data(error_browse,$jid) == ""} {
-	    set mech browse
-	} else {
-	    set mech disco
-	}
-	if {$data(users_$mech,$jid) != {}} {
-	    append info \
-		[format [::msgcat::mc "\nRoom participants at %s:"] \
-		     [clock format $data(time_$mech,$jid) -format %R]]
-	    foreach name $data(users_$mech,$jid) {
-		append info "\n\t$name"
-	    }
-	} else {
-	    append info \
-		[format [::msgcat::mc "\nRoom is empty at %s"] \
-		     [clock format $data(time_$mech,$jid) -format %R]]
-	}
-    }
-}
-hook::add roster_user_popup_info_hook \
-    [namespace current]::conferenceinfo::add_user_popup_info
-
-
-proc conferenceinfo::ask {args} {
-    variable options
-    variable data
-
-    if {!$options(autoask)} return
-
-    foreach connid [jlib::connections] {
-	if {[catch { set roster::roster(jids,$connid) } jids]} {
-	    continue
-	}
-	foreach jid $jids {
-	    lassign [roster::get_category_and_subtype $connid $jid] \
-		category type
-	    if {$category == "conference" && [node_from_jid $jid] != "" && \
-		    ![info exists chat::opened([chat::chatid $connid $jid])]} {
-	    
-		set sec [clock seconds]
- 
-		if {![info exists data(error_browse,$jid)] || \
-			$data(error_browse,$jid) == "" || \
-			$sec - $data(time_browse,$jid) >= $options(err_interval) * 60} {
-
-		    jlib::send_iq get \
-			[jlib::wrapper:createtag query \
-			     -vars {xmlns jabber:iq:browse}] \
-			-to $jid \
-			-connection $connid \
-			-command [list [namespace current]::receive $jid browse]
-		}
-
-		if {![info exists data(error_disco,$jid)] || \
-			$data(error_disco,$jid) == "" || \
-			$sec - $data(time_disco,$jid) >= $options(err_interval) * 60} {
-
-		    jlib::send_iq get \
-			[jlib::wrapper:createtag query \
-			     -vars [list xmlns $::NS(disco_items)]] \
-			-to $jid \
-			-connection $connid \
-			-command [list [namespace current]::receive $jid disco]
-		}
-	    }
-	}
-    }
-
-    after cancel [list [namespace current]::ask]
-    after [expr {$options(interval) * 60 * 1000}] [list [namespace current]::ask]
-}
-
-proc conferenceinfo::receive {jid mech res child} {
-    variable options
-    variable data
-
-    set data(error_$mech,$jid) ""
-    set data(error_${mech}_code,$jid) ""
-    set data(time_$mech,$jid) [clock seconds]
-    set data(users_$mech,$jid) {}
-
-    if {$res != "OK"} {
-	set data(error_${mech}_code,$jid) [lindex [error_type_condition $child] 1]
-	set data(error_$mech,$jid) [error_to_string $child]
-	return
-    }
-
-    jlib::wrapper:splitxml $child tag vars isempty chdata children
-
-    foreach item $children {
-	jlib::wrapper:splitxml $item tag1 vars1 isempty1 chdata1 children1
-	switch -- $mech {
-	    browse {
-		if {$tag1 == "user" || ($tag1 == "item" && \
-			[jlib::wrapper:getattr $vars1 category] == "user")} {
-		    set name [jlib::wrapper:getattr $vars1 name]
-		    if {$name != ""} {
-			lappend data(users_browse,$jid) $name
-		    }
-		}
-	    }
-	    disco {
-		if {$tag1 == "item"} {
-		    set node [jlib::wrapper:getattr $vars1 node]
-		    set name [jlib::wrapper:getattr $vars1 name]
-		    if {$name != "" && $node == ""} {
-			lappend data(users_disco,$jid) $name
-		    }
-		}
-	    }
-	}
-    }
-    set data(users_$mech,$jid) [lsort -dictionary $data(users_$mech,$jid)]
-}
-
-proc conferenceinfo::stop {args} {
-    if {[jlib::connections] == {}} {
-	after cancel [list [namespace current]::ask]
-    }
-}
-
-hook::add roster_end_hook [namespace current]::conferenceinfo::ask
-hook::add disconnected_hook [namespace current]::conferenceinfo::stop
-
-proc conferenceinfo::setup_menu {} {
-    set m [.mainframe getmenu roster]
-
-    $m add checkbutton \
-	-label [::msgcat::mc "Periodically browse roster conferences"] \
-	-variable [namespace current]::options(autoask)
-}
-hook::add finload_hook [namespace current]::conferenceinfo::setup_menu
-

Deleted: trunk/tkabber/plugins/general/conferences.tcl
===================================================================
--- trunk/tkabber/plugins/general/conferences.tcl	2006-09-05 20:19:00 UTC (rev 706)
+++ trunk/tkabber/plugins/general/conferences.tcl	2006-09-09 10:24:10 UTC (rev 707)
@@ -1,837 +0,0 @@
-# $Id$
-
-# JEP-0048 Bookmarks support (conference bookmarks in roster)
-# In addition to JEP-0048, Tkabber stores roster groups using
-# proprietory namespace tkabber:bookmarks:groups inside
-# jabber:iq:private storage (JEP-0049)
-#
-#   tkabber:bookmarks:groups description:
-#
-#   setting:
-#   <iq type='set' id='setgroups'>
-#	<query xmlns='jabber:iq:private'>
-#	    <storage xmlns='tkabber:bookmarks:groups'>
-#		<conference jid='talks at conference.jabber.ru'>
-#		    <group>Conferences</group>
-#		    <group>jabber.ru</group>
-#		</conference>
-#	    </storage>
-#	</query>
-#   </iq>
-#
-#   getting:
-#   <iq type='get' id='getgroups'>
-#	<query xmlns='jabber:iq:private'>
-#	    <storage xmlns='tkabber:bookmarks:groups'/>
-#	</query>
-#   </iq>
-#
-
-namespace eval conferences {
-    # variable to store roster conference bookmarks
-    array set bookmarks {}
-
-    variable NS
-    set NS(private) "jabber:iq:private"
-    set NS(bookmarks) "storage:bookmarks"
-    set NS(tkabber:groups) "tkabber:bookmarks:groups"
-}
-
-###############################################################################
-#
-#   Free bookmarks on disconnect
-#
-
-proc conferences::free_bookmarks {connid} {
-    variable bookmarks
-
-    array unset bookmarks $connid,*
-}
-
-hook::add disconnected_hook [namespace current]::conferences::free_bookmarks
-
-###############################################################################
-#
-#   Retrieve bookmarks on connect
-#
-
-proc conferences::request_bookmarks {connid} {
-    variable NS
-    variable bookmarks
-    variable responds
-
-    set responds($connid) 0
-    array unset bookmarks $connid,*
-
-    jlib::send_iq get \
-	[jlib::wrapper:createtag query \
-	     -vars [list xmlns $NS(private)] \
-	     -subtags [list [jlib::wrapper:createtag storage \
-				 -vars [list xmlns $NS(bookmarks)]]]] \
-	-command [list [namespace current]::process_bookmarks $connid] \
-	-connection $connid
-    jlib::send_iq get \
-	[jlib::wrapper:createtag query \
-	     -vars [list xmlns $NS(private)] \
-	     -subtags [list [jlib::wrapper:createtag storage \
-				 -vars [list xmlns $NS(tkabber:groups)]]]] \
-	-command [list [namespace current]::process_bookmarks $connid] \
-	-connection $connid
-}
-
-hook::add connected_hook [namespace current]::conferences::request_bookmarks 20
-
-proc conferences::process_bookmarks {connid res child} {
-    variable NS
-    variable bookmarks
-    variable responds
-
-    if {$res != "OK"} return
-
-    incr responds($connid)
-
-    jlib::wrapper:splitxml $child tag vars isempty cdata children
-
-    foreach ch $children {
-	jlib::wrapper:splitxml $ch tag1 vars1 isempty1 cdata1 children1
-
-	if {[jlib::wrapper:getattr $vars1 xmlns] == $NS(bookmarks)} {
-	    foreach bookmark $children1 {
-		jlib::wrapper:splitxml $bookmark btag bvars bisempty bcdata bchildren
-
-		if {$btag != "conference"} continue
-
-		set jid [string tolower [jlib::wrapper:getattr $bvars jid]]
-		set bookmarks($connid,jid,$jid) $jid
-
-		set bookmarks($connid,name,$jid) [jlib::wrapper:getattr $bvars name]
-		set bookmarks($connid,nick,$jid) ""
-		set bookmarks($connid,password,$jid) ""
-		if {![info exists bookmarks($connid,groups,$jid)]} {
-		    set bookmarks($connid,groups,$jid) {}
-		}
-
-		set autojoin [jlib::wrapper:getattr $bvars autojoin]
-		switch -- $autojoin {
-		    1 { set bookmarks($connid,autojoin,$jid) 1 }
-		    default { set bookmarks($connid,autojoin,$jid) 0 }
-		}
-		
-		foreach bch $bchildren {
-		    jlib::wrapper:splitxml \
-			$bch tag2 vars2 isempty2 cdata2 children2
-		    switch -- $tag2 {
-			nick { set bookmarks($connid,nick,$jid) $cdata2 }
-			password { set bookmarks($connid,password,$jid) $cdata2 }
-		    }
-		}
-	    }
-	} elseif {[jlib::wrapper:getattr $vars1 xmlns] == $NS(tkabber:groups)} {
-	    foreach bookmark $children1 {
-		jlib::wrapper:splitxml $bookmark btag bvars bisempty bcdata bchildren
-
-		if {$btag != "conference"} continue
-
-		set jid [string tolower [jlib::wrapper:getattr $bvars jid]]
-
-		set groups {}
-		foreach bch $bchildren {
-		    jlib::wrapper:splitxml \
-			$bch tag2 vars2 isempty2 cdata2 children2
-		    switch -- $tag2 {
-			group { lappend groups $cdata2 }
-		    }
-		}
-		set bookmarks($connid,groups,$jid) $groups
-	    }
-	}
-    }
-
-    if {$responds($connid) < 2} return
-
-    foreach idx [array names bookmarks $connid,jid,*] {
-	set jid $bookmarks($idx)
-	client:roster_push $connid $jid $bookmarks($connid,name,$jid) \
-			   $bookmarks($connid,groups,$jid) \
-			   bookmark "" conference ""
-    }
-    after idle [list [namespace current]::autojoin_groups $connid]
-}
-
-###############################################################################
-#
-#   Store bookmarks
-#
-
-proc conferences::store_bookmarks {connid} {
-    variable NS
-    variable bookmarks
-
-    set bookmarklist {}
-    set grouplist {}
-    foreach idx [array names bookmarks $connid,jid,*] {
-	set jid $bookmarks($idx)
-	set name $bookmarks($connid,name,$jid)
-	set autojoin $bookmarks($connid,autojoin,$jid)
-	
-	set vars [list jid $jid name $name autojoin $autojoin]
-	set subtags {}
-	if {$bookmarks($connid,nick,$jid) != ""} {
-	    lappend subtags [jlib::wrapper:createtag nick \
-				 -chdata $bookmarks($connid,nick,$jid)]
-	}
-	if {$bookmarks($connid,password,$jid) != ""} {
-	    lappend subtags [jlib::wrapper:createtag password \
-				 -chdata $bookmarks($connid,password,$jid)]
-	}
-	lappend bookmarklist [jlib::wrapper:createtag conference \
-				  -vars $vars \
-				  -subtags $subtags]
-	set vars [list jid $jid]
-	set groups {}
-	foreach group $bookmarks($connid,groups,$jid) {
-	    lappend groups [jlib::wrapper:createtag group \
-				-chdata $group]
-	}
-	lappend grouplist [jlib::wrapper:createtag conference \
-			       -vars $vars \
-			       -subtags $groups]
-    }
-
-    jlib::send_iq set \
-	[jlib::wrapper:createtag query \
-	     -vars [list xmlns $NS(private)] \
-	     -subtags [list [jlib::wrapper:createtag storage \
-				 -vars [list xmlns $NS(bookmarks)] \
-				 -subtags $bookmarklist]]] \
-	-command [list [namespace current]::store_bookmarks_result $connid] \
-	-connection $connid
-    jlib::send_iq set \
-	[jlib::wrapper:createtag query \
-	     -vars [list xmlns $NS(private)] \
-	     -subtags [list [jlib::wrapper:createtag storage \
-				 -vars [list xmlns $NS(tkabber:groups)] \
-				 -subtags $grouplist]]] \
-	-command [list [namespace current]::store_bookmarks_result $connid] \
-	-connection $connid
-}
-
-proc conferences::store_bookmarks_result {connid res child} {
-
-    if {$res == "OK"} return
-
-    if {[winfo exists .store_bookmarks_error]} {
-	return
-    }
-    MessageDlg .store_bookmarks_error -aspect 50000 -icon error \
-	-message [format [::msgcat::mc "Storing conferences failed: %s"] \
-			 [error_to_string $child]] \
-	-type user -buttons ok -default 0 -cancel 0
-}
-
-###############################################################################
-#
-#   Menu item for conference window
-#
-
-proc conferences::add_conference_menu_item {m connid jid} {
-    set chatid [chat::chatid $connid $jid]
-
-    if {[info exists ::muc::muc_password($chatid)]} {
-	set password $::muc::muc_password($chatid)
-    } else {
-	set password ""
-    }
-
-    $m add command -label [::msgcat::mc "Add conference to roster..."] \
-	-command [list [namespace current]::add_conference_dialog \
-		       -group [node_from_jid $jid] \
-		       -server [server_from_jid $jid] \
-		       -password $password \
-		       -connection $connid]
-}
-
-hook::add chat_create_conference_menu_hook \
-    [namespace current]::conferences::add_conference_menu_item 35
-
-###############################################################################
-#
-#   Add conference to roster dialog
-#
-
-proc conferences::add_conference_dialog {args} {
-    variable gra_group
-    variable gra_server
-    variable gra_nick
-    variable gra_password
-    variable gra_autojoin
-    variable gra_connid
-    variable gra_rostergroup
-
-    if {[lempty [jlib::connections]]} return
-
-    set gw .addgroup
-    catch { destroy $gw }
-
-    set connid [lindex [jlib::connections] 0]
-    set gra_server conference.[jlib::connection_server $connid]
-    set gra_group ""
-    set gra_password ""
-    set gra_autojoin 0
-    set gra_rostergroup Conferences
-    catch { unset gra_nick }
-
-    foreach {key val} $args {
-	switch -- $key {
-	    -group { set gra_group $val }
-	    -server { set gra_server $val }
-	    -nick { set gra_nick $val }
-	    -password { set gra_password $val }
-	    -autojoin { set gra_autojoin $val }
-	    -connection { set connid $val }
-	}
-    }
-
-    if {![info exists gra_nick]} {
-	set gra_nick [get_group_nick ${gra_group}@$gra_server ""]
-    }
-    set gra_connid [jlib::connection_jid $connid]
-
-    Dialog $gw -title [::msgcat::mc "Add Conference to Roster"] -separator 1 -anchor e \
-	    -default 0 -cancel 1 -parent . -modal none
-
-    set gf [$gw getframe]
-    grid columnconfigure $gf 0 -weight 0
-    grid columnconfigure $gf 1 -weight 1
-
-    label $gf.lgroup -text [::msgcat::mc "Conference:"]
-    entry $gf.group -textvariable [namespace current]::gra_group
-    label $gf.lserver -text [::msgcat::mc "Server:"]
-    entry $gf.server -textvariable [namespace current]::gra_server
-    label $gf.lnick -text [::msgcat::mc "Nick:"]
-    entry $gf.nick -textvariable [namespace current]::gra_nick
-    label $gf.lpassword -text [::msgcat::mc "Password:"]
-    entry $gf.password -show * -textvariable [namespace current]::gra_password
-    checkbutton $gf.autojoin -text [::msgcat::mc "Automatically join conference upon connect"] \
-	-variable [namespace current]::gra_autojoin
-    label $gf.lrostergroup -text [::msgcat::mc "Roster group:"]
-    ComboBox $gf.rostergroup -textvariable [namespace current]::gra_rostergroup \
-	-values [get_groups $connid]
-
-    grid $gf.lgroup  -row 0 -column 0 -sticky e
-    grid $gf.group   -row 0 -column 1 -sticky ew
-    grid $gf.lserver -row 1 -column 0 -sticky e
-    grid $gf.server  -row 1 -column 1 -sticky ew
-    grid $gf.lnick -row 2 -column 0 -sticky e
-    grid $gf.nick  -row 2 -column 1 -sticky ew
-    grid $gf.lpassword -row 3 -column 0 -sticky e
-    grid $gf.password  -row 3 -column 1 -sticky ew
-    grid $gf.autojoin -row 4 -column 0 -sticky w -columnspan 2
-    grid $gf.lrostergroup  -row 5 -column 0 -sticky e
-    grid $gf.rostergroup   -row 5 -column 1 -sticky ew
-
-    if {[llength [jlib::connections]] > 1} {
-	foreach c [jlib::connections] {
-	    lappend connections [jlib::connection_jid $c]
-	}
-	label $gf.lconnection -text [::msgcat::mc "Connection:"]
-	ComboBox $gf.connection -textvariable [namespace current]::gra_connid \
-				-values $connections -editable 0 \
-				-modifycmd [list [namespace current]::change_groups \
-						 $gf.rostergroup]
-
-	grid $gf.lconnection -row 6 -column 0 -sticky e
-	grid $gf.connection  -row 6 -column 1 -sticky ew
-    }
-    
-
-    $gw add -text [::msgcat::mc "Add"] -command [list [namespace current]::add_conference $gw]
-    $gw add -text [::msgcat::mc "Cancel"] -command [list destroy $gw]
-
-    $gw draw $gf.group
-}
-
-proc conferences::change_groups {combo args} {
-    variable gra_connid
-
-    foreach connid [jlib::connections] {
-        if {[jlib::connection_jid $connid] == $gra_connid} {
-	    $combo configure -values [get_groups $connid]
-	    return
-	}
-    }
-}
-
-proc conferences::get_groups {connid} {
-    return [roster::get_groups $connid \
-		-nested $::ifacetk::roster::options(nested) \
-		-delimiter $::ifacetk::roster::options(nested_delimiter) \
-		-undefined 0]
-}
-
-proc conferences::add_conference {gw} {
-    variable bookmarks
-    variable gra_group
-    variable gra_server
-    variable gra_nick
-    variable gra_password
-    variable gra_autojoin
-    variable gra_connid
-    variable gra_rostergroup
-
-    destroy $gw
-
-    set jid [string tolower ${gra_group}@$gra_server]
-    if {$gra_rostergroup == ""} {
-	set groups {}
-    } else {
-	set groups [list $gra_rostergroup]
-    }
-
-    foreach c [jlib::connections] {
-	if {[jlib::connection_jid $c] == $gra_connid} {
-	    set connid $c
-	}
-    }
-    if {![info exists connid]} {
-	set connid [jlib::route $jid]
-    }
-
-    if {[info exists bookmarks($connid,jid,$jid)]} {
-	update_bookmark $connid $jid -name $gra_group -nick $gra_nick \
-			-password $gra_password -autojoin $gra_autojoin \
-			-groups $groups
-    } else {
-	add_bookmark $connid $jid -name $gra_group -nick $gra_nick \
-		     -password $gra_password -autojoin $gra_autojoin \
-		     -groups $groups
-    }
-}
-
-###############################################################################
-#
-#   Add bookmark to roster
-#
-
-proc conferences::add_bookmark {connid jid args} {
-    variable bookmarks
-
-    if {[info exists bookmarks($connid,jid,$jid)]} return
-
-    foreach {key val} $args {
-	switch -- $key {
-	    -name { set name $val }
-	    -nick { set nick $val }
-	    -password { set password $val }
-	    -autojoin { set autojoin $val }
-	    -groups { set groups $val }
-	}
-    }
-
-    if {![info exists name]} {
-	set name [node_from_jid $jid]
-    }
-    if {![info exists nick]} {
-	set nick [get_group_nick $jid ""]
-    }
-    if {![info exists password]} {
-	set password ""
-    }
-    if {![info exists autojoin]} {
-	set autojoin 0
-    }
-    if {![info exists groups]} {
-	set groups {}
-    }
-
-    set bookmarks($connid,jid,$jid) $jid
-    set bookmarks($connid,name,$jid) $name
-    set bookmarks($connid,nick,$jid) $nick
-    set bookmarks($connid,password,$jid) $password
-    set bookmarks($connid,autojoin,$jid) $autojoin
-    set bookmarks($connid,groups,$jid) $groups
-
-    # TODO should we remove $jid from the roster if it is here?
-    client:roster_push $connid $jid $name $groups bookmark "" conference ""
-    store_bookmarks $connid
-}
-
-###############################################################################
-#
-#   Update bookmark in roster
-#
-
-proc conferences::update_bookmark {connid jid args} {
-    variable bookmarks
-
-    set store 0
-
-    foreach {key val} $args {
-	switch -- $key {
-	    -name { set name $val }
-	    -nick { set nick $val }
-	    -password { set password $val }
-	    -autojoin { set autojoin $val }
-	    -groups { set groups $val }
-	}
-    }
-
-    if {[info exists name] && $name != $bookmarks($connid,name,$jid)} {
-	set bookmarks($connid,name,$jid) $name
-	set store 1
-    }
-    if {[info exists nick] && $nick != $bookmarks($connid,nick,$jid)} {
-	set bookmarks($connid,nick,$jid) $nick
-	set store 1
-    }
-    if {[info exists password] && $password != $bookmarks($connid,password,$jid)} {
-	set bookmarks($connid,password,$jid) $password
-	set store 1
-    }
-    if {[info exists autojoin] && $autojoin != $bookmarks($connid,autojoin,$jid)} {
-	set bookmarks($connid,autojoin,$jid) $autojoin
-	set store 1
-    }
-    if {[info exists groups] && [lsort $groups] != [lsort $bookmarks($connid,groups,$jid)]} {
-	set bookmarks($connid,groups,$jid) $groups
-	set store 1
-    }
-    if {$store} {
-	client:roster_push $connid $jid $bookmarks($connid,name,$jid) \
-	    $bookmarks($connid,groups,$jid) bookmark "" conference ""
-	store_bookmarks $connid
-    }
-}
-
-###############################################################################
-#
-#   Add or update item in roster
-#
-
-proc conferences::send_bookmark {connid jid} {
-
-    if {[roster::itemconfig $connid $jid -subsc] != "bookmark"} return
-
-    set groups [roster::itemconfig $connid $jid -group]
-
-    add_bookmark $connid $jid -groups $groups
-    update_bookmark $connid $jid -groups $groups
-
-    return stop
-}
-
-hook::add roster_send_item_hook [namespace current]::conferences::send_bookmark
-
-###############################################################################
-#
-#   Remove bookmark from roster
-#
-
-proc conferences::remove_bookmark {connid jid} {
-    variable bookmarks
-
-    if {[roster::itemconfig $connid $jid -subsc] != "bookmark"} return
-
-    if {![info exists bookmarks($connid,jid,$jid)]} return
-
-    client:roster_push $connid $jid $bookmarks($connid,name,$jid) \
-		       $bookmarks($connid,groups,$jid) \
-		       remove "" conference ""
-
-    catch { unset bookmarks($connid,jid,$jid) }
-    catch { unset bookmarks($connid,name,$jid) }
-    catch { unset bookmarks($connid,nick,$jid) }
-    catch { unset bookmarks($connid,password,$jid) }
-    catch { unset bookmarks($connid,autojoin,$jid) }
-    catch { unset bookmarks($connid,groups,$jid) }
-
-    store_bookmarks $connid
-
-    return stop
-}
-
-hook::add roster_remove_item_hook \
-    [namespace current]::conferences::remove_bookmark
-
-###############################################################################
-#
-#   Rename group in roster bookmarks
-#
-
-proc conferences::rename_group {connid name new_name} {
-    variable bookmarks
-    
-    set store 0
-    foreach idx [array names bookmarks $connid,jid,*] {
-	set jid $bookmarks($idx)
-   
-	set groups $bookmarks($connid,groups,$jid)
-	if {[lcontain $groups $name] || \
-		($name == $roster::undef_group_name && $groups == {})} {
-	    set idx [lsearch -exact $groups $name]
-	    if {$new_name != ""} {
-		set groups [lreplace $groups $idx $idx $new_name]
-	    } else {
-		set groups [lreplace $groups $idx $idx]
-	    }
-	    set groups [lrmdups $groups]
-	    client:roster_push $connid $jid $bookmarks($connid,name,$jid) \
-			       $groups bookmark "" conference ""
-	    set bookmarks($connid,groups,$jid) $groups
-	    set store 1
-	}
-    }
-    if {$store} {
-	store_bookmarks $connid
-    }
-}
-
-hook::add roster_rename_group_hook \
-    [namespace current]::conferences::rename_group
-
-###############################################################################
-#
-#   Remove group name from roster bookmarks
-#
-
-proc conferences::remove_bookmarks_group {connid name} {
-    variable bookmarks
-
-    set store 0
-    foreach idx [array names bookmarks $connid,jid,*] {
-	set jid $bookmarks($idx)
-
-	set groups $bookmarks($connid,groups,$jid)
-	if {(([llength $groups] == 1) && [lcontain $groups $name]) || \
-		(($name == $roster::undef_group_name) && ($groups == {}))} {
-	    
-	    client:roster_push $connid $jid $bookmarks($connid,name,$jid) \
-			       $groups remove "" conference ""
-
-	    catch { unset bookmarks($connid,jid,$jid) }
-	    catch { unset bookmarks($connid,name,$jid) }
-	    catch { unset bookmarks($connid,nick,$jid) }
-	    catch { unset bookmarks($connid,password,$jid) }
-	    catch { unset bookmarks($connid,autojoin,$jid) }
-	    catch { unset bookmarks($connid,groups,$jid) }
-	    
-	    set store 1
-	} elseif {[lcontain $groups $name]} {
-	    set idx [lsearch -exact $groups $name]
-	    set groups [lreplace $groups $idx $idx]
-	    
-	    client:roster_push $connid $jid $bookmarks($connid,name,$jid) \
-			       $groups bookmark "" conference ""
-	    set bookmarks($connid,groups,$jid) $groups
-	    
-	    set store 1
-	}
-    }
-    if {$store} {
-	store_bookmarks $connid
-    }
-}
-
-hook::add roster_remove_users_group_hook \
-    [namespace current]::conferences::remove_bookmarks_group
-
-###############################################################################
-#
-#   Join group on roster item doubleclick
-#
-
-proc conferences::join_group {connid jid} {
-    variable bookmarks
-    
-    set args {}
-    if {$bookmarks($connid,nick,$jid) != ""} {
-	lappend args -nick $bookmarks($connid,nick,$jid)
-    }
-    if {$bookmarks($connid,password,$jid) != ""} {
-	lappend args -password $bookmarks($connid,password,$jid)
-    }
-    eval [list ::join_group $jid -connection $connid] $args
-}
-
-###############################################################################
-#
-#   Join group during autojoin
-#
-
-proc conferences::autojoin_group {connid jid} {
-    variable bookmarks
-    global gr_nick
-    
-    if {$bookmarks($connid,nick,$jid) != ""} {
-	set nick $bookmarks($connid,nick,$jid)
-    } else {
-	set nick [get_group_nick $jid $gr_nick]
-    }
-    if {$bookmarks($connid,password,$jid) != ""} {
-	set password $bookmarks($connid,password,$jid)
-    } else {
-	set password ""
-    }
-    muc::join_group $connid $jid $nick $password
-}
-
-###############################################################################
-#
-#   Autojoin groups
-#
-
-proc conferences::autojoin_groups {connid} {
-    variable bookmarks
-
-    foreach idx [array names bookmarks $connid,jid,*] {
-	set jid $bookmarks($idx)
-	if {$bookmarks($connid,autojoin,$jid)} {
-	    autojoin_group $connid $jid
-	}
-    }
-}
-
-###############################################################################
-#
-#   "Join" item in roster conference popup menu
-#
-
-proc conferences::popup_menu {m connid jid} {
-    variable bookmarks
-
-    set args {}
-    if {[roster::itemconfig $connid $jid -subsc] == "bookmark"} {
-	if {$bookmarks($connid,nick,$jid) != ""} {
-	    lappend args -nick $bookmarks($connid,nick,$jid)
-	}
-	if {$bookmarks($connid,password,$jid) != ""} {
-	    lappend args -password $bookmarks($connid,password,$jid)
-	}
-    }
-
-    $m add command -label [::msgcat::mc "Join..."] \
-	-command [list eval [list join_group_dialog \
-				  -server [server_from_jid $jid] \
-				  -group [node_from_jid $jid] \
-				  -connection $connid] \
-				  $args]
-}   
-
-hook::add roster_conference_popup_menu_hook \
-    [namespace current]::conferences::popup_menu 20
-
-###############################################################################
-#
-#   Roster doubleclick
-#
-
-proc conferences::roster_doubleclick {connid jid category subtype} {
-    switch -- $category {
-	conference {
-	    if {[roster::itemconfig $connid $jid -subsc] == "bookmark"} {
-		join_group $connid $jid
-	    } else {
-		global gr_nick
-		::join_group $jid \
-		    -nick [get_group_nick $jid $gr_nick] \
-		    -connection $connid
-	    }
-	    return stop
-	}
-    }
-}
-
-hook::add roster_jid_doubleclick \
-    [namespace current]::conferences::roster_doubleclick
-
-###############################################################################
-#
-#   Main menu setup
-#
-
-proc conferences::main_menu {} {
-    set m [.mainframe getmenu services]
-    $m insert 2 command -label [::msgcat::mc "Add conference to roster..."] \
-	-command [list [namespace current]::add_conference_dialog]
-}
-
-hook::add finload_hook [namespace current]::conferences::main_menu
-
-###############################################################################
-#
-#   Edit roster item
-#
-
-proc conferences::edit_item_setup {f connid jid} {
-    variable egra_name
-    variable egra_nick
-    variable egra_password
-    variable egra_autojoin
-    variable bookmarks
-
-    if {[roster::itemconfig $connid $jid -subsc] != "bookmark"} return
-
-    set tf [TitleFrame $f.prop \
-		-text [::msgcat::mc "Edit properties for %s" $jid]]
-    pack $tf -side top -expand yes -fill both
-    set g [$tf getframe]
-
-    set egra_name $bookmarks($connid,name,$jid)
-    set egra_autojoin $bookmarks($connid,autojoin,$jid)
-    if {[info exists bookmarks($connid,nick,$jid)]} {
-        set egra_nick $bookmarks($connid,nick,$jid)
-    } else {
-        set egra_nick ""
-    }
-    if {[info exists bookmarks($connid,password,$jid)]} {
-        set egra_password $bookmarks($connid,password,$jid)
-    } else {
-        set egra_password ""
-    }
-
-    label $g.lname -text [string trim [::msgcat::mc "Name: "]]
-    entry $g.name -textvariable [namespace current]::egra_name
-    label $g.lnick -text [::msgcat::mc "Nick:"]
-    entry $g.nick -textvariable [namespace current]::egra_nick
-    label $g.lpassword -text [::msgcat::mc "Password:"]
-    entry $g.password -show * -textvariable [namespace current]::egra_password
-    checkbutton $g.autojoin \
-	-text [::msgcat::mc "Automatically join conference upon connect"] \
-        -variable [namespace current]::egra_autojoin
-    grid columnconfigure $g 0 -weight 0
-    grid columnconfigure $g 1 -weight 1
-
-    grid $g.lname  -row 0 -column 0 -sticky e
-    grid $g.name   -row 0 -column 1 -sticky ew
-    grid $g.lnick -row 1 -column 0 -sticky e
-    grid $g.nick  -row 1 -column 1 -sticky ew
-    grid $g.lpassword -row 2 -column 0 -sticky e
-    grid $g.password  -row 2 -column 1 -sticky ew
-    grid $g.autojoin -row 3 -column 0 -sticky w -columnspan 2
-
-    return stop
-}
-
-hook::add roster_itemedit_setup_hook \
-    [namespace current]::conferences::edit_item_setup
-
-proc conferences::commit_bookmark_changes {connid jid groups} {
-    variable egra_name
-    variable egra_nick
-    variable egra_password
-    variable egra_autojoin
-
-    if {[roster::itemconfig $connid $jid -subsc] != "bookmark"} return
-
-    plugins::conferences::update_bookmark $connid $jid \
-	-name $egra_name -nick $egra_nick -password $egra_password \
-	-autojoin $egra_autojoin -groups $groups
-
-    return stop
-}
-
-hook::add roster_itemedit_commit_hook \
-    [namespace current]::conferences::commit_bookmark_changes
-
-###############################################################################
-

Modified: trunk/tkabber/plugins/general/headlines.tcl
===================================================================
--- trunk/tkabber/plugins/general/headlines.tcl	2006-09-05 20:19:00 UTC (rev 706)
+++ trunk/tkabber/plugins/general/headlines.tcl	2006-09-09 10:24:10 UTC (rev 707)
@@ -217,7 +217,7 @@
     set fnode [str2node $text]
     if {![$tw exists $fnode]} {
         $tw insert end root $fnode -text [string map [list "\n" " "] $text] -open 1 \
-            -image browser/message -font $font \
+            -image browser/headline -font $font \
             -fill $options(seencolor) \
             -data [list type from text $text unseen 0]
     }
@@ -229,7 +229,7 @@
 
         if {![$tw exists $snode]} {
             $tw insert end $fnode $snode -text [string map [list "\n" " "] $subject] -open 1 \
-                -image browser/message -font $font \
+                -image browser/headline -font $font \
                 -fill $options(seencolor) \
                 -data [list type subject text $subject unseen 0]
         }

Modified: trunk/tkabber/plugins/general/jitworkaround.tcl
===================================================================
--- trunk/tkabber/plugins/general/jitworkaround.tcl	2006-09-05 20:19:00 UTC (rev 706)
+++ trunk/tkabber/plugins/general/jitworkaround.tcl	2006-09-09 10:24:10 UTC (rev 707)
@@ -37,7 +37,7 @@
 
 ###############################################################################
 
-proc jitworkaround::set_received_name {connid jid name groups subsc ask category subtype} {
+proc jitworkaround::set_received_name {connid jid name groups subsc ask} {
     variable names
 
     if {$subsc == "remove"} return

Deleted: trunk/tkabber/plugins/general/roster_delimiter.tcl
===================================================================
--- trunk/tkabber/plugins/general/roster_delimiter.tcl	2006-09-05 20:19:00 UTC (rev 706)
+++ trunk/tkabber/plugins/general/roster_delimiter.tcl	2006-09-09 10:24:10 UTC (rev 707)
@@ -1,89 +0,0 @@
-# $Id$
-#
-# Nested roster groups server-side delimiter storing (JEP-0083).
-#
-###############################################################################
-
-namespace eval delimiter {}
-
-###############################################################################
-#
-# Retrieving nested groups delimiter
-#
-
-proc delimiter::request {connid fallback args} {
-    debugmsg plugins "delimiter::request $connid $fallback $args"
-    
-    set command ""
-    foreach {key val} $args {
-	switch -- $key {
-	    -command { set command $val }
-	}
-    }
-    
-    jlib::send_iq get \
-	[jlib::wrapper:createtag query \
-	     -vars [list xmlns $::NS(private)] \
-	     -subtags [list [jlib::wrapper:createtag roster \
-				 -vars [list xmlns $::NS(delimiter)]]]] \
-	-command [list [namespace current]::request_result \
-		       $connid $fallback $command] \
-	-connection $connid
-}
-
-proc delimiter::request_result {connid fallback command res child} {
-    debugmsg plugins "delimiter::request_result $connid $res"
-
-    set delimiter $fallback
-
-    if {$res == "OK"} {
-	jlib::wrapper:splitxml $child tag vars isempty cdata children
-
-	foreach ch $children {
-	    jlib::wrapper:splitxml $ch tag1 vars1 isempty1 cdata1 children1
-
-	    if {[jlib::wrapper:getattr $vars1 xmlns] == $NS(delimiter)} {
-		set delimiter $cdata1
-	    }
-	}
-    }
-
-    if {$command != ""} {
-	eval $command [list $connid $delimiter]
-    }
-}
-
-###############################################################################
-#
-# Storing nested groups delimiter
-#
-
-proc delimiter::store {connid delimiter args} {
-    debugmsg plugins "delimiter::store $connid $delimiter $args"
-
-    set command ""
-    foreach {key val} $args {
-	switch -- $key {
-	    -command { set command $val }
-	}
-    }
-    
-    jlib::send_iq set \
-	[jlib::wrapper:createtag query \
-	     -vars [list xmlns $::NS(private)] \
-	     -subtags [list [jlib::wrapper:createtag roster \
-				 -vars [list xmlns $::NS(delimiter)] \
-				 -chdata $delimiter]]] \
-	-command [list [namespace current]::store_result $connid $command] \
-	-connection $connid
-    
-}
-
-proc delimiter::store_result {connid command res child} {
-    debugmsg plugins "delimiter::store_result $connid $res"
-    
-    if {$command != ""} {
-	eval $command [list $res $child]
-    }
-}
-

Deleted: trunk/tkabber/plugins/general/rosterx.tcl
===================================================================
--- trunk/tkabber/plugins/general/rosterx.tcl	2006-09-05 20:19:00 UTC (rev 706)
+++ trunk/tkabber/plugins/general/rosterx.tcl	2006-09-09 10:24:10 UTC (rev 707)
@@ -1,211 +0,0 @@
-# $Id$
-# Roster Item Exchange Support (JEP-0093 and JEP-0144)
-
-namespace eval rosterx {}
-
-###############################################################################
-
-proc rosterx::process_x {acc f x connid from type replyP} {
-    lassign $acc row body
-
-    set rosterx 0
-    foreach xa $x {
-	jlib::wrapper:splitxml $xa tag vars isempty chdata children
-
-	set xmlns [jlib::wrapper:getattr $vars xmlns]
-	switch -- $xmlns \
-	    $::NS(rosterx) {
-		set rosterx 1
-		foreach child $children {
-		    process_x_rosterx $f $child $row $from
-		    incr row
-		}
-	    } \
-	    $::NS(xroster) {
-		if {$rosterx} break
-		foreach child $children {
-		    process_x_xroster $f $child $row $from
-		    incr row
-		}
-	    } \
-	}
-
-    return [list $row $body]
-}
-
-hook::add message_process_x_hook [namespace current]::rosterx::process_x 60
-
-###############################################################################
-
-proc rosterx::process_x_rosterx {f x row from} {
-    jlib::wrapper:splitxml $x tag vars isempty chdata children
-
-    set jid [jlib::wrapper:getattr $vars jid]
-    set name [jlib::wrapper:getattr $vars name]
-    set action [jlib::wrapper:getattr $vars action]
-
-    if {$jid == ""} return
-
-    if {$name != ""} {
-        set desc "$name ($jid)"
-    } else {
-        set desc $jid
-    }
-
-    label $f.luser$row -text [::msgcat::mc "Attached user:"]
-    set cb [button $f.user$row -text $desc \
-                -command [list [namespace current]::process_user $jid \
-                              "$from asked me to add you to my roster."]]
-    grid $f.luser$row -row $row -column 0 -sticky e
-    grid $f.user$row  -row $row -column 1 -sticky ew
-}
-
-###############################################################################
-
-proc rosterx::process_x_xroster {f x row from} {
-    jlib::wrapper:splitxml $x tag vars isempty chdata children
-
-    set jid [jlib::wrapper:getattr $vars jid]
-    set name [jlib::wrapper:getattr $vars name]
-
-    if {$jid == ""} return
-
-    if {$name != ""} {
-        set desc "$name ($jid)"
-    } else {
-        set desc $jid
-    }
-
-    label $f.luser$row -text [::msgcat::mc "Attached user:"]
-    set cb [button $f.user$row -text $desc \
-                -command [list [namespace current]::process_user $jid \
-                              "$from asked me to add you to my roster."]]
-    grid $f.luser$row -row $row -column 0 -sticky e
-    grid $f.user$row  -row $row -column 1 -sticky ew
-}
-
-###############################################################################
-
-proc rosterx::process_user {jid body} {
-    jlib::send_presence -to $jid -type subscribe -stat $body
-
-    jlib::send_iq set \
-        [jlib::wrapper:createtag query \
-             -vars [list xmlns $::NS(roster)] \
-             -subtags [list [jlib::wrapper:createtag item \
-                                     -vars [list jid $jid]]]]
-}
-
-###############################################################################
-
-proc rosterx::send_users_dialog {connid user} {
-    global send_uc
-
-    set jid [get_jid_of_user $connid $user]
-
-    if {[cequal $jid ""]} {
-        set jid $user
-    }
-
-    set gw .contacts
-    catch { destroy $gw }
-
-    if {[catch { set nick [roster::get_label $connid $user] }]} {
-	if {[catch { set nick [chat::get_nick $connid \
-					      $user groupchat] }]} {
-	    set nick $user
-	}
-    }
-
-    set choices {}
-    set balloons {}
-    foreach c [jlib::connections] {
-	foreach choice [roster::get_jids $c] {
-	    if {[roster::itemconfig $c $choice -isuser]} {
-		lappend choices [list $c $choice] [roster::get_label $c $choice]
-		lappend balloons [list $c $choice] $choice
-	    }
-	}
-    }
-    if {[llength $choices] == 0} {
-        MessageDlg ${gw}_err -aspect 50000 -icon info \
-	    -message [::msgcat::mc "No users in roster..."] -type user \
-	    -buttons ok -default 0 -cancel 0
-        return
-    }
-
-    CbDialog $gw [format [::msgcat::mc "Send contacts to %s"] $nick] \
-	[list [::msgcat::mc "Send"] \
-	      [list [namespace current]::send_users $gw $jid -connection $connid] \
-	      [::msgcat::mc "Cancel"] \
-	      [list destroy $gw]] \
-	send_uc $choices $balloons
-}
-
-###############################################################################
-
-proc rosterx::add_menu_item {m connid jid} {
-    $m add command \
-	   -label [::msgcat::mc "Send users..."] \
-           -command [list [namespace current]::send_users_dialog $connid $jid]
-}
-
-hook::add roster_create_groupchat_user_menu_hook \
-    [namespace current]::rosterx::add_menu_item 45
-hook::add chat_create_user_menu_hook \
-    [namespace current]::rosterx::add_menu_item 45
-hook::add roster_jid_popup_menu_hook \
-    [namespace current]::rosterx::add_menu_item 45
-hook::add message_dialog_menu_hook \
-    [namespace current]::rosterx::add_menu_item 45
-hook::add search_popup_menu_hook \
-    [namespace current]::rosterx::add_menu_item 45
-
-###############################################################################
-
-proc rosterx::send_users {gw jid args} {
-    global send_uc
-
-    foreach {opt val} $args {
-	switch -- $opt {
-	    -connection { set connid $val }
-	}
-    }
-    if {![info exists connid]} {
-	set connid [jlib::route $jid]
-    }
-
-    set sf [$gw getframe].sw.sf
-    set choices {}
-    foreach uc [array names send_uc] {
-        if {$send_uc($uc)} {
-            lappend choices $uc
-        }
-    }
-
-    destroy $gw
-
-    set subtags {}
-    set body [::msgcat::mc "Contact Information"]
-    foreach choice $choices {
-	lassign $choice con uc
-	lappend subtags [roster::item_to_xml $con $uc]
-	set nick [roster::get_label $con $uc]
-        append body "\n$nick - xmpp:$uc"
-    }
-
-    message::send_msg $jid -type normal -body $body \
-	-xlist [list \
-		    [jlib::wrapper:createtag x \
-			 -vars [list xmlns $::NS(rosterx)] \
-	                 -subtags $subtags] \
-		    [jlib::wrapper:createtag x \
-			 -vars [list xmlns $::NS(xroster)] \
-	                 -subtags $subtags]] \
-	-connection $connid
-}
-
-###############################################################################
-
-disco::register_feature $::NS(rosterx)
-

Copied: trunk/tkabber/plugins/roster/annotations.tcl (from rev 705, trunk/tkabber/plugins/general/annotations.tcl)
===================================================================
--- trunk/tkabber/plugins/roster/annotations.tcl	                        (rev 0)
+++ trunk/tkabber/plugins/roster/annotations.tcl	2006-09-09 10:24:10 UTC (rev 707)
@@ -0,0 +1,310 @@
+# $Id$
+
+# JEP-0145 Annotations support
+
+namespace eval annotations {
+    # variable to store roster notes
+    array set notes {}
+
+    variable NS
+    set NS(private) "jabber:iq:private"
+    set NS(rosternotes) "storage:rosternotes"
+}
+
+proc annotations::free_notes {connid} {
+    variable notes
+
+    array unset notes $connid,*
+}
+
+hook::add disconnected_hook [namespace current]::annotations::free_notes
+
+proc annotations::request_notes {connid} {
+    variable NS
+    variable notes
+
+    jlib::send_iq get \
+	[jlib::wrapper:createtag query \
+	     -vars [list xmlns $NS(private)] \
+	     -subtags [list [jlib::wrapper:createtag storage \
+				 -vars [list xmlns $NS(rosternotes)]]]] \
+	-command [list [namespace current]::process_notes $connid] \
+	-connection $connid
+}
+
+hook::add connected_hook [namespace current]::annotations::request_notes
+
+proc annotations::process_notes {connid res child} {
+    variable NS
+    variable notes
+
+    if {$res != "OK"} return
+
+    array set notes {}
+
+    jlib::wrapper:splitxml $child tag vars isempty cdata children
+
+    foreach ch $children {
+	jlib::wrapper:splitxml $ch tag1 vars1 isempty1 cdata1 children1
+
+	if {[jlib::wrapper:getattr $vars1 xmlns] == $NS(rosternotes)} {
+	    foreach note $children1 {
+		jlib::wrapper:splitxml $note ntag nvars nisempty ncdata nchildren
+
+		set jid [jlib::wrapper:getattr $nvars jid]
+		set cdate [jlib::wrapper:getattr $nvars cdate]
+		set mdate [jlib::wrapper:getattr $nvars mdate]
+		set notes($connid,jid,$jid) $jid
+		if {![catch { scan_time $cdate } cdate]} {
+		    set notes($connid,cdate,$jid) $cdate
+		}
+		if {![catch { scan_time $mdate } mdate]} {
+		    set notes($connid,mdate,$jid) $mdate
+		}
+		set notes($connid,note,$jid) $ncdata
+	    
+	    }
+	}
+    }
+}
+
+proc annotations::scan_time {timestamp} {
+    if {[regexp {(.*)T(.*)Z} $timestamp -> date time]} {
+	return [clock scan "$date $time" -gmt true]
+    } else {
+	return [clock scan $timestamp -gmt true]
+    }
+}
+
+proc annotations::cleanup_and_store_notes {connid} {
+    variable notes
+
+    set roster_jids {}
+    foreach rjid [roster::get_jids $connid] {
+	lappend roster_jids [node_and_server_from_jid $rjid]
+    }
+
+    foreach idx [array names notes $connid,jid,*] {
+	set jid $notes($idx)
+	if {[lsearch -exact $roster_jids $jid] < 0 || \
+		![info exists notes($connid,note,$jid)] || \
+		$notes($connid,note,$jid) == ""} {
+	    catch { unset notes($connid,jid,$jid) }
+	    catch { unset notes($connid,cdate,$jid) }
+	    catch { unset notes($connid,mdate,$jid) }
+	    catch { unset notes($connid,note,$jid) }
+	}
+    }
+
+    store_notes $connid
+}
+
+proc annotations::store_notes {connid} {
+    variable NS
+    variable notes
+
+    set notelist {}
+    foreach idx [array names notes $connid,jid,*] {
+	set jid $notes($idx)
+
+	set vars [list jid $jid]
+	if {[info exists notes($connid,cdate,$jid)]} {
+	    set cdate [clock format $notes($connid,cdate,$jid) \
+			     -format "%Y-%m-%dT%TZ" -gmt true]
+	}
+	lappend vars cdate $cdate
+	if {[info exists notes($connid,mdate,$jid)]} {
+	    set mdate [clock format $notes($connid,mdate,$jid) \
+			     -format "%Y-%m-%dT%TZ" -gmt true]
+	}
+	lappend vars mdate $mdate
+	if {[info exists notes($connid,note,$jid)] && \
+		$notes($connid,note,$jid) != ""} {
+	    lappend notelist \
+		[jlib::wrapper:createtag note \
+		     -vars $vars \
+		     -chdata $notes($connid,note,$jid)]
+	}
+    }
+
+    jlib::send_iq set \
+	[jlib::wrapper:createtag query \
+	     -vars [list xmlns $NS(private)] \
+	     -subtags [list [jlib::wrapper:createtag storage \
+				 -vars [list xmlns $NS(rosternotes)] \
+				 -subtags $notelist]]] \
+	-command [list [namespace current]::store_notes_result $connid] \
+	-connection $connid
+}
+
+proc annotations::store_notes_result {connid res child} {
+
+    if {$res == "OK"} return
+
+    if {[winfo exists .store_notes_error]} {
+	destroy .store_notes_error
+    }
+    MessageDlg .store_notes_error -aspect 50000 -icon error \
+	-message [format [::msgcat::mc "Storing roster notes failed: %s"] \
+			 [error_to_string $child]] \
+	-type user -buttons ok -default 0 -cancel 0
+}
+
+proc annotations::add_user_popup_info {infovar connid jid} {
+    variable notes
+    upvar 0 $infovar info
+
+    set jid [node_and_server_from_jid $jid]
+
+    if {[info exists notes($connid,note,$jid)] && \
+	    $notes($connid,note,$jid) != ""} {
+	append info "\n\tNote:\t"
+	append info [string map [list "\n" "\n\t\t"] "$notes($connid,note,$jid)"]
+
+	if {0} {
+	    if {[info exists notes($connid,cdate,$jid)]} {
+		append info [format "\n\tNote created: %s" \
+				 [clock format $notes($connid,cdate,$jid) \
+					-format "%Y-%m-%d %T" -gmt false]]
+	    }
+	    if {[info exists notes($connid,mdate,$jid)]} {
+		append info [format "\n\tNote modified: %s" \
+				 [clock format $notes($connid,mdate,$jid) \
+					-format "%Y-%m-%d %T" -gmt false]]
+	    }
+	}
+    }
+}
+
+hook::add roster_user_popup_info_hook \
+    [namespace current]::annotations::add_user_popup_info 80
+
+proc annotations::show_dialog {connid jid} {
+    variable notes
+    global font
+
+    set jid [node_and_server_from_jid $jid]
+
+    set allowed_name [jid_to_tag $jid]
+    set w .note_edit_${connid}_$allowed_name
+
+    if {[winfo exists $w]} {
+	destroy $w
+    }
+
+    Dialog $w -title [format [::msgcat::mc "Edit roster notes for %s"] $jid] \
+	-modal none -separator 1 -anchor e \
+	-default 0 -cancel 1
+
+    $w add -text [::msgcat::mc "Store"] \
+	-command [list [namespace current]::commit_changes $w $connid $jid]
+    $w add -text [::msgcat::mc "Cancel"] -command [list destroy $w]
+
+    set f [$w getframe]
+
+    if {[info exists notes($connid,cdate,$jid)]} {
+	label $f.cdate -text [format [::msgcat::mc "Created: %s"] \
+				     [clock format $notes($connid,cdate,$jid) \
+					    -format "%Y-%m-%d %T" -gmt false]]
+	pack $f.cdate -side top -anchor w
+    }
+
+    if {[info exists notes($connid,mdate,$jid)]} {
+	label $f.mdate -text [format [::msgcat::mc "Modified: %s"] \
+				     [clock format $notes($connid,mdate,$jid) \
+					    -format "%Y-%m-%d %T" -gmt false]]
+	pack $f.mdate -side top -anchor w
+    }
+
+    ScrolledWindow $f.sw
+    pack $f.sw -side top -expand yes -fill both
+    textUndoable $f.note -width 50 -height 5 -wrap word -font $font
+    if {[info exists notes($connid,note,$jid)]} {
+	$f.note insert 0.0 $notes($connid,note,$jid)
+    }
+    $f.sw setwidget $f.note
+
+    bind $f.note <Control-Key-Return> "$w invoke default
+				       break"
+    bind $w <Key-Return> { }
+    bind $w <Control-Key-Return> "$w invoke default
+				  break"
+
+    $w draw $f.note
+}
+
+proc annotations::commit_changes {w connid jid} {
+    variable notes
+
+    set text [$w getframe].note
+
+    set date [clock seconds]
+
+    set notes($connid,jid,$jid) $jid
+    if {![info exists notes($connid,cdate,$jid)]} {
+	set notes($connid,cdate,$jid) $date
+    }
+    set notes($connid,mdate,$jid) $date
+    set notes($connid,note,$jid) [$text get 0.0 "end -1 char"]
+
+    cleanup_and_store_notes $connid
+
+    destroy $w
+}
+
+proc annotations::prefs_user_menu {m connid jid} {
+    set rjid [roster::find_jid $connid $jid]
+    $m add command -label [::msgcat::mc "Edit item notes..."] \
+	-command [list [namespace current]::show_dialog $connid $rjid]
+}
+
+hook::add chat_create_user_menu_hook \
+    [namespace current]::annotations::prefs_user_menu 76
+hook::add roster_conference_popup_menu_hook \
+    [namespace current]::annotations::prefs_user_menu 76
+hook::add roster_service_popup_menu_hook \
+    [namespace current]::annotations::prefs_user_menu 76
+hook::add roster_jid_popup_menu_hook \
+    [namespace current]::annotations::prefs_user_menu 76
+
+proc annotations::note_page {tab connid jid editable} {
+    variable notes
+    global font
+
+    if {$editable} return
+
+    set jid [node_and_server_from_jid $jid]
+
+    if {![info exists notes($connid,note,$jid)] || \
+	    $notes($connid,note,$jid) == ""} {
+	return
+    }
+
+    set notestab [$tab insert end notes -text [::msgcat::mc "Notes"]]
+    set n [userinfo::pack_frame $notestab.notes [::msgcat::mc "Roster Notes"]]
+
+    if {[info exists notes($connid,cdate,$jid)]} {
+	label $n.cdate -text [format [::msgcat::mc "Created: %s"] \
+				     [clock format $notes($connid,cdate,$jid) \
+					    -format "%Y-%m-%d %T" -gmt false]]
+	pack $n.cdate -side top -anchor w
+    }
+
+    if {[info exists notes($connid,mdate,$jid)]} {
+	label $n.mdate -text [format [::msgcat::mc "Modified: %s"] \
+				     [clock format $notes($connid,mdate,$jid) \
+					    -format "%Y-%m-%d %T" -gmt false]]
+	pack $n.mdate -side top -anchor w
+    }
+
+    set sw [ScrolledWindow $n.sw -scrollbar vertical]
+    text $n.text -font $font -height 12 -wrap word
+    $sw setwidget $n.text
+    $n.text insert 0.0 $notes($connid,note,$jid)
+    $n.text configure -state disabled
+    pack $sw -side top -fill both -expand yes
+    pack $n -fill both -expand yes
+}
+
+hook::add userinfo_hook [namespace current]::annotations::note_page 40
+

Added: trunk/tkabber/plugins/roster/cache_categories.tcl
===================================================================
--- trunk/tkabber/plugins/roster/cache_categories.tcl	                        (rev 0)
+++ trunk/tkabber/plugins/roster/cache_categories.tcl	2006-09-09 10:24:10 UTC (rev 707)
@@ -0,0 +1,104 @@
+# $Id$
+
+namespace eval cache_categories {
+#   {server1 {category1 type1} server2 {category2 type2}}
+    custom::defvar category_and_subtype_list {} \
+	[::msgcat::mc "Cached service categories and types (from disco#info)."] \
+	-type string -group Hidden
+
+    variable requested_categories
+}
+
+##############################################################################
+
+proc cache_categories::fill_cached_categories_and_subtypes {connid} {
+    variable category_and_subtype_list
+    variable requested_categories
+
+    catch { array set tmp $category_and_subtype_list }
+    set requested_categories($connid) [array names tmp]
+    foreach jid [array names tmp] {
+	lassign $tmp($jid) category subtype
+	roster::override_category_and_subtype $connid $jid \
+					      $category $subtype
+    }
+}
+
+hook::add connected_hook \
+    [namespace current]::cache_categories::fill_cached_categories_and_subtypes
+
+##############################################################################
+
+proc cache_categories::free_cached_categories_and_subtypes {connid} {
+    variable category_and_subtype_list
+    variable requested_categories
+
+    if {$connid == {}} {
+	array unset requested_categories
+    } else {
+	catch { unset requested_categories($connid) }
+    }
+}
+
+hook::add disconnected_hook \
+    [namespace current]::cache_categories::free_cached_categories_and_subtypes
+
+##############################################################################
+
+proc cache_categories::request_category_and_subtype {connid jid} {
+    variable category_and_subtype_list
+    variable requested_categories
+
+    set server [server_from_jid $jid]
+    if {[lsearch -exact $requested_categories($connid) $server] >= 0} {
+	return
+    }
+
+    lappend requested_categories($connid) $server
+
+    jlib::send_iq get \
+	[jlib::wrapper:createtag query \
+	     -vars [list xmlns $::NS(disco_info)]] \
+	-to $server \
+	-connection $connid \
+	-command [list [namespace current]::parse_requested_categories $connid $server]
+}
+
+##############################################################################
+
+proc cache_categories::parse_requested_categories {connid server res child} {
+    variable category_and_subtype_list
+
+    if {$res != "OK"} return
+
+    jlib::wrapper:splitxml $child tag vars isempty chdata children
+
+    foreach ch $children {
+	jlib::wrapper:splitxml $ch tag1 vars1 isempty1 chdata1 children1
+	switch -- $tag1 {
+	    identity {
+		set category [jlib::wrapper:getattr $vars1 category]
+		set type [jlib::wrapper:getattr $vars1 type]
+
+		roster::override_category_and_subtype $connid $server \
+						      $category $type
+		lappend category_and_subtype_list \
+			$server [list $category $type]
+
+		foreach jid [roster::get_jids $connid] {
+		    if {[server_from_jid $jid] == $server} {
+			roster::heuristically_get_category_and_subtype $connid $jid
+		    }
+		}
+
+		custom::store_vars [namespace current]::category_and_subtype_list
+		::redraw_roster
+		break
+	    }
+	}
+    }
+}
+
+###############################################################################
+
+


Property changes on: trunk/tkabber/plugins/roster/cache_categories.tcl
___________________________________________________________________
Name: svn:keywords
   + Author Date Id Revision
Name: svn:eol-style
   + native

Copied: trunk/tkabber/plugins/roster/conferenceinfo.tcl (from rev 705, trunk/tkabber/plugins/general/conferenceinfo.tcl)
===================================================================
--- trunk/tkabber/plugins/roster/conferenceinfo.tcl	                        (rev 0)
+++ trunk/tkabber/plugins/roster/conferenceinfo.tcl	2006-09-09 10:24:10 UTC (rev 707)
@@ -0,0 +1,175 @@
+# $Id$
+
+namespace eval conferenceinfo {
+    custom::defgroup ConferenceInfo \
+	[::msgcat::mc "Options for Conference Info module, that allows you to see list of\
+participants in roster popup, regardless of whether you are currently joined\
+with the conference."] \
+	-group Tkabber \
+	-tag "Conference Info"
+
+    custom::defvar options(autoask) 0 \
+	[::msgcat::mc "Use this module"] -group ConferenceInfo -type boolean \
+	-command [namespace current]::ask
+    custom::defvar options(interval) 2 \
+	[::msgcat::mc "Interval (in minutes) between requests of participants list."] \
+	-type integer -group ConferenceInfo
+    custom::defvar options(err_interval) 60 \
+	[::msgcat::mc "Interval (in minutes) after error reply on request of participants list."] \
+	-type integer -group ConferenceInfo
+}
+
+
+# TODO: connid
+proc conferenceinfo::add_user_popup_info {infovar connid jid} {
+    variable data
+    variable options
+    upvar 0 $infovar info
+
+    if {!$options(autoask)} return
+    if {[info exists chat::opened([chat::chatid $connid $jid])]} return
+
+    if {![info exists data(error_browse,$jid)] || \
+	    ![info exists data(error_disco,$jid)]} return
+
+    if {$data(error_disco,$jid) != "" && $data(error_browse,$jid) != ""} {
+	if {$data(error_browse_code,$jid) != "feature-not-implemented"} {
+	    set errstr $data(error_browse,$jid)
+	} else {
+	    set errstr $data(error_disco,$jid)
+	}
+	append info [format [::msgcat::mc "\n\tCan't browse: %s"] $errstr]
+    } else {
+	if {$data(error_browse,$jid) == ""} {
+	    set mech browse
+	} else {
+	    set mech disco
+	}
+	if {$data(users_$mech,$jid) != {}} {
+	    append info \
+		[format [::msgcat::mc "\nRoom participants at %s:"] \
+		     [clock format $data(time_$mech,$jid) -format %R]]
+	    foreach name $data(users_$mech,$jid) {
+		append info "\n\t$name"
+	    }
+	} else {
+	    append info \
+		[format [::msgcat::mc "\nRoom is empty at %s"] \
+		     [clock format $data(time_$mech,$jid) -format %R]]
+	}
+    }
+}
+hook::add roster_user_popup_info_hook \
+    [namespace current]::conferenceinfo::add_user_popup_info
+
+
+proc conferenceinfo::ask {args} {
+    variable options
+    variable data
+
+    if {!$options(autoask)} return
+
+    foreach connid [jlib::connections] {
+	if {[catch { set roster::roster(jids,$connid) } jids]} {
+	    continue
+	}
+	foreach jid $jids {
+	    lassign [roster::get_category_and_subtype $connid $jid] \
+		category type
+	    if {$category == "conference" && [node_from_jid $jid] != "" && \
+		    ![info exists chat::opened([chat::chatid $connid $jid])]} {
+	    
+		set sec [clock seconds]
+ 
+		if {![info exists data(error_browse,$jid)] || \
+			$data(error_browse,$jid) == "" || \
+			$sec - $data(time_browse,$jid) >= $options(err_interval) * 60} {
+
+		    jlib::send_iq get \
+			[jlib::wrapper:createtag query \
+			     -vars {xmlns jabber:iq:browse}] \
+			-to $jid \
+			-connection $connid \
+			-command [list [namespace current]::receive $jid browse]
+		}
+
+		if {![info exists data(error_disco,$jid)] || \
+			$data(error_disco,$jid) == "" || \
+			$sec - $data(time_disco,$jid) >= $options(err_interval) * 60} {
+
+		    jlib::send_iq get \
+			[jlib::wrapper:createtag query \
+			     -vars [list xmlns $::NS(disco_items)]] \
+			-to $jid \
+			-connection $connid \
+			-command [list [namespace current]::receive $jid disco]
+		}
+	    }
+	}
+    }
+
+    after cancel [list [namespace current]::ask]
+    after [expr {$options(interval) * 60 * 1000}] [list [namespace current]::ask]
+}
+
+proc conferenceinfo::receive {jid mech res child} {
+    variable options
+    variable data
+
+    set data(error_$mech,$jid) ""
+    set data(error_${mech}_code,$jid) ""
+    set data(time_$mech,$jid) [clock seconds]
+    set data(users_$mech,$jid) {}
+
+    if {$res != "OK"} {
+	set data(error_${mech}_code,$jid) [lindex [error_type_condition $child] 1]
+	set data(error_$mech,$jid) [error_to_string $child]
+	return
+    }
+
+    jlib::wrapper:splitxml $child tag vars isempty chdata children
+
+    foreach item $children {
+	jlib::wrapper:splitxml $item tag1 vars1 isempty1 chdata1 children1
+	switch -- $mech {
+	    browse {
+		if {$tag1 == "user" || ($tag1 == "item" && \
+			[jlib::wrapper:getattr $vars1 category] == "user")} {
+		    set name [jlib::wrapper:getattr $vars1 name]
+		    if {$name != ""} {
+			lappend data(users_browse,$jid) $name
+		    }
+		}
+	    }
+	    disco {
+		if {$tag1 == "item"} {
+		    set node [jlib::wrapper:getattr $vars1 node]
+		    set name [jlib::wrapper:getattr $vars1 name]
+		    if {$name != "" && $node == ""} {
+			lappend data(users_disco,$jid) $name
+		    }
+		}
+	    }
+	}
+    }
+    set data(users_$mech,$jid) [lsort -dictionary $data(users_$mech,$jid)]
+}
+
+proc conferenceinfo::stop {args} {
+    if {[jlib::connections] == {}} {
+	after cancel [list [namespace current]::ask]
+    }
+}
+
+hook::add roster_end_hook [namespace current]::conferenceinfo::ask
+hook::add disconnected_hook [namespace current]::conferenceinfo::stop
+
+proc conferenceinfo::setup_menu {} {
+    set m [.mainframe getmenu roster]
+
+    $m add checkbutton \
+	-label [::msgcat::mc "Periodically browse roster conferences"] \
+	-variable [namespace current]::options(autoask)
+}
+hook::add finload_hook [namespace current]::conferenceinfo::setup_menu
+

Copied: trunk/tkabber/plugins/roster/conferences.tcl (from rev 705, trunk/tkabber/plugins/general/conferences.tcl)
===================================================================
--- trunk/tkabber/plugins/roster/conferences.tcl	                        (rev 0)
+++ trunk/tkabber/plugins/roster/conferences.tcl	2006-09-09 10:24:10 UTC (rev 707)
@@ -0,0 +1,847 @@
+# $Id$
+
+# JEP-0048 Bookmarks support (conference bookmarks in roster)
+# In addition to JEP-0048, Tkabber stores roster groups using
+# proprietory namespace tkabber:bookmarks:groups inside
+# jabber:iq:private storage (JEP-0049)
+#
+#   tkabber:bookmarks:groups description:
+#
+#   setting:
+#   <iq type='set' id='setgroups'>
+#	<query xmlns='jabber:iq:private'>
+#	    <storage xmlns='tkabber:bookmarks:groups'>
+#		<conference jid='talks at conference.jabber.ru'>
+#		    <group>Conferences</group>
+#		    <group>jabber.ru</group>
+#		</conference>
+#	    </storage>
+#	</query>
+#   </iq>
+#
+#   getting:
+#   <iq type='get' id='getgroups'>
+#	<query xmlns='jabber:iq:private'>
+#	    <storage xmlns='tkabber:bookmarks:groups'/>
+#	</query>
+#   </iq>
+#
+
+namespace eval conferences {
+    # variable to store roster conference bookmarks
+    array set bookmarks {}
+
+    variable NS
+    set NS(private) "jabber:iq:private"
+    set NS(bookmarks) "storage:bookmarks"
+    set NS(tkabber:groups) "tkabber:bookmarks:groups"
+}
+
+###############################################################################
+#
+#   Free bookmarks on disconnect
+#
+
+proc conferences::free_bookmarks {connid} {
+    variable bookmarks
+
+    array unset bookmarks $connid,*
+}
+
+hook::add disconnected_hook [namespace current]::conferences::free_bookmarks
+
+###############################################################################
+#
+#   Retrieve bookmarks on connect
+#
+
+proc conferences::request_bookmarks {connid} {
+    variable NS
+    variable bookmarks
+    variable responds
+
+    set responds($connid) 0
+    array unset bookmarks $connid,*
+
+    jlib::send_iq get \
+	[jlib::wrapper:createtag query \
+	     -vars [list xmlns $NS(private)] \
+	     -subtags [list [jlib::wrapper:createtag storage \
+				 -vars [list xmlns $NS(bookmarks)]]]] \
+	-command [list [namespace current]::process_bookmarks $connid] \
+	-connection $connid
+    jlib::send_iq get \
+	[jlib::wrapper:createtag query \
+	     -vars [list xmlns $NS(private)] \
+	     -subtags [list [jlib::wrapper:createtag storage \
+				 -vars [list xmlns $NS(tkabber:groups)]]]] \
+	-command [list [namespace current]::process_bookmarks $connid] \
+	-connection $connid
+}
+
+hook::add connected_hook [namespace current]::conferences::request_bookmarks 20
+
+proc conferences::process_bookmarks {connid res child} {
+    variable NS
+    variable bookmarks
+    variable responds
+
+    if {$res != "OK"} return
+
+    incr responds($connid)
+
+    jlib::wrapper:splitxml $child tag vars isempty cdata children
+
+    foreach ch $children {
+	jlib::wrapper:splitxml $ch tag1 vars1 isempty1 cdata1 children1
+
+	if {[jlib::wrapper:getattr $vars1 xmlns] == $NS(bookmarks)} {
+	    foreach bookmark $children1 {
+		jlib::wrapper:splitxml $bookmark btag bvars bisempty bcdata bchildren
+
+		if {$btag != "conference"} continue
+
+		set jid [string tolower [jlib::wrapper:getattr $bvars jid]]
+		set bookmarks($connid,jid,$jid) $jid
+
+		set bookmarks($connid,name,$jid) [jlib::wrapper:getattr $bvars name]
+		set bookmarks($connid,nick,$jid) ""
+		set bookmarks($connid,password,$jid) ""
+		if {![info exists bookmarks($connid,groups,$jid)]} {
+		    set bookmarks($connid,groups,$jid) {}
+		}
+
+		set autojoin [jlib::wrapper:getattr $bvars autojoin]
+		switch -- $autojoin {
+		    1 { set bookmarks($connid,autojoin,$jid) 1 }
+		    default { set bookmarks($connid,autojoin,$jid) 0 }
+		}
+		
+		foreach bch $bchildren {
+		    jlib::wrapper:splitxml \
+			$bch tag2 vars2 isempty2 cdata2 children2
+		    switch -- $tag2 {
+			nick { set bookmarks($connid,nick,$jid) $cdata2 }
+			password { set bookmarks($connid,password,$jid) $cdata2 }
+		    }
+		}
+	    }
+	} elseif {[jlib::wrapper:getattr $vars1 xmlns] == $NS(tkabber:groups)} {
+	    foreach bookmark $children1 {
+		jlib::wrapper:splitxml $bookmark btag bvars bisempty bcdata bchildren
+
+		if {$btag != "conference"} continue
+
+		set jid [string tolower [jlib::wrapper:getattr $bvars jid]]
+
+		set groups {}
+		foreach bch $bchildren {
+		    jlib::wrapper:splitxml \
+			$bch tag2 vars2 isempty2 cdata2 children2
+		    switch -- $tag2 {
+			group { lappend groups $cdata2 }
+		    }
+		}
+		set bookmarks($connid,groups,$jid) $groups
+	    }
+	}
+    }
+
+    if {$responds($connid) < 2} return
+
+    foreach idx [array names bookmarks $connid,jid,*] {
+	set jid $bookmarks($idx)
+	client:roster_push $connid $jid $bookmarks($connid,name,$jid) \
+			   $bookmarks($connid,groups,$jid) \
+			   bookmark ""
+	roster::override_category_and_subtype $connid $jid conference ""
+    }
+    after idle [list [namespace current]::autojoin_groups $connid]
+}
+
+###############################################################################
+#
+#   Store bookmarks
+#
+
+proc conferences::store_bookmarks {connid} {
+    variable NS
+    variable bookmarks
+
+    set bookmarklist {}
+    set grouplist {}
+    foreach idx [array names bookmarks $connid,jid,*] {
+	set jid $bookmarks($idx)
+	set name $bookmarks($connid,name,$jid)
+	set autojoin $bookmarks($connid,autojoin,$jid)
+	
+	set vars [list jid $jid name $name autojoin $autojoin]
+	set subtags {}
+	if {$bookmarks($connid,nick,$jid) != ""} {
+	    lappend subtags [jlib::wrapper:createtag nick \
+				 -chdata $bookmarks($connid,nick,$jid)]
+	}
+	if {$bookmarks($connid,password,$jid) != ""} {
+	    lappend subtags [jlib::wrapper:createtag password \
+				 -chdata $bookmarks($connid,password,$jid)]
+	}
+	lappend bookmarklist [jlib::wrapper:createtag conference \
+				  -vars $vars \
+				  -subtags $subtags]
+	set vars [list jid $jid]
+	set groups {}
+	foreach group $bookmarks($connid,groups,$jid) {
+	    lappend groups [jlib::wrapper:createtag group \
+				-chdata $group]
+	}
+	lappend grouplist [jlib::wrapper:createtag conference \
+			       -vars $vars \
+			       -subtags $groups]
+    }
+
+    jlib::send_iq set \
+	[jlib::wrapper:createtag query \
+	     -vars [list xmlns $NS(private)] \
+	     -subtags [list [jlib::wrapper:createtag storage \
+				 -vars [list xmlns $NS(bookmarks)] \
+				 -subtags $bookmarklist]]] \
+	-command [list [namespace current]::store_bookmarks_result $connid] \
+	-connection $connid
+    jlib::send_iq set \
+	[jlib::wrapper:createtag query \
+	     -vars [list xmlns $NS(private)] \
+	     -subtags [list [jlib::wrapper:createtag storage \
+				 -vars [list xmlns $NS(tkabber:groups)] \
+				 -subtags $grouplist]]] \
+	-command [list [namespace current]::store_bookmarks_result $connid] \
+	-connection $connid
+}
+
+proc conferences::store_bookmarks_result {connid res child} {
+
+    if {$res == "OK"} return
+
+    if {[winfo exists .store_bookmarks_error]} {
+	return
+    }
+    MessageDlg .store_bookmarks_error -aspect 50000 -icon error \
+	-message [format [::msgcat::mc "Storing conferences failed: %s"] \
+			 [error_to_string $child]] \
+	-type user -buttons ok -default 0 -cancel 0
+}
+
+###############################################################################
+#
+#   Menu item for conference window
+#
+
+proc conferences::add_conference_menu_item {m connid jid} {
+    set chatid [chat::chatid $connid $jid]
+
+    if {[info exists ::muc::muc_password($chatid)]} {
+	set password $::muc::muc_password($chatid)
+    } else {
+	set password ""
+    }
+
+    $m add command -label [::msgcat::mc "Add conference to roster..."] \
+	-command [list [namespace current]::add_conference_dialog \
+		       -group [node_from_jid $jid] \
+		       -server [server_from_jid $jid] \
+		       -password $password \
+		       -connection $connid]
+}
+
+hook::add chat_create_conference_menu_hook \
+    [namespace current]::conferences::add_conference_menu_item 35
+
+###############################################################################
+#
+#   Add conference to roster dialog
+#
+
+proc conferences::add_conference_dialog {args} {
+    variable gra_group
+    variable gra_server
+    variable gra_nick
+    variable gra_password
+    variable gra_autojoin
+    variable gra_connid
+    variable gra_rostergroup
+
+    if {[lempty [jlib::connections]]} return
+
+    set gw .addgroup
+    catch { destroy $gw }
+
+    set connid [lindex [jlib::connections] 0]
+    set gra_server conference.[jlib::connection_server $connid]
+    set gra_group ""
+    set gra_password ""
+    set gra_autojoin 0
+    set gra_rostergroup Conferences
+    catch { unset gra_nick }
+
+    foreach {key val} $args {
+	switch -- $key {
+	    -group { set gra_group $val }
+	    -server { set gra_server $val }
+	    -nick { set gra_nick $val }
+	    -password { set gra_password $val }
+	    -autojoin { set gra_autojoin $val }
+	    -connection { set connid $val }
+	}
+    }
+
+    if {![info exists gra_nick]} {
+	set gra_nick [get_group_nick ${gra_group}@$gra_server ""]
+    }
+    set gra_connid [jlib::connection_jid $connid]
+
+    Dialog $gw -title [::msgcat::mc "Add Conference to Roster"] -separator 1 -anchor e \
+	    -default 0 -cancel 1 -parent . -modal none
+
+    set gf [$gw getframe]
+    grid columnconfigure $gf 0 -weight 0
+    grid columnconfigure $gf 1 -weight 1
+
+    label $gf.lgroup -text [::msgcat::mc "Conference:"]
+    entry $gf.group -textvariable [namespace current]::gra_group
+    label $gf.lserver -text [::msgcat::mc "Server:"]
+    entry $gf.server -textvariable [namespace current]::gra_server
+    label $gf.lnick -text [::msgcat::mc "Nick:"]
+    entry $gf.nick -textvariable [namespace current]::gra_nick
+    label $gf.lpassword -text [::msgcat::mc "Password:"]
+    entry $gf.password -show * -textvariable [namespace current]::gra_password
+    checkbutton $gf.autojoin -text [::msgcat::mc "Automatically join conference upon connect"] \
+	-variable [namespace current]::gra_autojoin
+    label $gf.lrostergroup -text [::msgcat::mc "Roster group:"]
+    ComboBox $gf.rostergroup -textvariable [namespace current]::gra_rostergroup \
+	-values [get_groups $connid]
+
+    grid $gf.lgroup  -row 0 -column 0 -sticky e
+    grid $gf.group   -row 0 -column 1 -sticky ew
+    grid $gf.lserver -row 1 -column 0 -sticky e
+    grid $gf.server  -row 1 -column 1 -sticky ew
+    grid $gf.lnick -row 2 -column 0 -sticky e
+    grid $gf.nick  -row 2 -column 1 -sticky ew
+    grid $gf.lpassword -row 3 -column 0 -sticky e
+    grid $gf.password  -row 3 -column 1 -sticky ew
+    grid $gf.autojoin -row 4 -column 0 -sticky w -columnspan 2
+    grid $gf.lrostergroup  -row 5 -column 0 -sticky e
+    grid $gf.rostergroup   -row 5 -column 1 -sticky ew
+
+    if {[llength [jlib::connections]] > 1} {
+	foreach c [jlib::connections] {
+	    lappend connections [jlib::connection_jid $c]
+	}
+	label $gf.lconnection -text [::msgcat::mc "Connection:"]
+	ComboBox $gf.connection -textvariable [namespace current]::gra_connid \
+				-values $connections -editable 0 \
+				-modifycmd [list [namespace current]::change_groups \
+						 $gf.rostergroup]
+
+	grid $gf.lconnection -row 6 -column 0 -sticky e
+	grid $gf.connection  -row 6 -column 1 -sticky ew
+    }
+    
+
+    $gw add -text [::msgcat::mc "Add"] -command [list [namespace current]::add_conference $gw]
+    $gw add -text [::msgcat::mc "Cancel"] -command [list destroy $gw]
+
+    $gw draw $gf.group
+}
+
+proc conferences::change_groups {combo args} {
+    variable gra_connid
+
+    foreach connid [jlib::connections] {
+        if {[jlib::connection_jid $connid] == $gra_connid} {
+	    $combo configure -values [get_groups $connid]
+	    return
+	}
+    }
+}
+
+proc conferences::get_groups {connid} {
+    return [roster::get_groups $connid \
+		-nested $::ifacetk::roster::options(nested) \
+		-delimiter $::ifacetk::roster::options(nested_delimiter) \
+		-undefined 0]
+}
+
+proc conferences::add_conference {gw} {
+    variable bookmarks
+    variable gra_group
+    variable gra_server
+    variable gra_nick
+    variable gra_password
+    variable gra_autojoin
+    variable gra_connid
+    variable gra_rostergroup
+
+    destroy $gw
+
+    set jid [string tolower ${gra_group}@$gra_server]
+    if {$gra_rostergroup == ""} {
+	set groups {}
+    } else {
+	set groups [list $gra_rostergroup]
+    }
+
+    foreach c [jlib::connections] {
+	if {[jlib::connection_jid $c] == $gra_connid} {
+	    set connid $c
+	}
+    }
+    if {![info exists connid]} {
+	set connid [jlib::route $jid]
+    }
+
+    if {[info exists bookmarks($connid,jid,$jid)]} {
+	update_bookmark $connid $jid -name $gra_group -nick $gra_nick \
+			-password $gra_password -autojoin $gra_autojoin \
+			-groups $groups
+    } else {
+	add_bookmark $connid $jid -name $gra_group -nick $gra_nick \
+		     -password $gra_password -autojoin $gra_autojoin \
+		     -groups $groups
+    }
+}
+
+###############################################################################
+#
+#   Add bookmark to roster
+#
+
+proc conferences::add_bookmark {connid jid args} {
+    variable bookmarks
+
+    if {[info exists bookmarks($connid,jid,$jid)]} return
+
+    foreach {key val} $args {
+	switch -- $key {
+	    -name { set name $val }
+	    -nick { set nick $val }
+	    -password { set password $val }
+	    -autojoin { set autojoin $val }
+	    -groups { set groups $val }
+	}
+    }
+
+    if {![info exists name]} {
+	set name [node_from_jid $jid]
+    }
+    if {![info exists nick]} {
+	set nick [get_group_nick $jid ""]
+    }
+    if {![info exists password]} {
+	set password ""
+    }
+    if {![info exists autojoin]} {
+	set autojoin 0
+    }
+    if {![info exists groups]} {
+	set groups {}
+    }
+
+    set bookmarks($connid,jid,$jid) $jid
+    set bookmarks($connid,name,$jid) $name
+    set bookmarks($connid,nick,$jid) $nick
+    set bookmarks($connid,password,$jid) $password
+    set bookmarks($connid,autojoin,$jid) $autojoin
+    set bookmarks($connid,groups,$jid) $groups
+
+    # TODO should we remove $jid from the roster if it is here?
+    client:roster_push $connid $jid $name $groups bookmark ""
+    roster::override_category_and_subtype $connid $jid conference ""
+    store_bookmarks $connid
+}
+
+###############################################################################
+#
+#   Update bookmark in roster
+#
+
+proc conferences::update_bookmark {connid jid args} {
+    variable bookmarks
+
+    set store 0
+
+    foreach {key val} $args {
+	switch -- $key {
+	    -name { set name $val }
+	    -nick { set nick $val }
+	    -password { set password $val }
+	    -autojoin { set autojoin $val }
+	    -groups { set groups $val }
+	}
+    }
+
+    if {[info exists name] && $name != $bookmarks($connid,name,$jid)} {
+	set bookmarks($connid,name,$jid) $name
+	set store 1
+    }
+    if {[info exists nick] && $nick != $bookmarks($connid,nick,$jid)} {
+	set bookmarks($connid,nick,$jid) $nick
+	set store 1
+    }
+    if {[info exists password] && $password != $bookmarks($connid,password,$jid)} {
+	set bookmarks($connid,password,$jid) $password
+	set store 1
+    }
+    if {[info exists autojoin] && $autojoin != $bookmarks($connid,autojoin,$jid)} {
+	set bookmarks($connid,autojoin,$jid) $autojoin
+	set store 1
+    }
+    if {[info exists groups] && [lsort $groups] != [lsort $bookmarks($connid,groups,$jid)]} {
+	set bookmarks($connid,groups,$jid) $groups
+	set store 1
+    }
+    if {$store} {
+	client:roster_push $connid $jid $bookmarks($connid,name,$jid) \
+	    $bookmarks($connid,groups,$jid) bookmark ""
+	roster::override_category_and_subtype $connid $jid conference ""
+	store_bookmarks $connid
+    }
+}
+
+###############################################################################
+#
+#   Add or update item in roster
+#
+
+proc conferences::send_bookmark {connid jid} {
+
+    if {[roster::itemconfig $connid $jid -subsc] != "bookmark"} return
+
+    set groups [roster::itemconfig $connid $jid -group]
+
+    add_bookmark $connid $jid -groups $groups
+    update_bookmark $connid $jid -groups $groups
+
+    return stop
+}
+
+hook::add roster_send_item_hook [namespace current]::conferences::send_bookmark
+
+###############################################################################
+#
+#   Remove bookmark from roster
+#
+
+proc conferences::remove_bookmark {connid jid} {
+    variable bookmarks
+
+    if {[roster::itemconfig $connid $jid -subsc] != "bookmark"} return
+
+    if {![info exists bookmarks($connid,jid,$jid)]} return
+
+    client:roster_push $connid $jid $bookmarks($connid,name,$jid) \
+		       $bookmarks($connid,groups,$jid) \
+		       remove ""
+
+    catch { unset bookmarks($connid,jid,$jid) }
+    catch { unset bookmarks($connid,name,$jid) }
+    catch { unset bookmarks($connid,nick,$jid) }
+    catch { unset bookmarks($connid,password,$jid) }
+    catch { unset bookmarks($connid,autojoin,$jid) }
+    catch { unset bookmarks($connid,groups,$jid) }
+
+    store_bookmarks $connid
+
+    return stop
+}
+
+hook::add roster_remove_item_hook \
+    [namespace current]::conferences::remove_bookmark
+
+###############################################################################
+#
+#   Rename group in roster bookmarks
+#
+
+proc conferences::rename_group {connid name new_name} {
+    variable bookmarks
+    
+    set store 0
+    foreach idx [array names bookmarks $connid,jid,*] {
+	set jid $bookmarks($idx)
+   
+	set groups $bookmarks($connid,groups,$jid)
+	if {[lcontain $groups $name] || \
+		($name == $roster::undef_group_name && $groups == {})} {
+	    set idx [lsearch -exact $groups $name]
+	    if {$new_name != ""} {
+		set groups [lreplace $groups $idx $idx $new_name]
+	    } else {
+		set groups [lreplace $groups $idx $idx]
+	    }
+	    set groups [lrmdups $groups]
+	    client:roster_push $connid $jid $bookmarks($connid,name,$jid) \
+			       $groups bookmark ""
+	    roster::override_category_and_subtype $connid $jid conference ""
+	    set bookmarks($connid,groups,$jid) $groups
+	    set store 1
+	}
+    }
+    if {$store} {
+	store_bookmarks $connid
+    }
+}
+
+hook::add roster_rename_group_hook \
+    [namespace current]::conferences::rename_group
+
+###############################################################################
+#
+#   Remove group name from roster bookmarks
+#
+
+proc conferences::remove_bookmarks_group {connid name} {
+    variable bookmarks
+
+    set store 0
+    foreach idx [array names bookmarks $connid,jid,*] {
+	set jid $bookmarks($idx)
+
+	set groups $bookmarks($connid,groups,$jid)
+	if {(([llength $groups] == 1) && [lcontain $groups $name]) || \
+		(($name == $roster::undef_group_name) && ($groups == {}))} {
+	    
+	    client:roster_push $connid $jid $bookmarks($connid,name,$jid) \
+			       $groups remove ""
+
+	    catch { unset bookmarks($connid,jid,$jid) }
+	    catch { unset bookmarks($connid,name,$jid) }
+	    catch { unset bookmarks($connid,nick,$jid) }
+	    catch { unset bookmarks($connid,password,$jid) }
+	    catch { unset bookmarks($connid,autojoin,$jid) }
+	    catch { unset bookmarks($connid,groups,$jid) }
+	    
+	    set store 1
+	} elseif {[lcontain $groups $name]} {
+	    set idx [lsearch -exact $groups $name]
+	    set groups [lreplace $groups $idx $idx]
+	    
+	    client:roster_push $connid $jid $bookmarks($connid,name,$jid) \
+			       $groups bookmark ""
+	    roster::override_category_and_subtype $connid $jid conference ""
+	    set bookmarks($connid,groups,$jid) $groups
+	    
+	    set store 1
+	}
+    }
+    if {$store} {
+	store_bookmarks $connid
+    }
+}
+
+hook::add roster_remove_users_group_hook \
+    [namespace current]::conferences::remove_bookmarks_group
+
+###############################################################################
+#
+#   Join group on roster item doubleclick
+#
+
+proc conferences::join_group {connid jid} {
+    variable bookmarks
+    
+    set args {}
+    if {$bookmarks($connid,nick,$jid) != ""} {
+	lappend args -nick $bookmarks($connid,nick,$jid)
+    }
+    if {$bookmarks($connid,password,$jid) != ""} {
+	lappend args -password $bookmarks($connid,password,$jid)
+    }
+    eval [list ::join_group $jid -connection $connid] $args
+}
+
+###############################################################################
+#
+#   Join group during autojoin
+#
+
+proc conferences::autojoin_group {connid jid} {
+    variable bookmarks
+    global gr_nick
+    
+    if {$bookmarks($connid,nick,$jid) != ""} {
+	set nick $bookmarks($connid,nick,$jid)
+    } else {
+	set nick [get_group_nick $jid $gr_nick]
+    }
+    if {$bookmarks($connid,password,$jid) != ""} {
+	set password $bookmarks($connid,password,$jid)
+    } else {
+	set password ""
+    }
+    muc::join_group $connid $jid $nick $password
+}
+
+###############################################################################
+#
+#   Autojoin groups
+#
+
+proc conferences::autojoin_groups {connid} {
+    variable bookmarks
+
+    foreach idx [array names bookmarks $connid,jid,*] {
+	set jid $bookmarks($idx)
+	if {$bookmarks($connid,autojoin,$jid)} {
+	    autojoin_group $connid $jid
+	}
+    }
+}
+
+###############################################################################
+#
+#   "Join" item in roster conference popup menu
+#
+
+proc conferences::popup_menu {m connid jid} {
+    variable bookmarks
+
+    set args {}
+    if {[roster::itemconfig $connid $jid -subsc] == "bookmark"} {
+	if {$bookmarks($connid,nick,$jid) != ""} {
+	    lappend args -nick $bookmarks($connid,nick,$jid)
+	}
+	if {$bookmarks($connid,password,$jid) != ""} {
+	    lappend args -password $bookmarks($connid,password,$jid)
+	}
+    }
+
+    $m add command -label [::msgcat::mc "Join..."] \
+	-command [list eval [list join_group_dialog \
+				  -server [server_from_jid $jid] \
+				  -group [node_from_jid $jid] \
+				  -connection $connid] \
+				  $args]
+}   
+
+hook::add roster_conference_popup_menu_hook \
+    [namespace current]::conferences::popup_menu 20
+
+###############################################################################
+#
+#   Roster doubleclick
+#
+
+proc conferences::roster_doubleclick {connid jid category subtype} {
+    switch -- $category {
+	conference {
+	    if {[roster::itemconfig $connid $jid -subsc] == "bookmark"} {
+		join_group $connid $jid
+	    } else {
+		global gr_nick
+		::join_group $jid \
+		    -nick [get_group_nick $jid $gr_nick] \
+		    -connection $connid
+	    }
+	    return stop
+	}
+    }
+}
+
+hook::add roster_jid_doubleclick \
+    [namespace current]::conferences::roster_doubleclick
+
+###############################################################################
+#
+#   Main menu setup
+#
+
+proc conferences::main_menu {} {
+    set m [.mainframe getmenu services]
+    $m insert 2 command -label [::msgcat::mc "Add conference to roster..."] \
+	-command [list [namespace current]::add_conference_dialog]
+}
+
+hook::add finload_hook [namespace current]::conferences::main_menu
+
+###############################################################################
+#
+#   Edit roster item
+#
+
+proc conferences::edit_item_setup {f connid jid} {
+    variable egra_name
+    variable egra_nick
+    variable egra_password
+    variable egra_autojoin
+    variable bookmarks
+
+    if {[roster::itemconfig $connid $jid -subsc] != "bookmark"} return
+
+    set tf [TitleFrame $f.prop \
+		-text [::msgcat::mc "Edit properties for %s" $jid]]
+    set slaves [pack slaves $f]
+    if {$slaves == ""} {
+	pack $tf -side top -expand yes -fill both
+    } else {
+	pack $tf -side top -expand yes -fill both -before [lindex $slaves 0]
+    }
+    set g [$tf getframe]
+
+    set egra_name $bookmarks($connid,name,$jid)
+    set egra_autojoin $bookmarks($connid,autojoin,$jid)
+    if {[info exists bookmarks($connid,nick,$jid)]} {
+        set egra_nick $bookmarks($connid,nick,$jid)
+    } else {
+        set egra_nick ""
+    }
+    if {[info exists bookmarks($connid,password,$jid)]} {
+        set egra_password $bookmarks($connid,password,$jid)
+    } else {
+        set egra_password ""
+    }
+
+    label $g.lname -text [string trim [::msgcat::mc "Name: "]]
+    entry $g.name -textvariable [namespace current]::egra_name
+    label $g.lnick -text [::msgcat::mc "Nick:"]
+    entry $g.nick -textvariable [namespace current]::egra_nick
+    label $g.lpassword -text [::msgcat::mc "Password:"]
+    entry $g.password -show * -textvariable [namespace current]::egra_password
+    checkbutton $g.autojoin \
+	-text [::msgcat::mc "Automatically join conference upon connect"] \
+        -variable [namespace current]::egra_autojoin
+    grid columnconfigure $g 0 -weight 0
+    grid columnconfigure $g 1 -weight 1
+
+    grid $g.lname  -row 0 -column 0 -sticky e
+    grid $g.name   -row 0 -column 1 -sticky ew
+    grid $g.lnick -row 1 -column 0 -sticky e
+    grid $g.nick  -row 1 -column 1 -sticky ew
+    grid $g.lpassword -row 2 -column 0 -sticky e
+    grid $g.password  -row 2 -column 1 -sticky ew
+    grid $g.autojoin -row 3 -column 0 -sticky w -columnspan 2
+
+    return stop
+}
+
+hook::add roster_itemedit_setup_hook \
+    [namespace current]::conferences::edit_item_setup
+
+proc conferences::commit_bookmark_changes {connid jid groups} {
+    variable egra_name
+    variable egra_nick
+    variable egra_password
+    variable egra_autojoin
+
+    if {[roster::itemconfig $connid $jid -subsc] != "bookmark"} return
+
+    plugins::conferences::update_bookmark $connid $jid \
+	-name $egra_name -nick $egra_nick -password $egra_password \
+	-autojoin $egra_autojoin -groups $groups
+
+    return stop
+}
+
+hook::add roster_itemedit_commit_hook \
+    [namespace current]::conferences::commit_bookmark_changes
+
+###############################################################################
+

Copied: trunk/tkabber/plugins/roster/roster_delimiter.tcl (from rev 705, trunk/tkabber/plugins/general/roster_delimiter.tcl)
===================================================================
--- trunk/tkabber/plugins/roster/roster_delimiter.tcl	                        (rev 0)
+++ trunk/tkabber/plugins/roster/roster_delimiter.tcl	2006-09-09 10:24:10 UTC (rev 707)
@@ -0,0 +1,89 @@
+# $Id$
+#
+# Nested roster groups server-side delimiter storing (JEP-0083).
+#
+###############################################################################
+
+namespace eval delimiter {}
+
+###############################################################################
+#
+# Retrieving nested groups delimiter
+#
+
+proc delimiter::request {connid fallback args} {
+    debugmsg plugins "delimiter::request $connid $fallback $args"
+    
+    set command ""
+    foreach {key val} $args {
+	switch -- $key {
+	    -command { set command $val }
+	}
+    }
+    
+    jlib::send_iq get \
+	[jlib::wrapper:createtag query \
+	     -vars [list xmlns $::NS(private)] \
+	     -subtags [list [jlib::wrapper:createtag roster \
+				 -vars [list xmlns $::NS(delimiter)]]]] \
+	-command [list [namespace current]::request_result \
+		       $connid $fallback $command] \
+	-connection $connid
+}
+
+proc delimiter::request_result {connid fallback command res child} {
+    debugmsg plugins "delimiter::request_result $connid $res"
+
+    set delimiter $fallback
+
+    if {$res == "OK"} {
+	jlib::wrapper:splitxml $child tag vars isempty cdata children
+
+	foreach ch $children {
+	    jlib::wrapper:splitxml $ch tag1 vars1 isempty1 cdata1 children1
+
+	    if {[jlib::wrapper:getattr $vars1 xmlns] == $NS(delimiter)} {
+		set delimiter $cdata1
+	    }
+	}
+    }
+
+    if {$command != ""} {
+	eval $command [list $connid $delimiter]
+    }
+}
+
+###############################################################################
+#
+# Storing nested groups delimiter
+#
+
+proc delimiter::store {connid delimiter args} {
+    debugmsg plugins "delimiter::store $connid $delimiter $args"
+
+    set command ""
+    foreach {key val} $args {
+	switch -- $key {
+	    -command { set command $val }
+	}
+    }
+    
+    jlib::send_iq set \
+	[jlib::wrapper:createtag query \
+	     -vars [list xmlns $::NS(private)] \
+	     -subtags [list [jlib::wrapper:createtag roster \
+				 -vars [list xmlns $::NS(delimiter)] \
+				 -chdata $delimiter]]] \
+	-command [list [namespace current]::store_result $connid $command] \
+	-connection $connid
+    
+}
+
+proc delimiter::store_result {connid command res child} {
+    debugmsg plugins "delimiter::store_result $connid $res"
+    
+    if {$command != ""} {
+	eval $command [list $res $child]
+    }
+}
+

Copied: trunk/tkabber/plugins/roster/rosterx.tcl (from rev 705, trunk/tkabber/plugins/general/rosterx.tcl)
===================================================================
--- trunk/tkabber/plugins/roster/rosterx.tcl	                        (rev 0)
+++ trunk/tkabber/plugins/roster/rosterx.tcl	2006-09-09 10:24:10 UTC (rev 707)
@@ -0,0 +1,211 @@
+# $Id$
+# Roster Item Exchange Support (JEP-0093 and JEP-0144)
+
+namespace eval rosterx {}
+
+###############################################################################
+
+proc rosterx::process_x {acc f x connid from type replyP} {
+    lassign $acc row body
+
+    set rosterx 0
+    foreach xa $x {
+	jlib::wrapper:splitxml $xa tag vars isempty chdata children
+
+	set xmlns [jlib::wrapper:getattr $vars xmlns]
+	switch -- $xmlns \
+	    $::NS(rosterx) {
+		set rosterx 1
+		foreach child $children {
+		    process_x_rosterx $f $child $row $from
+		    incr row
+		}
+	    } \
+	    $::NS(xroster) {
+		if {$rosterx} break
+		foreach child $children {
+		    process_x_xroster $f $child $row $from
+		    incr row
+		}
+	    } \
+	}
+
+    return [list $row $body]
+}
+
+hook::add message_process_x_hook [namespace current]::rosterx::process_x 60
+
+###############################################################################
+
+proc rosterx::process_x_rosterx {f x row from} {
+    jlib::wrapper:splitxml $x tag vars isempty chdata children
+
+    set jid [jlib::wrapper:getattr $vars jid]
+    set name [jlib::wrapper:getattr $vars name]
+    set action [jlib::wrapper:getattr $vars action]
+
+    if {$jid == ""} return
+
+    if {$name != ""} {
+        set desc "$name ($jid)"
+    } else {
+        set desc $jid
+    }
+
+    label $f.luser$row -text [::msgcat::mc "Attached user:"]
+    set cb [button $f.user$row -text $desc \
+                -command [list [namespace current]::process_user $jid \
+                              "$from asked me to add you to my roster."]]
+    grid $f.luser$row -row $row -column 0 -sticky e
+    grid $f.user$row  -row $row -column 1 -sticky ew
+}
+
+###############################################################################
+
+proc rosterx::process_x_xroster {f x row from} {
+    jlib::wrapper:splitxml $x tag vars isempty chdata children
+
+    set jid [jlib::wrapper:getattr $vars jid]
+    set name [jlib::wrapper:getattr $vars name]
+
+    if {$jid == ""} return
+
+    if {$name != ""} {
+        set desc "$name ($jid)"
+    } else {
+        set desc $jid
+    }
+
+    label $f.luser$row -text [::msgcat::mc "Attached user:"]
+    set cb [button $f.user$row -text $desc \
+                -command [list [namespace current]::process_user $jid \
+                              "$from asked me to add you to my roster."]]
+    grid $f.luser$row -row $row -column 0 -sticky e
+    grid $f.user$row  -row $row -column 1 -sticky ew
+}
+
+###############################################################################
+
+proc rosterx::process_user {jid body} {
+    jlib::send_presence -to $jid -type subscribe -stat $body
+
+    jlib::send_iq set \
+        [jlib::wrapper:createtag query \
+             -vars [list xmlns $::NS(roster)] \
+             -subtags [list [jlib::wrapper:createtag item \
+                                     -vars [list jid $jid]]]]
+}
+
+###############################################################################
+
+proc rosterx::send_users_dialog {connid user} {
+    global send_uc
+
+    set jid [get_jid_of_user $connid $user]
+
+    if {[cequal $jid ""]} {
+        set jid $user
+    }
+
+    set gw .contacts
+    catch { destroy $gw }
+
+    if {[catch { set nick [roster::get_label $connid $user] }]} {
+	if {[catch { set nick [chat::get_nick $connid \
+					      $user groupchat] }]} {
+	    set nick $user
+	}
+    }
+
+    set choices {}
+    set balloons {}
+    foreach c [jlib::connections] {
+	foreach choice [roster::get_jids $c] {
+	    if {[roster::itemconfig $c $choice -isuser]} {
+		lappend choices [list $c $choice] [roster::get_label $c $choice]
+		lappend balloons [list $c $choice] $choice
+	    }
+	}
+    }
+    if {[llength $choices] == 0} {
+        MessageDlg ${gw}_err -aspect 50000 -icon info \
+	    -message [::msgcat::mc "No users in roster..."] -type user \
+	    -buttons ok -default 0 -cancel 0
+        return
+    }
+
+    CbDialog $gw [format [::msgcat::mc "Send contacts to %s"] $nick] \
+	[list [::msgcat::mc "Send"] \
+	      [list [namespace current]::send_users $gw $jid -connection $connid] \
+	      [::msgcat::mc "Cancel"] \
+	      [list destroy $gw]] \
+	send_uc $choices $balloons
+}
+
+###############################################################################
+
+proc rosterx::add_menu_item {m connid jid} {
+    $m add command \
+	   -label [::msgcat::mc "Send users..."] \
+           -command [list [namespace current]::send_users_dialog $connid $jid]
+}
+
+hook::add roster_create_groupchat_user_menu_hook \
+    [namespace current]::rosterx::add_menu_item 45
+hook::add chat_create_user_menu_hook \
+    [namespace current]::rosterx::add_menu_item 45
+hook::add roster_jid_popup_menu_hook \
+    [namespace current]::rosterx::add_menu_item 45
+hook::add message_dialog_menu_hook \
+    [namespace current]::rosterx::add_menu_item 45
+hook::add search_popup_menu_hook \
+    [namespace current]::rosterx::add_menu_item 45
+
+###############################################################################
+
+proc rosterx::send_users {gw jid args} {
+    global send_uc
+
+    foreach {opt val} $args {
+	switch -- $opt {
+	    -connection { set connid $val }
+	}
+    }
+    if {![info exists connid]} {
+	set connid [jlib::route $jid]
+    }
+
+    set sf [$gw getframe].sw.sf
+    set choices {}
+    foreach uc [array names send_uc] {
+        if {$send_uc($uc)} {
+            lappend choices $uc
+        }
+    }
+
+    destroy $gw
+
+    set subtags {}
+    set body [::msgcat::mc "Contact Information"]
+    foreach choice $choices {
+	lassign $choice con uc
+	lappend subtags [roster::item_to_xml $con $uc]
+	set nick [roster::get_label $con $uc]
+        append body "\n$nick - xmpp:$uc"
+    }
+
+    message::send_msg $jid -type normal -body $body \
+	-xlist [list \
+		    [jlib::wrapper:createtag x \
+			 -vars [list xmlns $::NS(rosterx)] \
+	                 -subtags $subtags] \
+		    [jlib::wrapper:createtag x \
+			 -vars [list xmlns $::NS(xroster)] \
+	                 -subtags $subtags]] \
+	-connection $connid
+}
+
+###############################################################################
+
+disco::register_feature $::NS(rosterx)
+

Modified: trunk/tkabber/plugins/unix/wmdock.tcl
===================================================================
--- trunk/tkabber/plugins/unix/wmdock.tcl	2006-09-05 20:19:00 UTC (rev 706)
+++ trunk/tkabber/plugins/unix/wmdock.tcl	2006-09-09 10:24:10 UTC (rev 707)
@@ -55,7 +55,7 @@
     set balloon_msg [format [::msgcat::mc "Message from %s"] $from]
     
     after cancel $msg_afterid
-    .icon.c itemconfigure icon -image browser/message
+    .icon.c itemconfigure icon -image docking/message
     .icon.c itemconfigure text -text [format [::msgcat::mc "%s msgs"] $msgs]
     
     set msg_afterid [after 5000 ::wmdock::clear_msg_status]

Modified: trunk/tkabber/roster.tcl
===================================================================
--- trunk/tkabber/roster.tcl	2006-09-05 20:19:00 UTC (rev 706)
+++ trunk/tkabber/roster.tcl	2006-09-09 10:24:10 UTC (rev 707)
@@ -13,12 +13,12 @@
 	unavailable [::msgcat::mc "%s is unavailable"]]
 }
 
-proc roster::process_item {connid jid name groups subsc ask category subtype} {
+proc roster::process_item {connid jid name groups subsc ask} {
     variable roster
     variable undef_group_name
     variable chats_group_name
 
-    debugmsg roster "ROSTER_ITEM: $jid; $name; $groups; $subsc; $ask; $category; $subtype"
+    debugmsg roster "ROSTER_ITEM: $connid; $jid; $name; $groups; $subsc; $ask"
 
     set jid [tolower_node_and_domain $jid]
 
@@ -37,12 +37,9 @@
 	set roster(name,$connid,$jid)     $name
 	set roster(subsc,$connid,$jid)    $subsc
 	set roster(ask,$connid,$jid)      $ask
-	set roster(category,$connid,$jid) $category
-	set roster(subtype,$connid,$jid)  $subtype
 
 	catch {unset roster(cached_category_and_subtype,$connid,$jid)}
-	lassign [get_category_and_subtype $connid $jid] ccategory csubtype
-	set roster(isuser,$connid,$jid) [cequal $ccategory user]
+	get_category_and_subtype $connid $jid
     } else {
 	lvarpop roster(jids,$connid) [lsearch -exact $roster(jids,$connid) $jid]
 
@@ -50,9 +47,6 @@
 	catch {unset roster(name,$connid,$jid)}
 	catch {unset roster(subsc,$connid,$jid)}
 	catch {unset roster(ask,$connid,$jid)}
-	catch {unset roster(category,$connid,$jid)}
-	catch {unset roster(subtype,$connid,$jid)}
-	catch {unset roster(isuser,$connid,$jid)}
 	catch {unset roster(cached_category_and_subtype,$connid,$jid)}
     }
 }
@@ -60,14 +54,12 @@
 hook::add roster_item_hook [namespace current]::roster::process_item
 hook::add roster_push_hook [namespace current]::roster::process_item
 
-proc client:roster_item {connid jid name groups subsc ask category subtype} {
-    hook::run roster_item_hook \
-	$connid $jid $name $groups $subsc $ask $category $subtype
+proc client:roster_item {connid jid name groups subsc ask} {
+    hook::run roster_item_hook $connid $jid $name $groups $subsc $ask 
 }
 
-proc client:roster_push {connid jid name groups subsc ask category subtype} {
-    hook::run roster_push_hook \
-	$connid $jid $name $groups $subsc $ask $category $subtype
+proc client:roster_push {connid jid name groups subsc ask} {
+    hook::run roster_push_hook $connid $jid $name $groups $subsc $ask
     ::redraw_roster
 }
 
@@ -210,13 +202,13 @@
 	    -ask      {set param ask}
 	    -category {set param category}
 	    -subtype  {set param subtype}
-	    -isuser   {set param isuser}
-	    default {return}
+	    -isuser   {
+		return [cequal [lindex [get_category_and_subtype $connid $jid] 0] "user"]
+	    }
+	    default   {return -code error "Illegal option"}
 	}
 	if {[info exists roster($param,$connid,$jid)]} {
 	    return $roster($param,$connid,$jid)
-	} elseif {$param == "isuser"} {
-	    return 0
 	} else {
 	    return ""
 	}
@@ -229,8 +221,7 @@
 		-ask      {set param ask}
 		-category {set param category}
 		-subtype  {set param subtype}
-		-isuser   {set param isuser}
-		default   {set param ""}
+		default   {return -code error "Illegal option"}
 	    }
 	    set roster($param,$connid,$jid) $val
 	}
@@ -271,14 +262,18 @@
 proc roster::find_jid {connid jid} {
     variable roster
 
-    if {[info exists roster(category,$connid,$jid)]} {
+    if {![info exists roster(jids,$connid)]} {
+	return ""
+    }
+
+    if {[lsearch -exact $roster(jids,$connid) $jid] >= 0} {
 	return $jid
     }
 
     lassign [get_category_and_subtype $connid $jid] category subtype
     if {$category == "user"} {
 	set rjid [node_and_server_from_jid $jid]
-	if {[info exists roster(category,$connid,$rjid)]} {
+	if {[lsearch -exact $roster(jids,$connid) $rjid] >= 0} {
 	    lassign [get_category_and_subtype $connid $rjid] rcategory rsubtype
 	    if {$category == $rcategory} {
 		return $rjid
@@ -297,6 +292,13 @@
     }
 }
 
+proc roster::override_category_and_subtype {connid jid category subtype} {
+    variable roster
+
+    set roster(cached_category_and_subtype,$connid,$jid) \
+	[list $category $subtype]
+}
+
 proc roster::get_category_and_subtype {connid jid} {
     variable roster
 
@@ -304,11 +306,8 @@
 	return $roster(cached_category_and_subtype,$connid,$jid)
     }
 
-    if {[info exists roster(category,$connid,$jid)] && \
-	    $roster(category,$connid,$jid) != ""} {
-	return [list $roster(category,$connid,$jid) $roster(subtype,$connid,$jid)]
-    }
-    
+    catch { plugins::cache_categories::request_category_and_subtype $connid $jid }
+
     return [heuristically_get_category_and_subtype $connid $jid]
 }
 
@@ -316,23 +315,38 @@
     variable roster
 
     set node [node_from_jid $jid]
-    set updomain [lindex [split [server_from_jid $jid] .] 0]
+    set server [server_from_jid $jid]
 
     if {$node == ""} {
+	set updomain [lindex [split $server .] 0]
 	set category service
 
-	if {[lcontain {aim icq irc jabber jud msn pager rss serverlist \
-			   sms smtp yahoo} $updomain]} {
-	    set subtype $updomain
-	} elseif {[cequal icqv7 $updomain]} {
-	    set subtype icq
-	} elseif {[cequal gg $updomain]} {
-	    set subtype x-gadugadu
-	} elseif {([cequal pogoda $updomain]) \
-		      || ([cequal weather $updomain])} {
-	    set subtype x-weather
-	} else {
-	    set subtype ""
+	switch -- $updomain {
+	    aim        -
+	    icq        -
+	    irc        -
+	    jabber     -
+	    jud        -
+	    msn        -
+	    mrim       -
+	    pager      -
+	    rss        -
+	    serverlist -
+	    sms	       -
+	    smtp       -
+	    yahoo {
+		set subtype $updomain
+	    }
+	    gg {
+		set subtype x-gadugadu
+	    }
+	    pogoda -
+	    weather {
+		set subtype x-weather
+	    }
+	    default {
+		set subtype ""
+	    }
 	}
 
 	set roster(cached_category_and_subtype,$connid,$jid) [list $category $subtype]
@@ -340,28 +354,32 @@
     }
 
     if {[resource_from_jid $jid] == ""} {
-	switch -- $updomain {
-	    tach -
-	    conference {
-		set category conference
-		set subtype ""
-	    }
-	    irc {
-		set category user
-		set subtype ""
-		if {[string first "%" $node] != -1} {
+	lassign [get_category_and_subtype $connid $server] scategory ssubtype
+
+	switch -glob -- $scategory/$ssubtype {
+	    conference/irc {
+		if {[string first "%" $node] >= 0} {
 		    set category conference
 		    set subtype irc
+		} else {
+		    set category user
+		    set subtype ""
 		}
 	    }
+	    conference/* {
+		set category conference
+		set subtype ""
+	    }
 	    default {
 		set category user
 		set subtype ""
 	    }
 	}
+
 	set roster(cached_category_and_subtype,$connid,$jid) [list $category $subtype]
 	return [list $category $subtype]
     }
+
     set roster(cached_category_and_subtype,$connid,$jid) {user client}
     return {user client}
 }
@@ -376,7 +394,6 @@
     array unset roster ask,*
     array unset roster category,*
     array unset roster subtype,*
-    array unset roster isuser,*
     array unset roster cached_category_and_subtype,*
     ::redraw_roster
 }
@@ -391,16 +408,11 @@
     array unset roster ask,$connid,*
     array unset roster category,$connid,*
     array unset roster subtype,$connid,*
-    array unset roster isuser,$connid,*
     array unset roster cached_category_and_subtype,$connid,*
 
     ::redraw_roster
 }
 
-proc roster::is_user {connid jid} {
-    return [cequal [lindex [get_category_and_subtype $connid $jid] 0] "user"]
-}
-
 ###############################################################################
 
 proc roster::item_to_xml {connid jid} {
@@ -676,3 +688,5 @@
     }
 }
 
+###############################################################################
+

Modified: trunk/tkabber/tkabber.tcl
===================================================================
--- trunk/tkabber/tkabber.tcl	2006-09-05 20:19:00 UTC (rev 706)
+++ trunk/tkabber/tkabber.tcl	2006-09-09 10:24:10 UTC (rev 707)
@@ -255,6 +255,7 @@
 load_source ifacetk iface.tcl
 
 plugins::load [file join plugins general]
+plugins::load [file join plugins roster]
 plugins::load [file join plugins search]
 plugins::load [file join plugins $tcl_platform(platform)]
 if {[info exists env(TKABBER_SITE_PLUGINS)] && \



More information about the Tkabber-dev mailing list