#
# A VERY! early, experimental try at a C/C++ source code browser, done
# mostly in TCL. The keyed list extension from TCLX is used.
#
# Dave Clemans, June 1993
# dave_clemans@mentorg.com
#

#
# Establish a basic runtime environment, get our utilities, etc.
#
set tkb_library [file dirname [info script]]
source $tkb_library/utils.tk
set tkbBrowserCmd "$tkb_library/$tkutVco/browser"

set tkbVersion 0.0

# Stuff for accessing tke, so we can subinvoke it from the browser
set tke_library $tkb_library

#
# Subroutines
#
source $tke_library/tkfs.tk

#
# Be able to subinvoke our editor
#
source $tke_library/tkedit.tk

# End of stuff for accessing tke

#
# A definition of a class
#
proc tkbCdef {name location} {
   global tkbClassList
   if {[info exists tkbClassList($name)] == 0} {
      keylset info LOC $location
      set tkbClassList($name) $info
      return
   }
}

#
# A declaration of a class
#
proc tkbCdecl {name location} {
#   global tkbClassList
#   set found [catch {set info $tkbClassList($name)}]
#   if {$found == 1} {
#      keylset info LOC $location
#      set tkbClassList($name) $info
#      return
#   }
#   if {[keylget info LOC {}] == 0} {
#      keylset info LOC $location
#      set tkbClassList($name) $info
#   }
}

#
# A definition of a subclass
#
proc tkbSubCdef {name parents location} {
   global tkbClassList
   if {[info exists tkbClassList($name)] == 0} {
      keylset info LOC $location PARENTS "$parents"
      set tkbClassList($name) $info
      return
   }
}

#
# A definition of a member function of a class
#
proc tkbMbrFuncDefn {scope name fulldecl location} {
   set i [string first "::" "$name"]
   set class ""
   if {$i != -1} {
      incr i -1
      set class [string range "$name" 0 $i]
      incr i 3
      set name [string range "$name" $i end]
   } else {
      set i [string first ":" "$scope"]
      if {$i != -1} {
         incr i
         set class [string range "$scope" $i end]
      } else {
         puts stderr "Error: tkbMbrFuncDefn: no class name found"
         return
      }
   }
   keylset funcinfo LOC $location FULLDECL "$fulldecl" NAME "$name"
   global tkbFuncDefnList
   global tkbFuncDefnListNO
   if  {[info exists tkbFuncDefnListNO($class::$name)] == 0 &&
      [info exists tkbFuncDefnList($class::$name)] == 0} {
      set tkbFuncDefnListNO($class::$name) 1
      set tkbFuncDefnList($class::$name) $funcinfo
   } else {
      if {[info exists tkbFuncDefnListNO($class::$name)] == 1 &&
         [info exists tkbFuncDefnList($class::$name)] == 1} {
         set finfo $tkbFuncDefnList($class::$name)
         keylget finfo FULLDECL fdecl
         set tkbFuncDefnList($class::$fdecl) $finfo
         unset tkbFuncDefnList($class::$name)
      }
      set tkbFuncDefnList($class::$fulldecl) $funcinfo
   }
}

#
# A declaration of a member function of a class
#
proc tkbMbrFuncDecl {scope name fulldecl location} {
   set i [string first "::" "$name"]
   set class ""
   if {$i != -1} {
      incr i -1
      set class [string range "$name" 0 $i]
      incr i 3
      set name [string range "$name" $i end]
   } else {
      set i [string first ":" "$scope"]
      if {$i != -1} {
         incr i
         set class [string range "$scope" $i end]
      } else {
         puts stderr "Error: tkbMbrFuncDecl: no class name found"
         return
      }
   }
   keylset funcinfo LOC $location FULLDECL "$fulldecl" NAME "$name"
   global tkbFuncDeclList
   global tkbFuncDeclListNO
   if  {[info exists tkbFuncDeclListNO($class::$name)] == 0 &&
      [info exists tkbFuncDeclList($class::$name)] == 0} {
      set tkbFuncDeclListNO($class::$name) 1
      set tkbFuncDeclList($class::$name) $funcinfo
   } else {
      if {[info exists tkbFuncDeclListNO($class::$name)] == 1 &&
         [info exists tkbFuncDeclList($class::$name)] == 1} {
         set finfo $tkbFuncDeclList($class::$name)
         keylget finfo FULLDECL fdecl
         set tkbFuncDeclList($class::$fdecl) $finfo
         unset tkbFuncDeclList($class::$name)
      }
      set tkbFuncDeclList($class::$fulldecl) $funcinfo
   }
}

#
# A definition of a function
#
proc tkbFuncDefn {scope name fulldecl location} {
   set scopeName ""
   if {"$scope" == "global"} {
      set scopeName "@GLOBAL"
   } else {
      set index [string first ":" "$location"]
      incr index -1
      set scopeName [string range "$location" 0 $index]
   }
   global tkbOtherList
   if {[info exists tkbOtherList($scopeName)] == 0} {
      set tkbOtherList($scopeName) 1
   }
   keylset funcinfo LOC $location FULLDECL "$fulldecl"
   global tkbFuncDefnList
   global tkbFuncDefnListNO
   if  {[info exists tkbFuncDefnListNO($scopeName::$name)] == 0 &&
      [info exists tkbFuncDefnList($scopeName::$name)] == 0} {
      set tkbFuncDefnListNO($scopeName::$name) 1
      set tkbFuncDefnList($scopeName::$name) $funcinfo
   } else {
      if {[info exists tkbFuncDefnListNO($scopeName::$name)] == 1 &&
         [info exists tkbFuncDefnList($scopeName::$name)] == 1} {
         set finfo $tkbFuncDefnList($scopeName::$name)
         keylget finfo FULLDECL fdecl
         set tkbFuncDefnList($scopeName::$fdecl) $finfo
         unset tkbFuncDefnList($scopeName::$name)
      }
      set tkbFuncDefnList($scopeName::$fulldecl) $funcinfo
   }
}

#
# A declaration of a function
#
proc tkbFuncDecl {scope name fulldecl location} {
   set scopeName ""
   if {"$scope" == "global"} {
      set scopeName "@GLOBAL"
   } else {
      set index [string first ":" "$location"]
      incr index -1
      set scopeName [string range "$location" 0 $index]
   }
   global tkbOtherList
   if {[info exists tkbOtherList($scopeName)] == 0} {
      set tkbOtherList($scopeName) 1
   }
   keylset funcinfo LOC $location FULLDECL "$fulldecl"
   global tkbFuncDeclList
   global tkbFuncDeclListNO
   if  {[info exists tkbFuncDeclListNO($scopeName::$name)] == 0 &&
      [info exists tkbFuncDeclList($scopeName::$name)] == 0} {
      set tkbFuncDeclListNO($scopeName::$name) 1
      set tkbFuncDeclList($scopeName::$name) $funcinfo
   } else {
      if {[info exists tkbFuncDeclListNO($scopeName::$name)] == 1 &&
         [info exists tkbFuncDeclList($scopeName::$name)] == 1} {
         set finfo $tkbFuncDeclList($scopeName::$name)
         keylget finfo FULLDECL fdecl
         set tkbFuncDeclList($scopeName::$fdecl) $finfo
         unset tkbFuncDeclList($scopeName::$name)
      }
      set tkbFuncDeclList($scopeName::$fulldecl) $funcinfo
   }
}

#
# A definition of an object
#
proc tkbObjDefn {scope parent name fulldecl location} {
   set scopeName ""
   if {"$scope" == "global"} {
      set scopeName "@GLOBAL"
   } else {
      if {"$scope" == "function" || "$scope" == "call"} {
         set scopeName "$parent"
         set index [string first ":" "$scopeName"]
         if {$index != -1} {
            incr index -1
            set scopeName [string range "$scopeName" 0 $index]
         }
      } else {
         set index [string first ":" "$location"]
         incr index -1
         set scopeName [string range "$location" 0 $index]
      }
   }
   global tkbOtherList
   if {[info exists tkbOtherList($scopeName)] == 0} {
      set tkbOtherList($scopeName) 1
   }
   keylset varinfo LOC $location FULLDECL "$fulldecl"
   global tkbVarDefnList
   if {[info exists tkbVarDefnList($scopeName::$name)] == 0} {
      set tkbVarDefnList($scopeName::$name) $varinfo
   }
}

#
# A declaration of an object
#
proc tkbObjDecl {scope parent name fulldecl location} {
   set scopeName ""
   if {"$scope" == "global"} {
      set scopeName "@GLOBAL"
   } else {
      if {"$scope" == "function" || "$scope" == "call"} {
         set scopeName "$parent"
         set index [string first ":" "$scopeName"]
         if {$index != -1} {
            incr index -1
            set scopeName [string range "$scopeName" 0 $index]
         }
      } else {
         set index [string first ":" "$location"]
         incr index -1
         set scopeName [string range "$location" 0 $index]
      }
   }
   global tkbOtherList
   if {[info exists tkbOtherList($scopeName)] == 0} {
      set tkbOtherList($scopeName) 1
   }
   keylset varinfo LOC $location FULLDECL "$fulldecl"
   global tkbVarDeclList
   if {[info exists tkbVarDeclList($scopeName::$name)] == 0} {
      set tkbVarDeclList($scopeName::$name) $varinfo
   }
}

#
# A definition of a class member object
#
proc tkbMbrObjDefn {scope parent name fulldecl location} {
   set i [string first "::" "$name"]
   set class ""
   if {$i != -1} {
      incr i -1
      set class [string range "$name" 0 $i]
      incr i 3
      set name [string range "$name" $i end]
   } else {
      set class $parent
   }
   keylset varinfo LOC $location FULLDECL "$fulldecl"
   global tkbVarDefnList
   if {[info exists tkbVarDefnList($class::$name)] == 0} {
      set tkbVarDefnList($class::$name) $varinfo
   }
}

#
# A declaration of a class member object
#
proc tkbMbrObjDecl {scope parent name fulldecl location} {
   set i [string first "::" "$name"]
   set class ""
   if {$i != -1} {
      incr i -1
      set class [string range "$name" 0 $i]
      incr i 3
      set name [string range "$name" $i end]
   } else {
      set class $parent
   }
   keylset varinfo LOC $location FULLDECL "$fulldecl"
   global tkbVarDeclList
   if {[info exists tkbVarDeclList($class::$name)] == 0} {
      set tkbVarDeclList($class::$name) $varinfo
   }
}

#
# A file has been saved, and any information about it in the database
# might have changed. Remove any old information, and put in new information.
#
proc tkeSaveUserHook {file} {
   global tkbBrowserWindow
   if {[winfo exists $tkbBrowserWindow] == 0} {
      return
   }
   set cfile ""
   case "$file" in {
      *.\[cChH\] {set cfile "$file"}
      *.cc {set cfile "$file"}
      *.hh {set cfile "$file"}
      *.cxx {set cfile "$file"}
      *.hxx {set cfile "$file"}
   }
   if {"$cfile" == ""} {
      return
   }

   # Get rid of old information; unfortunately this is a bit complicated
   global tkbClassList
   if {[info exists tkbClassList]} {
      set sid [array startsearch tkbClassList]
      set entries {}
      while {[array anymore tkbClassList $sid]} {
         set entry [array nextelement tkbClassList $sid]
         set info $tkbClassList($entry)
         keylget info LOC location
         if {[string first "$cfile:" "$location"] == 0} {
            lappend entries $entry
         }
      }
      array donesearch tkbClassList $sid
      set len [llength $entries]
      for {set i 0} {$i < $len} {incr i} {
         set entry [lindex $entries $i]
         unset tkbClassList($entry)
      }
   }
   global tkbOtherList
   if {[info exists tkbOtherList]} {
      set sid [array startsearch tkbOtherList]
      set entries {}
      while {[array anymore tkbOtherList $sid]} {
         set entry [array nextelement tkbOtherList $sid]
         if {"$cfile" == "$entry"} {
            lappend entries $cfile
         }
      }
      array donesearch tkbOtherList $sid
      set len [llength $entries]
      for {set i 0} {$i < $len} {incr i} {
         set entry [lindex $entries $i]
         unset tkbOtherList($entry)
      }
   }
   global tkbFuncDefnList
   global tkbFuncDefnListNO
   if {[info exists tkbFuncDefnList]} {
      set sid [array startsearch tkbFuncDefnList]
      set entries {}
      while {[array anymore tkbFuncDefnList $sid]} {
         set entry [array nextelement tkbFuncDefnList $sid]
         set info $tkbFuncDefnList($entry)
         keylget info LOC location
         if {[string first "$cfile:" "$location"] == 0} {
            lappend entries $entry
            keylget info NAME name
            if {[info exists tkbFuncDefnListNO($name)]} {
               unset tkbFuncDefnListNO($name)
            }
         }
      }
      array donesearch tkbFuncDefnList $sid
      set len [llength $entries]
      for {set i 0} {$i < $len} {incr i} {
         set entry [lindex $entries $i]
         unset tkbFuncDefnList($entry)
      }
   }
   global tkbFuncDeclList
   global tkbFuncDeclListNO
   if {[info exists tkbFuncDeclList]} {
      set sid [array startsearch tkbFuncDeclList]
      set entries {}
      while {[array anymore tkbFuncDeclList $sid]} {
         set entry [array nextelement tkbFuncDeclList $sid]
         set info $tkbFuncDeclList($entry)
         keylget info LOC location
         if {[string first "$cfile:" "$location"] == 0} {
            lappend entries $entry
            keylget info NAME name
            if {[info exists tkbFuncDeclListNO($name)]} {
               unset tkbFuncDeclListNO($name)
            }
         }
      }
      array donesearch tkbFuncDeclList $sid
      set len [llength $entries]
      for {set i 0} {$i < $len} {incr i} {
         set entry [lindex $entries $i]
         unset tkbFuncDeclList($entry)
      }
   }
   global tkbVarDefnList
   if {[info exists tkbVarDefnList]} {
      set sid [array startsearch tkbVarDefnList]
      set entries {}
      while {[array anymore tkbVarDefnList $sid]} {
         set entry [array nextelement tkbVarDefnList $sid]
         set info $tkbVarDefnList($entry)
         keylget info LOC location
         if {[string first "$cfile:" "$location"] == 0} {
            lappend entries $entry
         }
      }
      array donesearch tkbVarDefnList $sid
      set len [llength $entries]
      for {set i 0} {$i < $len} {incr i} {
         set entry [lindex $entries $i]
         unset tkbVarDefnList($entry)
      }
   }
   global tkbVarDeclList
   if {[info exists tkbVarDeclList]} {
      set sid [array startsearch tkbOtherList]
      set entries {}
      while {[array anymore tkbOtherList $sid]} {
         set entry [array nextelement tkbOtherList $sid]
         set info $tkbOtherList($entry)
         keylget info LOC location
         if {[string first "$cfile:" "$location"] == 0} {
            lappend entries $entry
         }
      }
      array donesearch tkbOtherList $sid
      set len [llength $entries]
      for {set i 0} {$i < $len} {incr i} {
         set entry [lindex $entries $i]
         unset tkbOtherList($entry)
      }
   }

   # and finally go get the new information
   global tkbBrowserCmd
   set cmd "|$tkbBrowserCmd $cfile"
   set fd [open $cmd r]
   while {[set line [gets $fd]] != ""} {
      eval $line
   }
   close $fd

   # Update our display
   global tkbShowGlobalsOrClasses
   if {$tkbShowGlobalsOrClasses == 0} {
      tkbGetOthers $tkbBrowserWindow
   } else {
      tkbGetClasses $tkbBrowserWindow
   }
   global tkbCurrentScope
   if {"$tkbCurrentScope" != ""} {
      tkbDisplayContents $tkbCurrentScope $tkbBrowserWindow
   }
}

#
# Get information about the files in this directory
#
proc tkbGetDirectoryInfo {dir} {
   global tkbBrowserCmd
   set args [glob -nocomplain "$dir/*.\[cChH\]" "$dir/*.cxx" "$dir/*.hxx" "$dir/*.cc" "$dir/*.hh"]
   set cmd "|$tkbBrowserCmd $args"
   set fd [open $cmd r]
   while {[set line [gets $fd]] != ""} {
      eval $line
   }
   close $fd
}

#
# Get requested names from a definition or declaration list
#
proc tkbGetNames {name src fnd} {
   upvar $src nlist
   upvar $fnd result
   set namelen [string length "$name::"]
   if {[info exists nlist]} {
      set sid [array startsearch nlist]
      while {[array anymore nlist $sid]} {
         set entry [array nextelement nlist $sid]
         set index [string first "$name::" "$entry"]
         if {$index != -1} {
            while {$index != -1} {
               if {$index == 1 && [string index "$entry" 0] == "~"} {
                  set i [expr $index+$namelen]
                  if {[string first "$name::" [string range "$entry" $i end]] == -1} {
                     break
                  }
                  set entry [string range "$entry" $i end]
                  continue
               }
               if {$index == 0} {
                  set entry [string range "$entry" $namelen end]
               } else {
                  set ef [expr $index-1]
                  incr index $namelen
                  set es [string range "$entry" 0 $ef]
                  set el [string range "$entry" $index end]
                  set entry "$es$el"
               }
               set index [string first "$name::" "$entry"]
            }
            set c [string index "$entry" 0]
            if {"$c" == "~"} {
               if {[string first "~$name" "$entry"] != 0} {
                  set entry [string range "$entry" 1 end]
               }
            }
            if {[lsearch $result $entry] == -1} {
               lappend result $entry
            }
         }
      }
      array donesearch nlist $sid
   }
}

#
# Put the contents of a class into a listbox window
#
proc tkbGetClassContents {name window} {
   global tkbCurrentScope
   global tkbClassList
   set tkbCurrentScope $name
   $window delete 0 end
   set total {}
   global tkbShowFuncsOrVars

   if {$tkbShowFuncsOrVars == 0 || $tkbShowFuncsOrVars == 2} {
      global tkbFuncDefnList
      tkbGetNames $name tkbFuncDefnList total
   }

   if {$tkbShowFuncsOrVars == 0 || $tkbShowFuncsOrVars == 2} {
      global tkbFuncDeclList
      tkbGetNames $name tkbFuncDeclList total
   }

   if {$tkbShowFuncsOrVars == 1 || $tkbShowFuncsOrVars == 2} {
      global tkbVarDefnList
      tkbGetNames $name tkbVarDefnList total
   }

   if {$tkbShowFuncsOrVars == 1 || $tkbShowFuncsOrVars == 2} {
      global tkbVarDeclList
      tkbGetNames $name tkbVarDeclList total
   }

   set total [lsort $total]
   set len [llength $total]
   for {set i 0} {$i < $len} {incr i} {
      $window insert end [lindex $total $i]
   }
}

#
# Try to display a selected class;
#  ignores scopes that aren't classes
#
proc tkbDisplaySelectedClass {name} {
   global tkutWindowRows
   global tkutWindowCols
   global tkbClassList
   if {[info exists tkbClassList($name)]} {
      set info $tkbClassList($name)
      if {[keylget info LOC location]} {
         set location [split "$location" ":"]
         set ew [tkeEditFile dummy [lindex $location 0]]
         wm geometry $ew ${tkutWindowCols}x${tkutWindowRows}
         $ew.tk yview -pickplace [lindex $location 1].0
      }
   }
}

#
# Try to display a selected item;
#  return non-zero if successful
#
proc tkbDisplaySelected {name scope src} {
   global tkutWindowRows
   global tkutWindowCols
   upvar $src nlist
   set namelen [string length "$scope::"]
   if {[info exists nlist]} {
      set sid [array startsearch nlist]
      while {[array anymore nlist $sid]} {
         set entry [array nextelement nlist $sid]
         set fentry "$entry"
         set index [string first "$scope::" "$entry"]
         if {$index != -1} {
            while {$index != -1} {
               if {$index == 1 && [string index "$entry" 0] == "~"} {
                  set i [expr $index+$namelen]
                  if {[string first "$name::" [string range "$entry" $i end]] == -1} {
                     break
                  }
                  set entry [string range "$entry" $i end]
                  continue
               }
               if {$index == 0} {
                  set entry [string range "$entry" $namelen end]
               } else {
                  set ef [expr $index-1]
                  incr index $namelen
                  set es [string range "$entry" 0 $ef]
                  set el [string range "$entry" $index end]
                  set entry "$es$el"
               }
               set index [string first "$scope::" "$entry"]
            }
            set c [string index "$entry" 0]
            if {"$c" == "~"} {
               if {[string first "~$scope" "$entry"] != 0} {
                  set entry [string range "$entry" 1 end]
               }
            }
            if {"$name" == "$entry"} {
               set info $nlist($fentry)
               if {[keylget info LOC location]} {
                  set location [split "$location" ":"]
                  set ew [tkeEditFile dummy [lindex $location 0]]
                  wm geometry $ew ${tkutWindowCols}x${tkutWindowRows}
                  $ew.tk yview -pickplace [lindex $location 1].0
                  return 1
               }
            }
         }
      }
      array donesearch nlist $sid
   }
   return 0
}

#
# Find information about a selected item and try to display it
#
proc tkbFindAndDisplaySelected {name scope} {
   global tkbFuncDefnList
   global tkbFuncDeclList
   global tkbVarDefnList
   global tkbVarDeclList
   global tkbShowDeclOrDefn
   global tkbBrowserWindow

   if {$tkbShowDeclOrDefn == 1} {
      if {[tkbDisplaySelected $name $scope tkbFuncDefnList]} {
         return
      }
      if {[tkbDisplaySelected $name $scope tkbVarDefnList]} {
         return
      }
   } else {
      if {[tkbDisplaySelected $name $scope tkbFuncDeclList]} {
         return
      }
      if {[tkbDisplaySelected $name $scope tkbFuncDefnList]} {
         return
      }
      if {[tkbDisplaySelected $name $scope tkbVarDeclList]} {
         return
      }
      if {[tkbDisplaySelected $name $scope tkbVarDefnList]} {
         return
      }
   }
   $tkbBrowserWindow.file.oframe.msg configure -text "Unable to find $name in scope $scope..."
   after 3000 $tkbBrowserWindow.file.oframe.msg configure -text "Contents of $scope..."
}

#
# Put info about the names in a selected scope into a listbox window
#
proc tkbDisplayContents {scope window} {
   $window.file.oframe.msg configure -text "Getting information about $scope..."
   update idletasks
   tkbGetClassContents $scope $window.file.oframe.list
   $window.file.oframe.msg configure -text "Contents of $scope..."
}

#
# Put our others list into a listbox window
#
proc tkbGetOthers {window} {
   global tkbOtherList
   if {[info exists tkbOtherList]} {
      $window.file.cframe.list delete 0 end
      set others [array names tkbOtherList]
      set others [lsort $others]
      set len [llength $others]
      for {set i 0} {$i < $len} {incr i} {
         $window.file.cframe.list insert end [lindex $others $i]
      }
   }
}

#
# Put our class list into a listbox window
#
proc tkbGetClasses {window} {
   global tkbClassList
   if {[info exists tkbClassList]} {
      $window.file.cframe.list delete 0 end
      set classes [array names tkbClassList]
      set classes [lsort $classes]
      set len [llength $classes]
      for {set i 0} {$i < $len} {incr i} {
         $window.file.cframe.list insert end [lindex $classes $i]
      }
   }
}

wm withdraw .

set w .tkb0
toplevel $w
wm title $w "C++/C Code Browser @ $tkutLocalSystem"
wm protocol $w WM_DELETE_WINDOW "destroy $w;tkutDelMainWindow"

frame $w.file -bd 10
pack append $w $w.file {left filly}

frame $w.file.cframe
pack append $w.file $w.file.cframe {top fillx}

frame $w.file.cframe.buttons
scrollbar $w.file.cframe.yscroll -relief sunken \
   -command "$w.file.cframe.list yview"
listbox $w.file.cframe.list -geometry 40x20 -relief sunken \
   -yscroll "$w.file.cframe.yscroll set"

set tkbShowGlobalsOrClasses 1
radiobutton $w.file.cframe.buttons.globals -text "Show Others" -width 16 \
   -anchor w -relief raised -variable tkbShowGlobalsOrClasses -value 0 \
   -command "tkbGetOthers $w"
radiobutton $w.file.cframe.buttons.classes -text "Show Classes" -width 16 \
   -anchor w -relief raised -variable tkbShowGlobalsOrClasses -value 1 \
   -command "tkbGetClasses $w"
pack append $w.file.cframe.buttons \
   $w.file.cframe.buttons.globals {top pady 4} \
   $w.file.cframe.buttons.classes {top pady 4}

message $w.file.cframe.msg -justify left -anchor nw -aspect 3000 -text "" \
   -relief raised

pack append $w.file.cframe \
   $w.file.cframe.msg {top fillx} \
   $w.file.cframe.buttons {right filly} \
   $w.file.cframe.yscroll {right filly} \
   $w.file.cframe.list {left expand fill}

frame $w.file.oframe
pack append $w.file $w.file.oframe {top fillx}

frame $w.file.oframe.buttons
frame $w.file.oframe.buttons.b1 -relief raised
frame $w.file.oframe.buttons.b2 -relief raised
frame $w.file.oframe.buttons.b3
scrollbar $w.file.oframe.yscroll -relief sunken \
   -command "$w.file.oframe.list yview"
listbox $w.file.oframe.list -geometry 40x20 -relief sunken \
   -yscroll "$w.file.oframe.yscroll set"

set tkbShowDeclOrDefn 1
radiobutton $w.file.oframe.buttons.b1.defn -text "Definition" -width 16 \
   -anchor w -relief raised -variable tkbShowDeclOrDefn -value 1
radiobutton $w.file.oframe.buttons.b1.decl -text "Declaration" -width 16 \
   -anchor w -relief raised -variable tkbShowDeclOrDefn -value 0
pack append $w.file.oframe.buttons.b1 \
   $w.file.oframe.buttons.b1.decl {top pady 8} \
   $w.file.oframe.buttons.b1.defn {top pady 8}

button $w.file.oframe.buttons.b3.quit -text Quit -relief raised -padx 10 \
   -command "destroy $w;tkutDelMainWindow"
pack append $w.file.oframe.buttons.b3 \
   $w.file.oframe.buttons.b3.quit {bottom pady 4}

set tkbCurrentScope ""
set tkbShowFuncsOrVars 2
radiobutton $w.file.oframe.buttons.b2.func -text "Show Functions" -width 16 \
   -anchor w -relief raised -variable tkbShowFuncsOrVars -value 0 \
   -command {if {$tkbCurrentScope != ""} {tkbDisplayContents $tkbCurrentScope $w}}
radiobutton $w.file.oframe.buttons.b2.var -text "Show Variables" -width 16 \
   -anchor w -relief raised -variable tkbShowFuncsOrVars -value 1 \
   -command {if {$tkbCurrentScope != ""} {tkbDisplayContents $tkbCurrentScope $w}}
radiobutton $w.file.oframe.buttons.b2.all -text "Show Both" -width 16 \
   -anchor w -relief raised -variable tkbShowFuncsOrVars -value 2 \
   -command {if {$tkbCurrentScope != ""} {tkbDisplayContents $tkbCurrentScope $w}}
pack append $w.file.oframe.buttons.b2 \
   $w.file.oframe.buttons.b2.func {top pady 8} \
   $w.file.oframe.buttons.b2.var {top pady 8} \
   $w.file.oframe.buttons.b2.all {top pady 8}

pack append $w.file.oframe.buttons \
   $w.file.oframe.buttons.b1 {top fillx pady 10} \
   $w.file.oframe.buttons.b2 {top fillx} \
   $w.file.oframe.buttons.b3 {bottom expand filly}

message $w.file.oframe.msg -justify left -anchor nw -aspect 3000 -text "" \
   -relief raised

pack append $w.file.oframe \
   $w.file.oframe.msg {top fillx} \
   $w.file.oframe.buttons {right filly} \
   $w.file.oframe.yscroll {right filly} \
   $w.file.oframe.list {left expand fill}

set win1 $w.file.cframe.list
set win2 $w.file.oframe.list

update idletasks

set tkbNumDirs 0
for {set ai 0} {$ai < $argc} {incr ai} {
   incr tkbNumDirs
   set dir [lindex $argv $ai]
   $w.file.cframe.msg configure -text "Reading information from directory $dir..."
   update idletasks
   tkbGetDirectoryInfo $dir
}
if {$tkbNumDirs == 0} {
   $w.file.cframe.msg configure -text "Reading information from current directory..."
   update idletasks
   tkbGetDirectoryInfo .
}
$w.file.cframe.msg configure -text "tkb C++/C Browser; Version $tkbVersion"

tkbGetClasses $w

    tk_listboxSingleSelect $win1 $win2

    bind $win1 <Button-1> {
        # puts stderr "button 1 release"
        %W select from [%W nearest %y]
        tkbDisplayContents [%W get [%W nearest %y]] $w
    }

    bind $win1 <Double-Button-1> {
        # puts stderr "button 1 release"
        %W select from [%W nearest %y]
        tkbDisplayContents [%W get [%W nearest %y]] $w
        tkbDisplaySelectedClass $tkbCurrentScope
    }

    bind $win2 <Button-1> {
        tkbFindAndDisplaySelected [%W get [%W nearest %y]] $tkbCurrentScope
    }

    bind $win2 <Double-Button-1> {
        tkbFindAndDisplaySelected [%W get [%W nearest %y]] $tkbCurrentScope
    }

set tkbBrowserWindow $w
tkutNewMainWindow

tkutWaitForNoWindows
exit 0
