diff -Naur Tkabber-orig/chats.tcl Tkabber/chats.tcl
--- Tkabber-orig/chats.tcl	2006-07-22 14:33:53.000000000 +0400
+++ Tkabber/chats.tcl	2006-07-22 21:21:37.850266400 +0400
@@ -691,6 +691,16 @@
     return $chats(inputwin,$chatid)
 }
 
+proc chat::search_panel {chatwin {spanel ""}} {
+	variable chats
+
+	if {![cequal $spanel ""]} {
+		set chats(spanel,$chatwin) $spanel
+	}
+
+	return $chats(spanel,$chatwin)
+}
+
 proc chat::is_groupchat {chatid} {
     variable chats
     if {[info exists chats(type,$chatid)]} {
diff -Naur Tkabber-orig/disco-search.tcl Tkabber/disco-search.tcl
--- Tkabber-orig/disco-search.tcl	1970-01-01 03:00:00.000000000 +0300
+++ Tkabber/disco-search.tcl	2006-07-22 21:28:01.600266400 +0400
@@ -0,0 +1,275 @@
+# Searching in the descovery window.
+# $Id: disco-search.tcl 13 2006-07-21 00:06:48Z kostix $
+
+proc disco::browser::search_open_panel {bw {nocheck 0}} {
+	variable browser
+	
+	set f $browser(search,$bw,panel)
+
+	if {$nocheck && [winfo ismapped $f]} return
+
+	search_reset $bw
+	
+	pack $f -side bottom -fill x
+	focus $f
+}
+
+
+
+proc disco::browser::search_close_panel {bw {nocheck 0}} {
+	variable browser
+
+	set f $browser(search,$bw,panel)
+
+	if {$nocheck && ![winfo ismapped $f]} return
+
+	pack forget $browser(search,$bw,panel)
+}
+
+
+
+proc disco::browser::search_toggle_panel {bw} {
+	variable browser
+	
+	set f $browser(search,$bw,panel)
+
+	if {[winfo ismapped $f]} {
+		search_close_panel $bw 1
+	} else {
+		search_open_panel $bw 1
+	}
+}
+
+
+
+proc disco::browser::search_setup_panel {bw} {
+	variable browser
+
+	# Main frame -- the search panel itself:
+	set panel [frame $bw.search]
+	set browser(search,$bw,panel) $panel
+
+	# Top frame: pattern entry and buttons:
+
+	set tf [frame $panel.top]
+
+	button $tf.close -text [::msgcat::mc Close] -command \
+		[list [namespace current]::search_close_panel $bw]
+	button $tf.sup -text [::msgcat::mc {Search up}] \
+		-command [list [namespace current]::search_next $bw up]
+	button $tf.sdown -text [::msgcat::mc {Search down}] \
+		-command [list [namespace current]::search_next $bw down]
+	button $tf.reset -text [::msgcat::mc Reset] \
+		-command [list [namespace current]::search_reset $bw]
+	pack $tf.close $tf.reset $tf.sdown $tf.sup -side right
+
+	entry $tf.pattern \
+		-textvar [namespace current]::browser(search,$bw,pattern)
+	pack $tf.pattern -side left -fill x -expand true
+
+	pack $tf -fill x
+
+	# Middle frame: search mode toggles + status label:
+
+	set mf [frame $panel.middle]
+
+	set browser(search,$bw,mode) jid/node
+
+	label $mf.stext -text [::msgcat::mc {Search by:}] -padx 0
+	radiobutton $mf.jid -text [::msgcat::mc JID/node] \
+		-value jid/node \
+		-variable [namespace current]::browser(search,$bw,mode)
+	radiobutton $mf.title -text [::msgcat::mc name] \
+		-value name \
+		-variable [namespace current]::browser(search,$bw,mode)
+	pack $mf.stext $mf.jid $mf.title -side left
+
+	label $mf.status -anchor e \
+		-textvar [namespace current]::browser(search,$bw,status)
+	pack $mf.status -side right -fill x
+
+	pack $mf -fill x
+
+	# Bottom frame: matching modes + case insensetiveness:
+
+	set bf [frame $panel.bottom]
+
+	label $bf.lmatch -text [::msgcat::mc {Match using:}] -padx 0
+
+	set browser(search,$bw,match) glob
+
+	radiobutton $bf.glob -text [::msgcat::mc glob-style] \
+		-value glob \
+		-variable [namespace current]::browser(search,$bw,match)
+	radiobutton $bf.regexp -text [::msgcat::mc regexp] \
+		-value regexp \
+		-variable [namespace current]::browser(search,$bw,match)
+	radiobutton $bf.exact -text [::msgcat::mc exact] \
+		-value exact \
+		-variable [namespace current]::browser(search,$bw,match)
+
+	set browser(search,$bw,nocase) 1
+
+	checkbutton $bf.nocase -text [::msgcat::mc {Case insensitive}] \
+		-anchor e \
+		-variable [namespace current]::browser(search,$bw,nocase)
+
+	pack $bf.lmatch $bf.glob $bf.regexp $bf.exact -side left
+	pack $bf.nocase -side right
+
+	pack $bf -fill x
+}
+
+
+
+proc disco::browser::search_next {bw direction} {
+	variable browser
+
+	if {[cequal $browser(search,$bw,pattern) ""]} {
+		search_set_status $bw [::msgcat::mc {No pattern to search}]
+		return
+	}
+
+	search_set_status $bw ""
+
+    set tw $browser(tree,$bw)
+	
+	# Get the root-of-the-search node:
+	set tnode [search_get_root $bw]
+	if {[cequal $tnode ""]} { # no root, no selection
+		search_set_status $bw [::msgcat::mc {Select a populated item}]
+		return
+	}
+
+    lassign [$tw itemcget $tnode -data] type
+	if {![cequal $type item]} { # cannot search on non-items
+		search_set_status $bw [::msgcat::mc {Select a populated item}]
+		return
+	}
+
+	# Save root node, if needed:
+	if {![info exists browser(search,$bw,root)]} {
+		set browser(search,$bw,root) $tnode
+	}
+
+	# Get list of children nodes
+	set children [$tw nodes $tnode]
+	set len [llength $children]
+
+	# Setup iterate-by-children loop based on the search direction
+	if {[cequal $direction down]} {
+		if {[info exists browser(search,$bw,lastix)]} {
+			set ix $browser(search,$bw,lastix)
+			incr ix ;# next to last
+		} else { # just on the 1st element
+			set ix 0
+		}
+		set cond {$ix < $len}
+		set post {incr ix}
+	} else { # up
+		if {[info exists browser(search,$bw,lastix)]} {
+			set ix $browser(search,$bw,lastix)
+			incr ix -1 ;# prev to last
+		} else { # just on the last element
+			set ix [expr $len - 1]
+		}
+		set cond {$ix >= 0}
+		set post {incr ix -1}
+	}
+	
+	# Now $ix is the index of the children to start searching from
+
+	for {} $cond $post {
+		set child [lindex $children $ix]
+
+		set data [lassign [$tw itemcget $child -data] type]
+
+		if {![cequal $type item]} continue
+
+		lassign $data jid node
+
+		if {[cequal $browser(search,$bw,mode) name]} {
+			set what [[namespace parent]::get_jid_name $jid $node]
+		} else {
+			set what $jid
+		}
+
+		if {[search_match $bw $what]} {
+			set browser(search,$bw,lastix) $ix
+			search_hilite $tw $child
+			return
+		}
+	}
+
+	search_set_status $bw [::msgcat::mc {Nothing was found}]
+}
+
+
+
+proc disco::browser::search_match {bw what} {
+	variable browser
+
+	set pat $browser(search,$bw,pattern)
+
+	if {$browser(search,$bw,nocase)} {
+		set args [list -nocase $pat $what]
+	} else {
+		set args [list $pat $what]
+	}
+
+	switch -- $browser(search,$bw,match) {
+		exact {
+			return [eval string equal $args]
+		}
+		glob {
+			return [eval string match $args]
+		}
+		regexp {
+			return [eval regexp $args]
+		}
+	}
+
+	return 0
+}
+
+
+
+proc disco::browser::search_hilite {tw tnode} {
+	$tw see $tnode
+	$tw selection set $tnode
+}
+
+
+
+proc disco::browser::search_set_status {bw status} {
+	variable browser
+	set browser(search,$bw,status) $status
+}
+
+
+
+proc disco::browser::search_reset {bw} {
+	variable browser
+
+	set tnode [search_get_root $bw]
+	if {$tnode != ""} {
+		search_hilite $browser(tree,$bw) $tnode
+	}
+
+	search_set_status $bw ""
+
+	unset -nocomplain browser(search,$bw,root)
+	unset -nocomplain browser(search,$bw,lastix)
+}
+
+
+
+proc disco::browser::search_get_root {bw} {
+	variable browser
+
+	if {[info exists browser(search,$bw,root)]} {
+		return $browser(search,$bw,root)
+	} else {
+		return [lindex [$browser(tree,$bw) selection get] 0]
+	}
+}
diff -Naur Tkabber-orig/disco.tcl Tkabber/disco.tcl
--- Tkabber-orig/disco.tcl	2006-03-17 07:29:42.000000000 +0300
+++ Tkabber/disco.tcl	2006-07-22 20:03:58.053391400 +0400
@@ -1,4 +1,4 @@
-# $Id: disco.tcl,v 1.42 2006/03/17 04:29:42 aleksey Exp $
+# $Id: disco.tcl 12 2006-07-20 17:31:59Z kostix $
 
 set ::NS(disco_items) "http://jabber.org/protocol/disco#items"
 set ::NS(disco_info)  "http://jabber.org/protocol/disco#info"
@@ -440,6 +440,8 @@
     set config(identitycolor) [option get $w identitycolor JDisco]
     set config(optioncolor)   [option get $w optioncolor   JDisco]
 
+	bind $w <Destroy> [list [namespace current]::destroy_state $w]
+
     frame $w.navigate
     button $w.navigate.back -text <- \
 	-command [list [namespace current]::history_move $w 1]
@@ -502,6 +504,10 @@
     set browser(hist,$w) {}
     set browser(histpos,$w) 0
 
+    search_setup_panel $w
+    bind $w <<OpenSearchPanel>> \
+        [list [namespace current]::search_toggle_panel $w]
+
     go $w
 }
 
@@ -1245,6 +1251,23 @@
     }
 }
 
+
+
+# Destroy all (global) state assotiated with the given browser window.
+# Intended to be bound to a <Destroy> event handler for browser windows.
+proc disco::browser::destroy_state {bw} {
+	variable browser
+
+	array unset browser(*,$bw)
+	array unset browser(*,$bw,*)
+
+	foreach ix [lsearch -all $browser(opened) $bw] {
+		set browser(opened) [lreplace $browser(opened) $ix $ix]
+	}
+}
+
+
+
 hook::add postload_hook \
     [list browser::register_ns_handler $::NS(disco_info) disco::browser::open_win \
 	 -desc [list * [::msgcat::mc "Discover service"]]]
diff -Naur Tkabber-orig/ifacetk/iface.tcl Tkabber/ifacetk/iface.tcl
--- Tkabber-orig/ifacetk/iface.tcl	2006-07-22 14:33:53.000000000 +0400
+++ Tkabber/ifacetk/iface.tcl	2006-07-22 21:33:09.990891400 +0400
@@ -2,6 +2,7 @@
 
 namespace eval ifacetk {
     variable options
+    variable toplevel_events
 
     custom::defgroup IFace \
 	[::msgcat::mc "Options for main interface."] \
@@ -1369,3 +1370,33 @@
 	-message $message -type user -buttons ok -default 0 -cancel 0
 }
 
+# Synthesize the given event in the frame that is packed in the
+# frame (ouch!) of the active tab (for tabbed interface).
+# NOTE that if the target frame hasn't any handler for the event,
+# it is (usually) passed back to the toplevel, so we guard against
+# multiple runs for the same event.
+proc ifacetk::dispatch_event_to_active_tab {event} {
+	variable toplevel_events
+
+	if {[info exists toplevel_events($event)]} return
+
+	set page [.nb raise]
+	if {$page == {}} return
+	set frame [lindex [pack slaves [.nb getframe $page]] 0]
+
+	set toplevel_events($event) 1
+	event generate $frame $event
+	unset toplevel_events($event)
+}
+
+event add <<OpenSearchPanel>> <Control-s>
+
+proc ifacetk::install_toplevel_events {} {
+	if {!$::usetabbar} return
+
+	foreach event {<<OpenSearchPanel>>} {
+		bind . $event [list ifacetk::dispatch_event_to_active_tab $event]
+	}
+}
+
+hook::add finload_hook ifacetk::install_toplevel_events
diff -Naur Tkabber-orig/plugins/chat/search.tcl Tkabber/plugins/chat/search.tcl
--- Tkabber-orig/plugins/chat/search.tcl	2005-08-29 00:46:15.000000000 +0400
+++ Tkabber/plugins/chat/search.tcl	2006-07-22 21:18:19.631516400 +0400
@@ -1,6 +1,8 @@
 # $Id: search.tcl,v 1.4 2005/08/28 20:46:15 aleksey Exp $
 
-proc open_search_panel {sf chatw} {
+proc open_search_panel {chatw} {
+	set sf [chat::search_panel $chatw]
+
     set sentry $sf.search
 
     pack $sf -side bottom -anchor w -fill x -before [winfo parent $chatw].csw
@@ -29,6 +31,8 @@
 
     set sf [frame [winfo parent $chatw].search]
 
+	chat::search_panel $chatw $sf
+
     #set slabel [label $sf.slabel -text [::msgcat::mc "Search:"]]
     #pack $slabel -side left
 
@@ -52,9 +56,8 @@
     bind $sentry <Escape> \
 	[double% [list [namespace current]::close_search_panel $sf $chatid]]
 
-    event add <<OpenSearchPanel>> <Control-s>
-    bind $cw.input <<OpenSearchPanel>> \
-	[double% [list [namespace current]::open_search_panel $sf $chatw]]
+    bind $cw <<OpenSearchPanel>> \
+		[double% [list [namespace current]::open_search_panel $chatw]]
 }
 
 hook::add open_chat_post_hook [namespace current]::setup_search_panel
diff -Naur Tkabber-orig/tkabber.tcl Tkabber/tkabber.tcl
--- Tkabber-orig/tkabber.tcl	2006-06-09 00:21:44.000000000 +0400
+++ Tkabber/tkabber.tcl	2006-07-22 21:27:00.365891400 +0400
@@ -237,6 +237,7 @@
 load_source login.tcl
 load_source browser.tcl
 load_source disco.tcl
+load_source disco-search.tcl
 load_source userinfo.tcl
 load_source datagathering.tcl
 load_source negotiate.tcl
