blob: 54e515f41b809420a8d8cc729761769b712a4696 [file] [log] [blame]
# Register display window for Insight.
# Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004, 2007 Red Hat, Inc.
#
# Written by Keith Seitz (keiths@redhat.com)
# and Martin Hunt (hunt@redhat.com)
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License (GPL) as published by
# the Free Software Foundation; either version 2 of the License, or (at
# your option) any later version.
#
# This program 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.
# TODO
#
# Must fix:
# o Edit menus -- weirdo interaction with tkTable. Seems okay on windows.
# Needs more testing on unix (popup edit menu item).
#
# Want really badly:
# o Multiple selections
# o Multiple displays
# o Better resizing
# o Register groups (gdb and user-defined)
# o format register values before inserting into table?
# (Instead of displaying "0x0", we should use "0x00000000" on
# machines with 32-bit regs, "0x0000000000000000" on machines
# with 64-bit regs, etc. Maybe user-defined formats, i.e.,
# "0x0000 0000 0000 0000 0000 0000"?)
# ------------------------------------------------------------------
# NAME: RegWin::constructor
# DESCRIPTION: Create a new register window
#
# ARGUMENTS: None
# RETURNS: Nothing
# ------------------------------------------------------------------
itcl::body RegWin::constructor {args} {
eval itk_initialize $args
gdbtk_busy
window_name "Registers" "Regs"
_build_win
_layout_table
# Clear gdb's changed list
catch {gdb_reginfo changed}
gdbtk_idle
}
# ------------------------------------------------------------------
# NAME: RegWin::destructor
# DESCRIPTION: Destroys the register window
#
# ARGUMENTS: None
# RETURNS: Nothing
# ------------------------------------------------------------------
itcl::body RegWin::destructor {} {
debug
}
# ------------------------------------------------------------------
# NAME: RegWin::_load_prefs
# DESCRIPTION: Load register preferences
#
# ARGUMENTS: None
# RETURNS: Nothing
# ------------------------------------------------------------------
itcl::body RegWin::_load_prefs {} {
debug
# Find out largest register name length.
set _max_label_width 0; # for reg labels
set _reg_display_list {}
set _register(hidden) {}
set regs [gdb_reginfo group $_group]
foreach r [gdb_reginfo name -numbers $regs] {
set nm [lindex $r 0]
set rn [lindex $r 1]
set size [string length $nm]
if {$size > $_max_label_width} {
set _max_label_width $size
}
# Set type from prefs or default to first in list of types
set _types($rn) [gdb_reginfo type $rn]
set tp [pref getd gdb/reg/${nm}-type]
set _type($rn,name) ""
if {$tp != ""} {
foreach t $_types($rn) {
if {[lindex $t 0] == $tp} {
set _type($rn,name) $tp
set _type($rn,addr) [lindex $t 1]
set _type($rn,code) [lindex $t 2]
break
}
}
}
if {$_type($rn,name) == ""} {
# either not set or couldn't find it in list of types
set _type($rn,name) [lindex [lindex $_types($rn) 0] 0]
set _type($rn,addr) [lindex [lindex $_types($rn) 0] 1]
set _type($rn,code) [lindex [lindex $_types($rn) 0] 2]
}
# Check preferences for format
set _format($rn) [pref getd gdb/reg/${nm}-format]
if {$_format($rn) == ""} {
# no preference set. Set it to hex or float
if {$_type($rn,code) == "int"} {
set _format($rn) "x"
} else {
set _format($rn) "f"
}
pref setd gdb/reg/${nm}-format $_format($rn)
}
gdb_reginfo format $rn $_type($rn,addr) $_format($rn)
# Check if the user prefers not to show this register
if {[pref getd gdb/reg/$nm] == "no"} {
set _cell($rn) hidden
lappend _register(hidden) $rn
} else {
lappend _reg_display_list $rn
}
# assume editable, for now
set _editable($rn) 1
}
incr _max_label_width 2; # padding
}
#
# Table layout/display methods
#
# ------------------------------------------------------------------
# NAME: private method RegWin::_build_win
# DESCRIPTION: Builds the register window from widgets
#
# ARGUMENTS: None
# RETURNS: Nothing
#
# NOTES: This method should only be called once for
# each RegWin. To change the layout of the table
# in the window, use RegWin::_layout_table.
# ------------------------------------------------------------------
itcl::body RegWin::_build_win {} {
# Create scrollbars and table
itk_component add vscroll {
scrollbar $itk_interior.vs -orient vertical
}
itk_component add hscroll {
scrollbar $itk_interior.hs -orient horizontal
}
itk_component add table {
::table $itk_interior.tbl -variable [scope _data] \
-browsecmd [code $this _select_cell %S] -font global/fixed \
-colstretch unset -rowstretch unset -selectmode single \
-resizeborders none -multiline false -colwidth 18 \
-autoclear 0 -bg $::Colors(bg) \
-padx 5 -xscrollcommand [code $itk_component(hscroll) set] \
-yscrollcommand [code $itk_component(vscroll) set]
} {
keep -foreground
keep -insertbackground
keep -highlightcolor
keep -highlightbackground
}
bind $itk_component(table) <Up> \
[format "%s; break" [code $this _move up]]
bind $itk_component(table) <Down> \
[format "%s; break" [code $this _move down]]
bind $itk_component(table) <Left> \
[format "%s; break" [code $this _move left]]
bind $itk_component(table) <Right> \
[format "%s; break" [code $this _move right]]
bind $itk_component(table) <3> \
[code $this _but3 %x %y %X %Y]
bind $itk_component(table) <Double-1> break
bind $itk_component(table) <1> \
[code $this _edit %x %y]
bind $itk_component(table) <Return> \
[format "%s; break" [code $this _accept_edit]]
bind $itk_component(table) <KP_Enter> \
[format "%s; break" [code $this _accept_edit]]
bind $itk_component(table) <Escape> \
[code $this _unedit]
$itk_component(hscroll) configure -command [code $itk_component(table) xview]
$itk_component(vscroll) configure -command [code $itk_component(table) yview]
# Create/configure tags for various display styles
# normal - the "normal" display style
# highlight - changed registers are highlighted
# sel - the selection fg/bg should conform to standard
# header - used on the register name cells and empty cells
# edit - used on a cell being edited
$itk_component(table) tag configure normal \
-state disabled -bg $::Colors(textbg) -fg $::Colors(textfg)
$itk_component(table) tag configure sel -bg $::Colors(sbg) -fg $::Colors(sfg)
$itk_component(table) tag configure highlight -bg $::Colors(change) -fg black
$itk_component(table) tag raise highlight
$itk_component(table) tag configure header \
-anchor w -state disabled -relief raised
$itk_component(table) tag configure disabled \
-state disabled
$itk_component(table) tag raise active
$itk_component(table) tag configure edit \
-state normal
$itk_component(table) tag raise edit
$itk_component(table) tag raise sel
itk_component add frame {
frame $itk_interior.m
}
iwidgets::optionmenu $itk_component(frame).opt -labeltext "Group:" \
-labelpos w -command [code $this _select_group]
eval $itk_component(frame).opt insert end [gdb_reginfo grouplist]
$itk_component(frame).opt select "all"
pack $itk_component(frame).opt -anchor nw
grid $itk_component(frame) -row 0 -columnspan 2 -sticky news
grid $itk_component(table) -row 1 -column 0 -sticky news
grid $itk_component(vscroll) -row 1 -column 1 -sticky ns
grid $itk_component(hscroll) -row 2 -column 0 -sticky ew
grid columnconfigure $itk_interior 0 -weight 1
grid rowconfigure $itk_interior 0 -weight 0
grid rowconfigure $itk_interior 1 -weight 1
# Add popup menu - we populate it in the event handler
itk_component add popup {
menu $itk_interior.pop -tearoff 0
} {}
}
# ------------------------------------------------------------------
# NAME: private method RegWin::_layout_table
# DESCRIPTION: Configures and lays out the table
#
# ARGUMENTS: None
# RETURNS: Nothing
#
# NOTES: Uses preferences to determine if/how a register
# is displayed
# ------------------------------------------------------------------
itcl::body RegWin::_layout_table {} {
debug
if {[info exists _cell]} {
unset _cell
unset _register
}
# Clear any column spans
foreach span [$itk_component(table) spans] {
$itk_component(table) spans $span 0,0
}
_load_prefs
# Fill data array with register names.
#
# The table is indexed by (row,col). All odd columns will contain
# register values and all even columns will contain the labels.
#
set x 0
set y 0
# get register list
set regs [gdb_reginfo name -numbers $_reg_display_list]
# Set table dimensions
set num [llength $regs]
set _rows [pref get gdb/reg/rows]
set _cols [expr $num / $_rows]
if {[expr $num % $_rows] != 0} { incr _cols }
set _cols [expr 2 * $_cols]
$itk_component(table) configure -cols $_cols -rows $_rows
# get values
if {[catch {gdb_reginfo value $_reg_display_list} values]} {
dbug W "values=$values"
set values ""
}
set i 0
# now build table
foreach r $regs {
set name [lindex $r 0]
set rn [lindex $r 1]
set _cell($rn) "$y,[expr {$x+1}]"
set _register($_cell($rn)) $rn
set _data($y,$x) $name
set _data($_cell($rn)) [lindex $values $i]
incr i
# Go to next row/column
incr y
if {$y == $_rows} {
set _col_size([expr {$x+1}]) 0
# Size the column
if {$::gdb_running} {
_size_column [expr {$x+1}] 1
}
$itk_component(table) width $x $_max_label_width
$itk_component(table) tag col header $x
$itk_component(table) tag col normal [expr {$x+1}]
set y 0
incr x 2
}
}
# Mark empty cells
while {$y != $_rows && $x != $_cols} {
set _data($y,$x) ""
set _data($y,[expr {$x+1}]) ""
$itk_component(table) spans $y,$x 0,1
$itk_component(table) tag cell header $y,$x
set _col_size([expr {$x+1}]) 0
incr y
if {$y == $_rows} {
# Size the column
if {$::gdb_running} {
_size_column [expr {$x+1}] 1
}
$itk_component(table) width $x $_max_label_width
$itk_component(table) tag col header $x
$itk_component(table) tag col normal [expr {$x+1}]
set y 0
incr x 2
}
}
}
# ------------------------------------------------------------------
# NAME: private method RegWin::_size_cell_column
# DESCRIPTION: Resize the column for a given cell.
#
# ARGUMENTS:
# cell - the cell whose column is to be resized
# down - whether the resizing should size the column
# down or just up.
# RETURNS: Nothing
#
# NOTES: See _size_column for the reasoning for the "down"
# option.
# ------------------------------------------------------------------
itcl::body RegWin::_size_cell_column {cell down} {
set col [string trim [lindex [split $cell ,] 1] ()]
_size_column $col $down
}
# ------------------------------------------------------------------
# NAME: private method RegWin::_size_column
# DESCRIPTION: Resize the given column
#
# ARGUMENTS:
# col - the column to be resized
# down - whether the resizing should size the column
# RETURNS: down or just up.
#
# NOTES: The down option allows column sizes to change down
# as well as up. For most cases, this is what is
# wanted. However, when the user is stepping, it is
# really annoying to see the column sizes changing.
# It's bad enough we must size up, but going down
# is just too much. Consequently, when updating the
# contents of the table, we specify that the columns
# should not downsize. This helps mitigate the
# annoyance.
# ------------------------------------------------------------------
itcl::body RegWin::_size_column {col down} {
set max 0
foreach cell [array names _data *,$col] {
set len [string length $_data($cell)]
if {$len > $max} { set max $len }
}
if {($down && $max != $_col_size($col))
|| (!$down && $max > $_col_size($col))} {
set _col_size($col) $max
$itk_component(table) width $col [expr {$max + 2}]
# Force the table to update itself
after idle event generate $itk_component(table) <Configure> \
-width [winfo width $itk_component(table)]
}
}
# ------------------------------------------------------------------
# NAME: private method RegWin::reconfig
# DESCRIPTION: Reconfigures register window when a preference
# changes.
#
# ARGUMENTS: None
# RETURNS: Nothing
#
# ------------------------------------------------------------------
itcl::body RegWin::reconfig {} {
$itk_component(table) tag configure normal \
-state disabled -bg $::Colors(textbg) -fg $::Colors(textfg)
}
#
# Table event handlers and related methods
#
# ------------------------------------------------------------------
# NAME: private method RegWin::_accept_edit
# DESCRIPTION: Change a register's value
#
# ARGUMENTS: None
# RETURNS: Nothing
#
# NOTES: Event handler for <Enter> and <KP_Enter>
# in table
# ------------------------------------------------------------------
itcl::body RegWin::_accept_edit {} {
debug
set cell [$itk_component(table) tag cell edit]
if {[llength $cell] == 1 && [info exists _register($cell)]} {
# Select the same cell again. This forces the table
# to keep this value. Otherwise, we'll never see it...
_select_cell $cell
set rn $_register($cell)
set n [gdb_reginfo name $rn]
if {[llength $_types($rn)] > 1} {
append n ".$_type($rn,name)"
}
set v [string trim [$itk_component(table) curvalue] \ \r\n]
debug "n=$n v=$v"
if {$v != ""} {
if {[catch {gdb_cmd "set \$${n}=$v"} result]} {
tk_messageBox -icon error -type ok -message $result \
-title "Error in Expression" -parent $_top
}
}
# Always update the register, even for error conditions. This
# will ensure that the cell's old value is restored to the table.
_update_register $_register($cell)
_size_cell_column $cell 1
}
_unedit
}
# ------------------------------------------------------------------
# NAME: private method RegWin::_add_to_watch
# DESCRIPTION: Add a register to the watch window
#
# ARGUMENTS: rn - the register number to add to the WatchWin
# RETURNS: Nothing
#
# NOTES: Only works with one WatchWin...
# ------------------------------------------------------------------
itcl::body RegWin::_add_to_watch {rn} {
[ManagedWin::open WatchWin] add "\$[gdb_reginfo name $rn]"
}
# ------------------------------------------------------------------
# NAME: private method RegWin::_add_to_watch
# DESCRIPTION: Add a register to the watch window
#
# ARGUMENTS: rn - the register number to add to the WatchWin
# RETURNS: Nothing
#
# NOTES: Only works with one WatchWin...
# ------------------------------------------------------------------
itcl::body RegWin::_open_memory {rn} {
ManagedWin::open MemWin -force -addr_exp $_data($_cell($rn))
}
# ------------------------------------------------------------------
# NAME: private method RegWin::_but3
# DESCRIPTION: Configure the popup menu before posting it
#
# ARGUMENTS: x - x-coordinate of buttonpress
# y - y-coordinate
# X - x-root coordinate
# Y - y-root coordinate
# RETURNS: Nothing
# ------------------------------------------------------------------
itcl::body RegWin::_but3 {x y X Y} {
# Only post the menu when we're not executing the inferior,
# the inferior is in a runnable state, and we're not in a disabled
# cell.
if {!$_running && $::gdb_running} {
# Select the register
set cell [_select_cell [$itk_component(table) index @$x,$y]]
if {[info exists _register($cell)]} {
set rn $_register($cell)
set name [gdb_reginfo name $rn]
$itk_component(popup) delete 0 end
$itk_component(popup) add command -label $name -state disabled
$itk_component(popup) add separator
if {[llength $_types($rn)] > 1} {
foreach t $_types($rn) {
$itk_component(popup) add radio -label [lindex $t 0] \
-variable [scope _type($rn,addr)] \
-value [lindex $t 1] \
-command [code $this _change_format $rn [lindex $t 0]]
}
$itk_component(popup) add separator
}
$itk_component(popup) add radio -label "Hex" \
-variable [scope _format($rn)] -value x \
-command [code $this _change_format $rn]
if {$_type($rn,code) == "int"} {
$itk_component(popup) add radio -label "Decimal" \
-variable [scope _format($rn)] -value d \
-command [code $this _change_format $rn]
$itk_component(popup) add radio -label "Unsigned" \
-variable [scope _format($rn)] -value u \
-command [code $this _change_format $rn]
} elseif {$_type($rn,code) == "float"} {
$itk_component(popup) add radio -label "Floating Point" \
-variable [scope _format($rn)] -value f \
-command [code $this _change_format $rn]
}
$itk_component(popup) add separator
if {$_editable($rn)} {
set state normal
} else {
set state disabled
}
if {$_type($rn,code) == "int"} {
$itk_component(popup) add command \
-label "Open Memory Window" -command [code $this _open_memory $rn]
}
$itk_component(popup) add command \
-label "Add to Watch" -command [code $this _add_to_watch $rn]
$itk_component(popup) add separator
$itk_component(popup) add command \
-label "Remove from Display" \
-command [code $this _delete_from_display $rn]
if {[llength $_register(hidden)] != 0} {
$itk_component(popup) add command -label "Display all Registers" \
-command [code $this _display_all]
}
# Help
$itk_component(popup) add separator
$itk_component(popup) add command \
-label "Help" -command {open_help register.html}
# Close
$itk_component(popup) add separator
$itk_component(popup) add command -label "Close" \
-underline 0 -command [code delete object $this]
tk_popup $itk_component(popup) $X $Y
}
}
}
# ------------------------------------------------------------------
# NAME: private method RegWin::_delete_from_display
# DESCRIPTION: Remove a register from the display
#
# ARGUMENTS: rn - the register number to remove
# RETURNS: Nothing
# ------------------------------------------------------------------
itcl::body RegWin::_delete_from_display {rn} {
# Mark the cell as hidden
set index [lsearch $_reg_display_list $rn]
if {$index != -1} {
pref setd gdb/reg/[gdb_reginfo name $rn] no
set _reg_display_list [lreplace $_reg_display_list $index $index]
# Relayout table
_layout_table
}
}
# ------------------------------------------------------------------
# NAME: private method RegWin::_display_all
# DESCRIPTION: Display all registers in the window
#
# ARGUMENTS: None
# RETURNS: Nothing
# ------------------------------------------------------------------
itcl::body RegWin::_display_all {} {
# Unhide all hidden registers
foreach r $_register(hidden) {
pref setd gdb/reg/[gdb_reginfo name $r] {}
}
# Note which register is active and restore it
if {[catch {$itk_component(table) index active} cell]} {
set active {}
} else {
set active $_register($cell)
}
_layout_table
if {$active != ""} {
$itk_component(table) activate $_cell($active)
}
}
# ------------------------------------------------------------------
# NAME: private method RegWin::_edit
# DESCRIPTION: Enables a cell for editing
#
# ARGUMENTS:
# x - the x coordinate of the button press
# y - the y coordinate of the button press
# RETURNS: Nothing
#
# NOTES: Event handler for <1> in table.
#
# ------------------------------------------------------------------
itcl::body RegWin::_edit {x y} {
_select_cell [$itk_component(table) index @$x,$y]
}
# ------------------------------------------------------------------
# NAME: private method _move
# DESCRIPTION: Handle arrow key events in table
#
# ARGUMENTS: direction - "up", "down", "left", "right"
# RETURNS: Nothing
#
# NOTES: Event handler for <Up>, <Down>, <Left>, <Right>
# in table. This is needed because the table
# has some rather strange bindings for moving
# the insertion cursor when editing a cell.
# This method will move to the next cell when
# we're not editing, or it will move the icursor
# if we are editing.
# ------------------------------------------------------------------
itcl::body RegWin::_move {direction} {
debug $direction
# If there is no active cell, the table will call error
if {[catch {$itk_component(table) index active row} row]} {
return
}
if {[$itk_component(table) tag cell edit] != ""} {
# Editing
switch $direction {
up {
# Go to beginning
$itk_component(table) icursor 0
}
down {
# Go to end
$itk_component(table) icursor end
}
left {
# Go left one character
set ic [$itk_component(table) icursor]
if {$ic > 0} {
$itk_component(table) icursor [expr {$ic - 1}]
}
}
right {
# Go right one character
set ic [$itk_component(table) icursor]
if {$ic < [$itk_component(table) icursor end] } {
$itk_component(table) icursor [expr {$ic + 1}]
}
}
}
} else {
# Not editing
set col [$itk_component(table) index active col]
switch $direction {
up {
incr row -1
if {$row < 0} {
# go to bottom
set row $_rows
}
}
down {
incr row 1
if {$row == $_rows} {
# go to top
set row 0
}
}
left {
incr col -2
if {$col < 0} {
# go to right
set col [expr {$_cols -1}]
}
}
right {
incr col 2
if {$col > $_cols} {
# go to left
set col 0
}
}
}
# clear the selection
# FIXME: multiple selections?
$itk_component(table) selection clear all
_select_cell $row,$col
}
}
# ------------------------------------------------------------------
# NAME: private method RegWin::_select_cell
# DESCRIPTION: Selects a given cell in the table
#
# ARGUMENTS:
# cell - the table index to select
# RETURNS: The actual cell selected
#
# NOTES: Adjusts the cell index so that it always
# selects the value cell for a register
# ------------------------------------------------------------------
itcl::body RegWin::_select_cell {cell} {
# Abort an edit
_unedit
# check if going to label. If so, highlight next
set row [lindex [split $cell ,] 0]
set col [lindex [split $cell ,] 1]
if {[expr {$col % 2}] == 0} {
# going onto a label
incr col 1
}
set cell "$row,$col"
# Make the selected cell the active one
$itk_component(table) activate $row,$col
$itk_component(table) see active
# Select this cell and its label
# FIXME: multiple selections?
$itk_component(table) selection clear all
$itk_component(table) selection set $cell $row,[expr {$col-1}]
# Now mark the cell as being edited.
if {$::gdb_running && [info exists _register($cell)]} {
$itk_component(table) tag cell edit $cell
}
focus $itk_component(table)
return $cell
}
# ------------------------------------------------------------------
# NAME: private method RegWin::_unedit
# DESCRIPTION: Cancels an edit
#
# ARGUMENTS: None
# RETURNS: Nothing
# ------------------------------------------------------------------
itcl::body RegWin::_unedit {} {
# clear the tag
set cell [$itk_component(table) tag cell edit]
if {$cell != ""} {
$itk_component(table) selection clear all
$itk_component(table) tag cell normal $cell
focus $itk_component(table)
}
}
#
# Register operations
#
# ------------------------------------------------------------------
# NAME: private method RegWin::_get_value
# DESCRIPTION: Get the value of a register
#
# ARGUMENTS: rn - the register number whose value should be
# fetched
# RETURNS: The register's value or ""
#
# NOTES:
# ------------------------------------------------------------------
itcl::body RegWin::_get_value {rn} {
if {[catch {gdb_reginfo value $rn} value]} {
dbug W "\"gdb_reginfo value $rn\" returned $value"
set value ""
} else {
set value [string trim $value \ ]
}
return $value
}
# ------------------------------------------------------------------
# NAME: private method RegWin::_change_format
# DESCRIPTION: Change the display format of the register
#
# ARGUMENTS: rn - the register number to change
# newtype - type name (optional if just format changed)
#
# RETURNS: Nothing
#
# NOTES:
# ------------------------------------------------------------------
itcl::body RegWin::_change_format {rn {newtype {}}} {
set name [gdb_reginfo name $rn]
if {$newtype != ""} {
set _type($rn,name) $newtype
pref setd gdb/reg/${name}-type $newtype
}
gdb_reginfo format $rn $_type($rn,addr) $_format($rn)
# Set the new format in prefs.
pref setd gdb/reg/${name}-format $_format($rn)
_update_register $rn
_size_cell_column $_cell($rn) 1
# Show the active cell in case it's moved as a result
# of resizing the columns.
$itk_component(table) see active
}
# ------------------------------------------------------------------
# NAME: private_method RegWin::_update_register
# DESCRIPTION: Updates the value of a register and refreshes
# the table
#
# ARGUMENTS:
# rn - the register number to update
# RETURNS: Nothing
# ------------------------------------------------------------------
itcl::body RegWin::_update_register {rn} {
set _data($_cell($rn)) [_get_value $rn]
}
# ------------------------------------------------------------------
# NAME: private_method RegWin::_select_group
# DESCRIPTION: Changes the register group. Callback
#
# ARGUMENTS:
#
# RETURNS: Nothing
# ------------------------------------------------------------------
itcl::body RegWin::_select_group {} {
set gr [$itk_component(frame).opt get]
debug $gr
if {$gr == ""} {
return
}
# Change anything on the old change list back to normal
foreach r $_change_list {
if {[info exists _cell($r)] && $_cell($r) != "hidden"} {
$itk_component(table) tag cell normal $_cell($r)
}
}
set _group $gr
_layout_table
# highlight changed registers if they still exist in the new group
foreach r $_change_list {
if {[info exists _cell($r)] && $_cell($r) != "hidden" && $_data($_cell($r)) != ""} {
$itk_component(table) tag cell highlight $_cell($r)
}
}
# Clear gdb's change list
catch {gdb_reginfo changed}
}
#
# Gdb Events
#
# ------------------------------------------------------------------
# NAME: public method RegWin::arch_changed
# DESCRIPTION: ArchChangedEvent handler
#
# ARGUMENTS: event - the ArchChangedEvent (not used)
# RETURNS: Nothing
# ------------------------------------------------------------------
itcl::body RegWin::arch_changed {event} {
# Update internal register caches
gdb_reg_arch_changed
# Relayout the table
_layout_table
# Clear gdb's change list
catch {gdb_reginfo changed}
}
# ------------------------------------------------------------------
# NAME: public method RegWin::busy
# DESCRIPTION: BusyEvent handler
#
# ARGUMENTS: event - the BusyEvent (not used)
# RETURNS: Nothing
# ------------------------------------------------------------------
itcl::body RegWin::busy {event} {
# Abort any edit. Need to check if the table is constructed,
# since we call gdbtk_busy when we're created...
if {[info exists itk_component(table)]} {
_unedit
}
# Set fencepost
set _running 1
# Set cursor
$_top configure -cursor watch
}
# ------------------------------------------------------------------
# NAME: public method RegWin::idle
# DESCRIPTION: IdleEvent handler
#
# ARGUMENTS: event - the IdleEvent (not used)
# RETURNS: Nothing
# ------------------------------------------------------------------
itcl::body RegWin::idle {event} {
# Clear fencepost
set _running 0
# Reset cursor
$_top configure -cursor {}
}
# ------------------------------------------------------------------
# NAME: public method RegWin::set_variable
# DESCRIPTION: SetVariableEvent handler
#
# ARGUMENTS: None
# RETURNS: Nothing
# ------------------------------------------------------------------
itcl::body RegWin::set_variable {event} {
switch [$event get variable] {
disassembly-flavor {
_layout_table
}
}
}
# ------------------------------------------------------------------
# NAME: public method RegWin::update
# DESCRIPTION: UpdateEvent handler
#
# ARGUMENTS: event - the UpdateEvent (not used)
# RETURNS: Nothing
# ------------------------------------------------------------------
itcl::body RegWin::update {event} {
debug
# Change anything on the old change list back to normal
foreach r $_change_list {
if {[info exists _cell($r)] && $_cell($r) != "hidden"} {
$itk_component(table) tag cell normal $_cell($r)
}
}
# Now update and highlight the newly changed values
set _change_list {}
if {![catch {gdb_reginfo changed $_reg_display_list} changed]} {
set _change_list $changed
}
# Problem: if the register was invalid (i.e, we were not running),
# its old value will probably be "0x0". Now if we run and its real
# value is "0x0", then it will appear as a blank in the register
# window. Safegaurd against that here by adding any such register
# which is not already in the change list.
foreach r $_reg_display_list {
if {$_data($_cell($r)) == "" && [lsearch $_change_list $r] == -1} {
lappend _change_list $r
}
}
# Tag the changed cells and resize the columns
set cols {}
foreach r $_change_list {
_update_register $r
if {$_data($_cell($r)) != ""} {
$itk_component(table) tag cell highlight $_cell($r)
}
set col [lindex [split $_cell($r) ,] 1]
if {[lsearch $cols $col] == -1} {
lappend cols $col
}
}
foreach col $cols {
set col [string trim $col ()]
_size_column $col 0
}
debug "END REGISTER UPDATE CALLBACK"
}