# Copyright (c) 2000, Red Hat, Inc.
# 
# This file is part of Source-Navigator.
# 
# Source-Navigator is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as published
# by the Free Software Foundation; either version 2, or (at your option)
# any later version.
# 
# Source-Navigator is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
# 
# You should have received a copy of the GNU General Public License along
# with Source-Navigator; see the file COPYING.  If not, write to
# the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
# MA 02111-1307, USA.
# 
#####################################################
##
## Class Browser that can be integrated in any subwindow.
##
#####################################################
itcl_class Class& {
	constructor {{config ""}} {
		global sn_options
		
		set class [$this info class]
		@@rename $this $this-tmp-
		@@frame $this -class $class
		@@rename $this $this-win-
		@@rename $this-tmp- $this
		
		set topw [winfo toplevel $this]
		set cls [info class]
		
		set pw [tixPanedWindow $this.paned \
					-orientation $sn_options(def,class-orientation)]
		if {$sn_options(def,members-order) == "first"} {
			set mempane [$pw add mem -expand 0.8]
			set clspane [$pw add cls -expand 0.2]
		} else {
			set clspane [$pw add cls -expand 0.2]
			set mempane [$pw add mem -expand 0.8]
		}
		set memlist $mempane.list
		
		#classname to browse
		global $memlist-class_name $this-visib
		@@set $memlist-class_name $classname
		@@set $this-visib 0
		
		#init mixer variables
		set i 0
		foreach p $mixer_vars {
			upvar #0 $this-mixer-$p mv
			if {$i < 6} {
				set mv 1
			} else {
				set mv 0
			}
			incr i
		}
		upvar #0 $memlist-and and
		set and 0
		
		#restore old setting
		if {$flags != ""} {
			set i 0
			foreach p $mixer_vars {
				upvar #0 $this-mixer-$p mv
				set mv [lindex $flags $i]
				incr i
			}
		}
		set vis class
		
		#Add related menu entries to the class browser
		if {$menu != ""} {
		}
		
		#Add toolbar buttons related to the class browser
		if {$toolbar != ""} {
			set clsfr $toolbar.clsfr
			pack [frame $clsfr] -side left
			
			#create a combo box for the types of the class
			Combo& $clsfr.name_visib \
				-width 9 \
				-filter "" \
				-contents [list subclass class baseclass] \
				-textvariable $this-visib \
				-selectcommand "$this ComboRefresh_cb"
			#	-postcommand "\[$clsfr.name_visib treew\] see -top 0"
			$clsfr.name_visib selecttext $vis
			pack $clsfr.name_visib -side left -fill x
	
			#Mixer
			button $clsfr.mixer \
				-takefocus 0 \
				-text [get_indep String Mixer] \
				-underline [get_indep Pos Mixer] \
				-pady 0 \
				-command "$this mixer"
			balloon_bind_info $clsfr.mixer [get_indep String MixerINFO]
			pack $clsfr.mixer -side left -fill y -expand n
		}

		#Create a tree for the class members
		ClassBrowserSelector& $memlist \
			-width 60 \
			-height 15 \
			-exportselection 0\
			-fillselection 1\
			-selectmode browse\
			-tabs [list 250 150 150 400] -tabsize 3 \
			-labels [list \
				"[get_indep String Name]" \
				"[get_indep String Class]" \
				"[get_indep String Type]" \
				"[get_indep String Parameters]"] \
			-info_label $mesg_area \
			-sortedinsertion 0 \
			-sortnocase 1 \
			-bestfit 1 \
			-truncate 1 \
			-font $sn_options(def,class-font) \
			-propagate 0
		set memlist_tree [$memlist tree]
		$memlist bind <space> [$memlist bind <Return>]
		$memlist bind <Double-1> "$this handle_doubleclick"
		$memlist bind <ButtonRelease-1> "$this handle_click"
		$memlist bind <3> \
			"focus %W; $this select_post_members_menu %W %X %Y %y; break"
		
		set tree [sn_treetable $clspane \
				-selectmode browse \
				-indent 15 \
				-font $sn_options(def,class-font) \
				-height 6 \
				-borderwidth 0]
		bind $tree <ButtonRelease-1> "$this handle_class_click"

		@@bind $tree <1> "
			set tog \[$tree identify %x %y\]
			set t_m_p \[$tree nearest %y\]
			if {\$tog != \"\" && \$tog != \"text\" && \$t_m_p > -1} {
				watch y $topw
				$this toggle_class \$t_m_p
				watch n $topw
			}
			unset tog; unset t_m_p
			break"
		@@bind $tree <Control-1> "\
			set t_m_p \[%W nearest %y\]
			if {\$t_m_p > -1} {
				watch y $topw
				$this tree_select \[%W get \$t_m_p\]
				watch n $topw
			}
			unset t_m_p
			break"
		@@bind $tree <3> \
			"focus %W;$this select_post_menu %W %X %Y %y; break"

		@@bind $tree <Double-1> \
			"watch y $topw; $this edit_class %W \[%W nearest %y\]; watch n $topw"

		@@bind $tree <space> \
			"watch y $topw; $this edit_class %W; watch n $topw; break"

		@@bind $tree <Return> \
			"watch y $topw; $this edit_class %W; watch n $topw;break"

		pack $tree -fill both -expand y
		pack $memlist -side top -fill both -expand y

		pack $pw -fill both -expand y -side bottom
		
		#call user defined procedure
		catch {sn_rc_classbrowser $this $tree $memlist}
		
		if {$classname != ""} {
			goto "" $classname
		}
		
		@@focus $memlist
		
		#Set title for the topwindow
		SetTitle
	}
	destructor {
		foreach v [@@info globals "$this-*"] {
			catch {uplevel #0 unset $v}
		}
	}
	method config {config} {
	}	
	
	#post menu for members
	method select_post_members_menu {w X Y y} {
		set m .cls_select_post_members_menu
		catch {tk_destroy $m}
		menu $m -tearoff 0
		wm overrideredirect $m 1
		set y [$w nearest $y]
		$w selection clear 0 end
		$w selection set $y
		set txt [Retriever& @@ convert_to_line $memlist]
			if {$txt != ""} {
			set txt [split $txt \t]
			set sym [lindex $txt 0]
			set cls [lindex $txt 1]
			set prm [lindex $txt 3]
			set fil [lindex $txt 4]
			set lin [lindex $txt 5]
			if {$cls == ""} {
				upvar #0 $memlist-class_name name
				set cls $name
			}
			set lbl " [get_indep String Of] '$cls\:\:$sym'"
			set state normal
		} else {
			set sym ""
			set cls ""
			set prm ""
			set fil ""
			set lin ""
			set lbl ""
			set state disabled
		}
		#set vw "[get_indep String View] "
		set vw ""
		
		#Editor
		$m add command \
				-label "$vw[get_indep String MultiEditor]$lbl" \
				-underline [get_indep Pos MultiEditor]\
				-command "watch y $topw; $this handle_doubleclick; watch n $topw" \
				-state $state
						  
		#Class hierarchy
		$m add command \
				-label "$vw[get_indep String MultiClassHierarchy] [get_indep String Of] '$cls'" \
				-underline [get_indep Pos MultiClassHierarchy]\
				-command "watch y $topw; sn_classtree $cls; watch n $topw" \
				-state $state
				
		#Xref
		$m add command \
				-label "$vw[get_indep String MultiXRef]$lbl" \
				-underline [get_indep Pos MultiXRef]\
				-command "sn_xref both [list $cls\:\:$sym] [list ""] [list $fil] [list $lin] [list ""] [list $prm]" \
				-state $state
		
		$m add separator
		
		#add default menu entries
		$memlist tree_post_menu $m
		
		tk_popup $m $X $Y
	}
	
	method select_post_menu {w X Y y} {
		global sn_options
		set m .cls_select_post_menu

		# It has to be destroyed because we might have problems with "tk_popup"!
		catch {tk_destroy $m}

		menu $m -tearoff 0
		wm overrideredirect $m 1

		set y [$w nearest $y]

		set str [tree_get $w $y]

		if {$str == ""} {
			set str "selection"
			set target ""
			set state "disabled"
		} else {
			set target $str
			set state "normal"
			
			#select the entry
			$w selection clear 0 end
			$w selection set $y
		}
		$m add command -label [format [get_indep String SelectOnly] $str]\
			-command "watch y $topw; $this tree_select $target; watch n $topw"\
			-state $state
		$m add command -label [get_indep String SelectAll]\
			-command "watch y $topw; $this tree_select -all; watch n $topw"\
			-accelerator "$sn_options(sys,alt-accelpref)+A"
			
		$m add separator

		tk_popup $m $X $Y
	}

	method handle_doubleclick {} {
		if {$doubleclickcommand != ""} {
			watch y $topw
			#@@eval $doubleclickcommand $memlist.tree
			@@eval $doubleclickcommand [Selection]
			watch n $topw
		}
	}
	
	method handle_class_click {} {
		set sel [$tree curselection]
		if {$sel == ""} {
			return
		}
		set cls [$tree get $sel]
		if {$selectcommand != ""} {
			watch y $topw
			@@eval $selectcommand [list cl $cls "" "" "" "" "" ""]
			watch n $topw
		}
	}
	method handle_click {} {
		if {$selectcommand != ""} {
			watch y $topw
			@@eval $selectcommand [Selection]
			watch n $topw
		}
	}
	
	method Title {{full 1}} {
		global sn_options
		upvar #0 $memlist-class_name name
		set t "[get_indep String ClassBrowTitle]"
		if {$name != ""} {
			set t "$t: $name"
		}
		if {$full} {
			return [sn_title $t]
		} else {
			return $t
		}
	}
	method Icon {} {
		global sn_options
		upvar #0 $memlist-class_name name
		return [sn_view_icon [get_indep String ClassBrowTitle] $name]
	}
	
	method SetTitle {} {
		wm title    [winfo toplevel $this] [Title]
		wm iconname [winfo toplevel $this] [Icon]
	}
	
	#don't change the status of overridden/overloaded
	proc classbrowser_switch {frm fnc} {
		foreach fr {mem flags further} {
			foreach w [winfo children $frm.$fr] {
				if {[winfo class $w] == "Checkbutton" && [string first "further.and" $w] == -1} {
					if {[$w cget -state] != "disabled"} {
						$w $fnc
					}
				}
			}
		}
	}
	method mixer {} {
		global sn_options
		global mixer_status
		set t $this-mixer
		if {[winfo exists $t]} {
			$t raise
			return
		}
		Toplevel& $t
		$t on_close "$t.button_0 invoke"
		$t withdraw
		set title [string trimright [get_indep String Mixer] "."]
		$t title $title
		$t iconname $title
		$t bind_tk <Return> "$t delete"
		sn_motif_buttons $t bottom 0 [get_indep String ok]
		$t.button_0 config -command "$t delete"
		frame $t.chk
		
		#Buttons ALL,NONE,AND
		set chkfr $t.chk.btns
		frame $chkfr
		button $chkfr.all \
				-text [get_indep String All]\
				-under [get_indep Pos All]\
				-command "
					Class& @@ classbrowser_switch $t.chk select
					$this refresh"
		balloon_bind_info $chkfr.all [get_indep String ClassAllINFO]
		button $chkfr.none \
				-text [get_indep String None]\
				-under [get_indep Pos None]\
				-command "
					Class& @@ classbrowser_switch $t.chk deselect
					$this refresh"
		balloon_bind_info $chkfr.none [get_indep String ClassNoneINFO]
		@@grid $chkfr.all - $chkfr.none -padx 10 -pady 10 -sticky w
		pack $chkfr -fill x -expand y -pady 10
		
		#Member flags PUBLIC,PROTECTED,PRIVATE
		set chkfr $t.chk.mem
		frame $chkfr
		global $t-methods
		checkbutton $chkfr.methods \
			-text [get_indep String Methods] \
			-under [get_indep Pos Methods] \
			-variable $t-methods \
			-onvalue "1" \
			-offvalue "0" \
			-command "$this refresh" \
			-state normal
		global $t-instvar
		checkbutton $chkfr.instvar \
			-text [get_indep String ClassVars] \
			-under [get_indep Pos ClassVars] \
			-variable $t-instvar \
			-onvalue "1" \
			-offvalue "0" \
			-command "$this refresh" \
			-state normal
		global $t-friends
		checkbutton $chkfr.friends \
			-text [get_indep String Friends] \
			-under [get_indep Pos Friends] \
			-variable $t-friends \
			-onvalue "1" \
			-offvalue "0" \
			-command "$this refresh" \
			-state normal
		@@grid $chkfr.methods $chkfr.instvar $chkfr.friends -padx 10 -sticky w
		pack $chkfr -fill x -expand y -pady 10
		
		frame $t.chk.line1 -relief sunken -bd 2 -height 2 -width 300
		pack $t.chk.line1 -fill x -expand y
		
		set widgets ""
		
		#Member FLAGS
		set chkfr $t.chk.flags
		frame $chkfr
		foreach p [lrange $mixer_vars 3 5] {
			global $t-$p
			lappend widgets [checkbutton $chkfr.$p \
				-text $p \
				-variable $t-$p \
				-onvalue "1" \
				-offvalue "0" \
				-command "$this refresh" \
				-state normal]
		}
		pack $chkfr -fill x -expand y -pady 10
		frame $t.chk.line2 -relief sunken -bd 2 -height 2 -width 300
		pack $t.chk.line2 -fill x -expand y
		
		#Member Further flags
		set chkfr $t.chk.further
		frame $chkfr
		checkbutton $chkfr.and \
			-text [get_indep String And] \
			-under [get_indep Pos And] \
			-variable $memlist-and \
			-onvalue "1" \
			-offvalue "0" \
			-command "$this refresh" \
			-state normal
		balloon_bind_info $chkfr.and [get_indep String AndINFO]
		foreach p [lrange $mixer_vars 6 10] {
			global $t-$p
			lappend widgets [checkbutton $chkfr.$p \
				-text $p \
				-variable $t-$p \
				-onvalue "1" \
				-offvalue "0" \
				-command "$this refresh" \
				-state normal]
		}
		pack $chkfr -fill x -expand y -pady 10
		frame $t.chk.line3 -relief sunken -bd 2 -height 2 -width 300
		pack $t.chk.line3 -fill x -expand y
		
		#Group flags OVERRIDE,OVERLOADED
		set chkfr $t.chk.groups
		frame $chkfr
		foreach p [lrange $mixer_vars 11 end] {
			global $t-$p
			lappend widgets [checkbutton $chkfr.$p \
				-text $p \
				-variable $t-$p \
				-onvalue "1" \
				-offvalue "0" \
				-command "$this refresh" \
				-state normal]
		}
		pack $chkfr -fill x -expand y -pady 10
		
		@@eval grid [lrange $widgets 0 2] -padx 10 -sticky w
		@@grid $t.chk.further.and -column 1 -padx 10 -sticky w
		@@eval grid [lrange $widgets 3 5] -padx 10 -sticky w
		@@eval grid [lrange $widgets 6 7] -padx 10 -sticky w
		@@eval grid [lrange $widgets 8 end] -padx 10 -sticky w
		
		pack $t.chk -anchor w -padx 10 -pady 10
		
		catch {$t resizable no no}
		focus $t
		$t move_to_mouse
	}

	method tree_get {tr y} {
		set v [$tr get $y]

		set off [string first {<} $v]
		if {$off > 0} {
			set v [string range $v 0 [expr $off - 1]]
		}
		return $v
	}

	method tree_select {target} {
		upvar #0 $memlist-class_viewed class_viewed

		if {[$tree size] <= 0} {
			bell
			return
		}

		set off [string first {<} $target]
		if {$off > 0} {
			set target [string range $target 0 [expr $off - 1]]
		}

		set plus_b enabled_image
		set minus_b undefined_image

		if {$target == "-all"} {
			set base_classes ""

			$tree selection clear 0 end

			$tree itemconfig 0 -image $plus_b
			for {set i 1; set num [$tree size]} {$i < $num} {incr i} {
				set bitm [lindex [$tree itemconfig $i -image] 4]
				if {[string first "unvisited" $bitm] == -1} {
					set cls [tree_get $tree $i]
					lappend base_classes $cls
					@@set class_viewed($cls) 1
					$tree itemconfig $i -image $plus_b
				}
			}
			set base_classes [@@lunique [@@lsort -command sn_compare $base_classes]]
		} else {
			set cls [tree_get $tree 0]
			if {$cls == $target} {
				set base_classes ""
				$tree itemconfig 0 -image $plus_b
			} else {
				set base_classes $target
				$tree itemconfig 0 -image $minus_b
			}
			for {set i 1; set num [$tree size]} {$i < $num} {incr i} {
				set bitm [lindex [$tree itemconfig $i -image] 4]
				if {[string first "unvisited" $bitm] == -1} {
					set cls [tree_get $tree $i]
					if {$cls == $target} {
						@@set class_viewed($cls) 1
						$tree itemconfig $i -image $plus_b
					} else {
						@@set class_viewed($cls) 0
						$tree itemconfig $i -image $minus_b
					}
				}
			}
		}

		$this refresh
	}

	method toggle_class {y} {
		upvar #0 $memlist-class_viewed class_viewed

		set bitm [lindex [$tree itemconfigure $y -image] 4]

		if {[string first "unvisited" $bitm] != -1} {
			return;			# Not defined class.
		}

		set cls [tree_get $tree $y]

		if {[string first "enabled" $bitm] != -1} {
			set bitm undefined_image

			#hide members of this class
			if {$y != 0} {
				@@set class_viewed($cls) 0
				set off [lsearch -exact $base_classes $cls]
				set base_classes [lreplace $base_classes $off $off]
			}
		} else {
			set bitm enabled_image

			#view members of this class
			if {$y != 0} {
				@@set class_viewed($cls) 1
				lappend base_classes $cls
				set base_classes [@@lunique [@@lsort -command sn_compare $base_classes]]
			}
		}
		if {$y == 0} {
			$tree itemconfig $y -image $bitm
		} else {
			#Now, it gets a little complicated. Because in case of multiple
			#inheritance, it can happen that a base class has been included twice
			#and we have to update all the appropiate bitmaps.
			for {set s [$tree size]; set i 0} {$i < $s} {incr i} {
				if {[tree_get $tree $i] == $cls} {
					$tree itemconfig $i -image $bitm
				}
			}
		}

		$this refresh
	}

	method edit_class {w {y ""}} {
		if {$class_doubleclickcommand == ""} {
			return
		}
		if {$y == -1} {
			return
		}
		if {$y == ""} {
			set y [lindex [$w curselection] 0]
			if {$y == ""} {
				return
			}
		}
		set bitm [lindex [$w itemconfig $y -image] 4]
		if {[string first "unvisited" $bitm] != -1} {
			bell
			return;			# Not defined class.
		}
		set cls [$w get $y]

		@@eval $class_doubleclickcommand $cls
	}

	proc convert_sym_to_bit {sym} {
		global SN_Scope_Bits
	
		set bits 0
		foreach s $sym {
			if {$s != ""} {
				set bits [expr $bits | $SN_Scope_Bits($s)]
			}
		}
		return $bits
	}

	method get_class_hier {sub_classes parent} {
		global sn_options sn_sep
		global SN_Scope_Bits

		#build the tree of the class structure
		foreach c $sub_classes {
			set attr $base_class_in($c)
			foreach t [list public protected private] {
				if {[expr $attr & $SN_Scope_Bits($t)]} {
					break
				}
			}
			set cls_inf [paf_db_cl seq -data -col 0 "$c$sn_sep"]
			if {$cls_inf == ""} {
				set bt unvisited_image
			} else {
				set bt enabled_image
			}

			$tree insert end \
				-text ${c}$base_class_templ($c) \
				-parent $parent \
				-image $bt \
				-font $sn_options(def,${t}-font)

			if { [lsearch -exact $base_classes $c] == -1} {
				lappend base_classes $c
			}
			set base_class_in($c) $attr

			#get the list of the parent classes for the current class
			upvar #0 $memlist-sub_classes_of sub_classes_of
			upvar #0 $memlist-base_classes_of base_classes_of
			
			set sub_cls_l ""
			foreach sc [paf_db_in seq -uniq -col {1 5 8} "$c$sn_sep"] {
				set cls [lindex $sc 0]
				
				#verify if class refer itself
				if { $cls == $c } {
					continue
				}
				lappend sub_cls_l $cls
				set base_class_in($cls) [lindex $sc 1]
				set base_class_templ($cls) [lindex $sc 2]
				
				#this class have "c" as sub class
				@@set sub_classes_of($cls) $c
			}
			
			#this class have base classes
			@@set base_classes_of($c) $sub_cls_l
			
			#call this procedure recursively to build all parent classes
			if {$sub_cls_l != ""} {
				get_class_hier [@@lunique [@@lsort -command sn_compare $sub_cls_l]] \
					[expr [$tree size] - 1]
			}
		}
	}

	method get_subclasses {cname file beg_line end_line} {
		global sn_options sn_sep
		set cls_name $cname
		#get the parent classes of the base classes
		set base_classes ""
		catch {unset base_class_in}
		catch {unset base_class_templ}
		set sub_cls ""
		if {[@@info commands paf_db_in] != ""} {
			foreach i [@@lunique [@@lsort -command sn_compare [paf_db_in seq\
				-col [list 1 5 "2 -$beg_line:$end_line" 8]\
				-end $file "$cls_name$sn_sep"]]] {

				set cls [lindex $i 0]

				if { $cls != $cname } {
					set base_class_in($cls) [lindex $i 1]
					set base_class_templ($cls) [lindex $i 3]
					lappend sub_cls $cls
				}
			}
		}

		#add the first class on the top
		catch {$tree remove 0}
		set bitm enabled_image
		$tree insert end -text $cname -image $bitm

		upvar #0 $memlist-sub_classes_of sub_classes_of
		upvar #0 $memlist-base_classes_of base_classes_of
		
		#display the parent classes of the base class as subtree
		@@set base_classes_of($cname) $sub_cls
		foreach c $sub_cls {
			@@set sub_classes_of($c) $cname
		}
		get_class_hier $sub_cls 0

		Tree& @@ resize_widget $tree

		set all_base_classes $base_classes
		
		upvar #0 $memlist-class_viewed class_viewed
		foreach b $base_classes {
			@@set class_viewed($b) 1
		}
	}

	method class_members {cname loc visib type {inherit 0}} {
		global SN_Scope_Bits sn_sep

		foreach p $mixer_vars {
			upvar #0 $this-mixer-$p mv
			if {$mv} {
				set v$p $p
			} else {
				set v$p ""
			}
		}
		if {[string trim "$vpublic $vprotected $vprivate"] == ""} {
			set vpublic public
			set vprotected protected
			set vprivate private
		}

		set file [lindex $loc 0]
		if {[catch {set beg_line [expr int([lindex $loc 1])]}]} {
			set beg_line 1
		}
		if {[catch {set end_line [expr int([lindex $loc 2])]}] || $end_line == 0} {
			set end_line [expr 1024 * 1024]
		}

		#read all base classes and display thim in the tree list
		if {![info exists all_base_classes]} {
			get_subclasses $cname $file $beg_line $end_line
		}

		switch $visib {
		"class" -
		"baseclass" {
				set vis [convert_sym_to_bit "$vpublic $vprotected $vprivate"]
			}
		"subclass" {
				set vis [convert_sym_to_bit "$vpublic $vprotected"]
			}
		default {
				set vis [convert_sym_to_bit "$vpublic $vprotected $vprivate"]
			}
		}
		set db_types ""
		foreach w $type {
			if {[@@info commands paf_db_$w] != ""} {
				lappend db_types $w
			}
		}
		set type $db_types

		#we make filtering in the c procedure by displaying the members
		#by using global variable
		set total ""
		
		#read members for the browsed class
		#we don't need to display the class name of
		#the browsed class
		set bitm [$tree itemcget 0 -image]
		if {[string first "enabled" $bitm] != -1} {
			foreach w $type {
				set app [list "\($w\) "]
				#Line format:
				#0. Member
				#1. Parameter
				#2. Counter
				#3. Type
				#4. Class
				#5. file name
				#6. file position
				#7. flags
				foreach r [paf_db_$w seq -end $file\
					-col [list \
						"1 $app" \
						{7 "| 0000 "} \
						{6 "| \{\} "} \
						3 \
						"2 -$beg_line:$end_line "\
						"5 :0:${vis} " \
						] "$cname$sn_sep"] {
					lappend total $r
				}
			}
		}

		#read members for every base class and add it's contents in a list
		set cou 1
		foreach c $base_classes {
			if {[lsearch -exact $base_classes $c] == -1} {
				continue
			}
			switch $visib {
			"baseclass" {
				set vis [convert_sym_to_bit "$vpublic $vprotected $vprivate"]
			}
			"class" {
				set vis [convert_sym_to_bit "$vpublic $vprotected"]
			}
			"subclass" {
				if {$base_class_in($c) == $SN_Scope_Bits(private)} {
					continue
				}
				set vis [convert_sym_to_bit "$vpublic $vprotected"]
			}
			default {
				set vis [convert_sym_to_bit "$vpublic $vprotected $vprivate"]
				}
			}
			foreach w $type {
				set app [list "\($w\) "]
				set n [format %04d $cou]
				#Line format:
				#0. Member
				#2. Parameter
				#3. Counter
				#1. Type
				#4. Class
				#5. file name
				#6. file position
				#7. flags
				eval lappend total [paf_db_$w seq\
						-col [list \
						"1 $app" \
						"7 \"| $n \"" \
						"6 \"| \"" \
						0 \
						3 \
						2 \
						"5 :0:${vis}"\
						] "$c$sn_sep"]
			}
			incr cou
		}
		return [@@lsort -command sn_compare $total]
	}

	protected last_browsed_class ""

	#refill the combobox and redisplay the class browser
	method RefreshAll {{cls_name ""} {loc ""} {vis ""} {flags ""} {reset 0}} {
		#reinsert the class names into combobox
		fill_combo
		
		#restore flag settings
		if {$flags != ""} {
			set i 0
			foreach p $mixer_vars {
				upvar #0 $this-mixer-$p mv
				set mv [lindex $flags $i]
				incr i
			}
		}
		
		#redisplay the browsed class
		refresh $cls_name $loc $reset
	}
	
	#because the combobox call the function with combo and with
	#the selected text, make a different function
	method ComboRefresh_cb {classtype} {
		refresh
	}
	
	method refresh {{cls_name ""} {loc ""} {reset 0}} {
		upvar #0 $memlist-class_name name
		upvar #0 $this-visib visib
		upvar #0 $memlist-member_filter member_filter
		
		#no class is selected
		if {$cls_name == ""} {
			set cls_name $name
		}
		if {$cls_name == ""} {
			#no class specified
			return 1
		}
		
		#verify if class is availiable and return it's position
		if {$last_browsed_class != $cls_name || $reset} {
			if {$loc == ""} {
				#get the location of the browsed class
				set cnt [read_matched_from_db "" cl -exact $cls_name]
				if {[llength $cnt] > 1} {
					set cnt [lindex $cnt 0]
				}
				if {$cnt == ""} {
					#class not availiable
					return 1
				} else {
					set cnt [split $cnt \t]
				}
				set location [lrange $cnt 4 end]
			} else {
				set location $loc
			}
			catch {unset all_base_classes}
		}
		if {$cls_name != "" && $name != $cls_name} {
			@@set name $cls_name
		}
		
		#can never happen !!!
		if {$location == ""} {
			catch {$tree remove 0}
			$memlist config -contents ""
			set last_browsed_class ""
			set base_classes ""
			set all_base_classes ""
			catch {unset base_class_in}
			catch {unset base_class_templ}
			return 1
		}
		
		#get needed values from member filer (mixer)
		set int ""
		foreach p [lrange $mixer_vars 6 end] {
			upvar #0 $this-mixer-$p mv
			if {$mv} {
				lappend int $p
			}
		}
		set int [convert_sym_to_bit $int]
		if {"$int" == ""} {
			set int 0
		}
		set member_filter $int
		
		#mark last listed class
		set last_browsed_class $cls_name

		#build scopes for class members to be displayed
		set qry ""
		upvar #0 $this-mixer-methods methods
		upvar #0 $this-mixer-instvar instvar
		upvar #0 $this-mixer-friends friends
		if {$methods} {
			lappend qry md
		}
		if {$instvar} {
			lappend qry iv
		}
		if {$friends} {
			lappend qry fr
		}
		if {$qry == ""} {
			set qry [list md iv fr]
		}

		#display members into the member list
		$memlist config\
			-contents [$this class_members $cls_name $location $visib $qry]
			
		SetTitle
		if {$symbols != ""} {
			$symbols selecttext $cls_name
		}
		return 0
	}

	method classname {} {
		upvar #0 $memlist-class_name name
		return $name
	}

	#
	#procedure to call the class browser
	#####################################
	proc Browse_Class {{name ""} {gotosymbol_str ""}} {
		global sn_options
		global tkeWinNumber
	
		set mwin [MultiWindow& @@ find_Reusable]
		if {![winfo exists $mwin]} {
			#create a new multiple window
			incr tkeWinNumber
			set mwin .multiwindow-$tkeWinNumber
			MultiWindow& $mwin \
				-raise classbr
			set active_wdg [$mwin ActiveWidget]
		} else {
			#toggle to the class browser and display the
			#class
			$mwin view classbr
			
			set active_wdg [$mwin ActiveWidget]
		}
		
		#goto method or class
		if {$gotosymbol_str != ""} {
			eval $active_wdg gotosymbol $gotosymbol_str
		#goto only to classes
		} else {
			$active_wdg gotosymbol cl $name
			return
			set ret [$active_wdg goto "" $name]
			if {$ret} {
				#no class with the specified name
				bell
				return
			}
			sn_add_history class \
				$name \
				[sn_make_history_title browse "" $name] \
				sn_classbrowser
		}
	}
	
	method print {} {
		$memlist print_dialog_box
	}
	
	method filter {{all 0}} {
		if {$symbols == ""} {
			return
		}
		upvar #0 $memlist-class_name name
		upvar #0 $symbols_filter-related related
		
		#verify if there are classes availiable
		if {[@@info commands paf_db_cl] != ""} {
			#display only related classes
			if {$related} {
				$symbols contents [@@lunique [@@lsort -command sn_compare [concat $name $base_classes]]]
				set displayed 0
			#display all classes
			} else {
				$symbols contents [paf_db_cl seq -col 0]
				set displayed 1
			}
		} else {
			$symbols contents ""
		}
	}
	
	#this function is called, when the symbols combobox
	#is called
	method postcommand {m} {
		if {! $displayed} {
			filter
			set displayed 1
		}
	}

	#that meens that the notepad is changed to this view
	#View the related toolbar buttons and enable
	#the menu entries for the class browser
	method activate {} {
		upvar #0 $memlist-class_name name
		#display the contents always by activating
		set displayed 0
		
		if {$menu != ""} {
			set mn [string range $menu 0 [expr [string last "." $menu] - 1]]
			$mn entryconfig [get_indep String MultiClass]	-state normal
		}
		if {$toolbar != ""} {
			pack $toolbar.clsfr -side left
		}
		#display current class name
		if {$symbols != ""} {
			$symbols enable
			#delete old contents
			$symbols contents ""
			$symbols selecttext $name
		}
	}
	
	#that meens that the notepad is changed to a different
	#view. Hide the related toolbar buttons and disable
	#the menu entries for the class browser
	method deactivate {} {
		#hide filter window, if availiable
		if {[winfo exists $this-mixer]} {
			$this-mixer delete
		}
		if {$menu != ""} {
			set mn [string range $menu 0 [expr [string last "." $menu] - 1]]
			$mn entryconfig [get_indep String MultiClass]	-state disabled
		}
		if {$toolbar != ""} {
			pack forget $toolbar.clsfr
		}
	}
	
	method gotosymbol {{scope ""} {sym ""} {cls ""} {file ""} {from ""} {type ""} {prm ""} {to ""} {always 1}} {
	
		#goto class
		if {$scope == "cl" || $scope == "" || $cls != "" && $sym == ""} {
			return [goto "" $sym]
		}
		
		#here twice must be availiable (class and member)
		if {$sym == "" || $cls == ""} {
			#something wrong!!
			return 1
		}
		
		#first goto class
		if {[goto "" $cls]} {
			#invalid class name
			return 1
		}
		
		#now we want to select the given member in the list
		if {$scope == "mi"} {
			#all displayed methods are declarations
			set scope "md"
		}
		set str "${sym}($scope)\t\t"
		set idx [[$memlist tree] search -begins $str 0]
		
		if {$idx != ""} {
			$memlist selectnum $idx
		}
		
		return 0
	}
	
	method goto {combo cls} {
		upvar #0 $memlist-class_name name
		
		set cls [string trim $cls]
		if {$cls == ""} {
			return 1
		}
		
		#already selected
		if {$name == $cls} {
			return 0
		}
		
		#dump the current view into the history stack
		$topw history_stack_add_point $this
		
		#verify if the class is availiable
		set res [refresh $cls]
		if {$res} {
			#invalid class name
			return 1
		}
		
		#select the current class in the upper combo box
		if {$symbols != ""} {
			$symbols selecttext $cls
		}
		
		#class displayed successfull
		return 0
	}

	#return selected class or selected member
	method Selection {} {
		global sn_options sn_sep
		
		upvar #0 $memlist-class_name name
		
		#is a member selected?
		set sel [$memlist curselection]
		if {$sel != ""} {
			set txt [Retriever& @@ convert_to_line $memlist]
			set txt [split $txt \t]
			get_key_and_scope [lindex $txt 0] sym scope
			set cls [lindex $txt 1]
			if {$cls == ""} {
				set cls $name
			}
			set typ [lindex $txt 2]
			set prm [lindex $txt 3]
			set fil [lindex $txt 4]
			set lin [lindex $txt 5]
			
			#goto definition or implementation (optional)
			if {$sn_options(def,class-goto-imp) == "imp"} {
				if {$scope == "md"} {
					set scope "mi"
					set ffil ""
					set llin ""
					set ccls $cls
					set mod 1
				} elseif {$scope == "fr"} {
					set scope "fu"
					set ffil ""
					set llin ""
					#friend impl. has no class name
					set ccls ""
					set mod 1
				} else {
					set mod 0
				}
				#get file and position name, if nothing is found
				#about implementation, goto definition
				if {$mod} {
					set pat [string trim "$ccls$sn_sep$sym" " $sn_sep"]
					
					#build a search string, so that a match is looked for
					#on the priority of the options
					lappend looking_list [list $typ $prm $fil]
					lappend looking_list [list $typ $prm ""]
					lappend looking_list [list "" $prm $fil]
					lappend looking_list [list "" $prm ""]
					lappend looking_list [list "" "" ""]
					
					foreach look $looking_list {
						set tt [lindex $look 0]
						set pp [lindex $look 1]
						set ff [lindex $look 2]
						
						#don't make the same fetch again!
						if {[info exists looking_arr($tt,$pp,$ff)]} {
							continue
						}
						set looking_arr($tt,$pp,$ff) 1
						
						#1. Try to find something in the current file
						set cnt [read_matched_from_db \
								"" $scope -exact $pat $tt $pp $ff]
					
						#give up if nothing is found!!
						if {$cnt != ""} {
							set cnt [split [lindex $cnt 0] \t]
							set typ [lindex $cnt 1]
							set prm [lindex $cnt 2]
							set fil [lindex $cnt 4]
							set lin [lindex $cnt 5]
							set cls $ccls
							break
						}
					}
					catch {unset looking_list}
					catch {unset looking_arr}
				}
			}
			
			return [list $scope $sym $cls $fil $lin $typ $prm ""]
		}
		#is a class selected?
		set sel [$tree curselection]
		if {$sel != ""} {
			return [list cl [$tree get $sel] "" "" "" "" "" ""]
		}
		
		#nothing is selected, return the current browsed class
		if {$name != ""} {
			return [list cl $name "" "" "" "" "" ""]
		}
		return ""
	}
	
	method clearselection {} {
		$memlist selection clear 0 end
		$tree selection clear 0 end
	}
	
	method Focus {} {
		focus [$memlist tree]
	}

	#make a title for the Dump position, this is usefull
	#for the views stack (prev/next)
	method DumpTitle {{dump ""}} {
		if {$dump == ""} {
			set dump [Dump]
		}
		set scope [lindex $dump 0]
		if {$scope == "cl"} {
			set cls [lindex $dump 1]
			set mtd ""
		} else {
			set mtd [lindex $dump 1]
			set cls [lindex $dump 2]
		}
		if {$mtd == ""} {
			return "Class $cls"
		} else {
			return "Class ${mtd}($scope) $cls"
		}
	}
	
	method AddHistoryFromDump {dump title} {
		set scope [lindex $dump 0]
		if {$scope == "cl"} {
			set cls [lindex $dump 1]
			set mtd ""
		} else {
			set mtd [lindex $dump 1]
			set cls [lindex $dump 2]
		}
		if {$mtd == ""} {
			set name $cls
		} else {
			set name "${mtd}($scope) $cls"
		}
		sn_add_history class \
				[list "" $dump] \
				[sn_make_history_title browse "" $name] \
				sn_classbrowser
	}
	
	#return the important data to restore this widget
	#in later time again (used by saving the project)
	method Dump {} {
		return [Selection]
	}
	
	#gets the result from the function "Dump" to
	#restore the older state (used by restoring the project)
	method Restore {str} {
		eval $this gotosymbol $str
		#Focus
	}
	
	method Refresh_Display {} {
		global sn_options
		upvar #0 $memlist-class_name cls
		refresh $cls "" 1
	}
	
	method Update_Layout {} {
		global sn_options
	}
	
	method Close {{mode 0}} {
		return 1
	}
	
	method whoami {} {
		return classbr
	}
	method next {} {
		return $next
	}

	protected topw "."
	protected displayed 0
	protected base_classes ""
	protected all_base_classes ""
	protected base_class_in ""
	protected base_class_templ ""
	protected tree ""
	protected memlist ""
	protected ClassTitle ""
	protected mixer_vars "methods instvar friends public private protected static structor inline virtual {pure virtual} overridden overloaded"
    
	protected can
	
	public classname "" {
		if {[winfo exists $memlist]} {
			goto "" $classname
		}
	}
	public location ""
	public flags ""
	public width 80
	public height 30
	public symbols ""
	public symbols_filter ""
	public mesg_area ""
	public menu ""
	public toolbar ""
	public doubleclickcommand ""
	public class_doubleclickcommand ""
	public selectcommand ""
	public class_selectcommand ""
	
	#contains the next widget, when the window is spliten
	#into more than one area
	#Simulate a single chain
	public next ""
}

itcl_class ClassBrowserSelector& {
	inherit Tree&

	constructor {config} {
		upvar #0 $this-overridden overridden
		upvar #0 $this-member_filter member_filter

		@@set overridden 0
		@@set member_filter 0
		
		#create treetable
		Tree&@@constructor
		
		set topw [winfo toplevel $this]
		
		checkbutton $this.filter.overridden \
				-text [get_indep String ClassBrowOverridden] \
				-under [get_indep Pos ClassBrowOverridden] \
				-variable $this-overridden \
				-command "watch y $topw; $this fill; watch n $topw" \
				-relief groove
		pack $this.filter.overridden -side left -before $this.filter.label
	}

	destructor {
		foreach v [@@info globals "$this-*"] {
			catch {uplevel #0 unset $v}
		}
	}
	
	method fill {{bsy 1}} {
		global sn_options
		global $this-sub_classes_of
		global	$this-base_classes_of
		global	$this-class_viewed
		
		@@upvar #0 $this-class_name class_name
		@@upvar #0 $this-overridden overridden
		@@upvar #0 $this-member_filter member_filter
		@@upvar #0 $this-and and

		global $this-sub_classes_of \
			$this-base_classes_of \
			$this-class_viewed

		if {![winfo exists $this]} {
			return
		}

		if {$bsy} {
			$this config -state disabled
		}

		set y [lindex [$tree yview] 0]

		set filter [getfilter]

		#check new contents to view only filtered values
		if {$filter != "*"} {
			if {$nocase} {
				set flt [Tree& @@ nocase_glob_pattern $filter]
			} else {
				set flt $filter
			}
			set show [lmatch -glob 0 $contents $flt]
		} else {
			set show $contents
		}
		
		#display contents in the browse list
		class_browser_insert -delete \
				$tree \
				$show \
				$this-base_classes_of \
				$this-sub_classes_of \
				$this-class_viewed \
				$overridden \
				$member_filter \
				$sn_options(def,public-font) \
				$sn_options(def,protected-font) \
				$sn_options(def,private-font) \
				$class_name \
				$and

		Tree& @@ resize_widget $tree

		if {$bsy} {
			$this config -state normal
		}
	}

	protected topw "."
	public contents {} {
		if {[winfo exists $this]} {
			$this fill 0
		}
	}
}

proc sn_classbrowser {{name ""} {gotosymbol_str ""}} {
	global Switch_Is_Enabled
	incr Switch_Is_Enabled -1
	
	#verify if we want to use the multi window mode?
	Class& @@ Browse_Class $name $gotosymbol_str
	
	incr Switch_Is_Enabled 1
}


