#
# StackWin
# ----------------------------------------------------------------------
# Implements stack window for gdb
#
#   PUBLIC ATTRIBUTES:
#
#
#   METHODS:
#
#     reconfig ....... called when preferences change
#
#
#   X11 OPTION DATABASE ATTRIBUTES
#
#
# ----------------------------------------------------------------------
#   AUTHOR:  Martin M. Hunt	hunt@cygnus.com     
#            Cygnus Solutions   
#


itcl_class StackWin {
  # ------------------------------------------------------------------
  #  CONSTRUCTOR - create new stack window
  # ------------------------------------------------------------------
  constructor {config} {
    #
    #  Create a window with the same name as this object
    #
    set class [$this info class]
    @@rename $this $this-tmp-
    @@frame $this -class $class 
    @@rename $this $this-win-
    @@rename $this-tmp- $this
    add_hook gdb_idle_hook "$this update"
    build_win
  }


  # ------------------------------------------------------------------
  #  METHOD:  build_win - build the main register window
  # ------------------------------------------------------------------
  method build_win {} {
    tixScrolledListBox $this.s -scrollbar auto
    set lb [$this.s subwidget listbox]
    $lb configure -selectmode single -selectbackground gold
    update
    balloon register $lb "Click on a frame to select the current frame"

    # bind mouse button 1 to change the stack frame
    bind $lb <ButtonPress-1> "$this change_frame %y"
    bind $lb <ButtonRelease-1> break

    pack $this.s -side left -expand yes -fill both
  }


  # ------------------------------------------------------------------
  #  METHOD:  update - update widget when PC changes
  # ------------------------------------------------------------------
  method update {args} {
    set lb [$this.s subwidget listbox]
    if [catch {set trace [gdb_cmd bt]}] {
      # no stack
      set trace "NO STACK"
    }
    
    $lb delete 0 end
    eval {$lb insert end} [split $trace \n]

    # this next section checks to see if the source
    # window is looking at some location other than the 
    # bottom of the stack.  If so, highlight the stack frame
    set loc [gdb_loc]
    if {[lindex $loc 4] != [lindex $loc 5]} {
      set line 0
      for {set i 0} { $line != {}} {incr i} {
	# must do a split before a lindex because
	# the line may not be a valid list and
	# tcl 8 requires a valid list for input to lindex
	set line [split [$lb get $i]]
	set pc [lindex $line 2]
	if {[lindex $loc 4] == $pc} {
	  $lb selection set $i
	}
      }
    }
  }


  # ------------------------------------------------------------------
  #  METHOD:  change_frame - change the current frame
  # ------------------------------------------------------------------
  method change_frame {y} {
    set lb [$this.s subwidget listbox]
    set linenum [$lb nearest $y]
    catch {gdb_cmd "frame $linenum"}
    catch {run_hooks gdb_idle_hook}
  }

  # ------------------------------------------------------------------
  #  DESTRUCTOR - destroy window containing widget
  # ------------------------------------------------------------------
  destructor {
    remove_hook gdb_idle_hook "$this update"
    set top [winfo toplevel $this]
    destroy $this
    destroy $top
  }

  # ------------------------------------------------------------------
  #  METHOD:  config - used to change public attributes
  # ------------------------------------------------------------------
  method config {config} {}
    
  # ------------------------------------------------------------------
  #  METHOD:  reconfig - used when preferences change
  # ------------------------------------------------------------------
  method reconfig {} {
    destroy $this.s
    build_win
  }
  
  #
  #  PROTECTED DATA
  #
}

