diff options
Diffstat (limited to 'gdb/gdbtk/library/regwin.itb')
-rw-r--r-- | gdb/gdbtk/library/regwin.itb | 585 |
1 files changed, 585 insertions, 0 deletions
diff --git a/gdb/gdbtk/library/regwin.itb b/gdb/gdbtk/library/regwin.itb new file mode 100644 index 00000000000..2515498c06e --- /dev/null +++ b/gdb/gdbtk/library/regwin.itb @@ -0,0 +1,585 @@ +# Register display window for GDBtk. +# Copyright 1998, 1999 Cygnus Solutions +# +# 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. + + +# ------------------------------------------------------------------ +# CONSTRUCTOR - create new register window +# ------------------------------------------------------------------ +body RegWin::constructor {args} { + global tixOption + debug "RegWin::constructor" + wm withdraw [winfo toplevel $itk_interior] + gdbtk_busy + + set NormalForeground $tixOption(fg) + set HighlightForeground [pref get gdb/reg/highlight_fg] + + if {[pref getd gdb/reg/menu] != ""} { + set mbar 0 + } + + init_reg_display_vars 1 + build_win + eval itk_initialize $args + + gdbtk_idle + add_hook gdb_update_hook "$this update" + add_hook gdb_busy_hook [list $this busy] + add_hook gdb_idle_hook [list $this idle] + if {[get_disassembly_flavor] != ""} { + add_hook gdb_set_hook [code $this handle_set_hook] + } +} + +# ------------------------------------------------------------------ +# DESTRUCTOR - destroy window containing widget +# ------------------------------------------------------------------ +body RegWin::destructor {} { + debug "RegWin::destructor" + remove_hook gdb_update_hook "$this update" + remove_hook gdb_busy_hook [list $this busy] + remove_hook gdb_idle_hook [list $this idle] + if {[get_disassembly_flavor] != ""} { + remove_hook gdb_set_hook [code $this handle_set_hook] + } +} + + + +# ------------------------------------------------------------------ +# METHOD: build_win - build the main register window +# ------------------------------------------------------------------ +body RegWin::build_win {} { + global reg_display tixOption tcl_platform + + set dim [dimensions] + set nRows [lindex $dim 0] + set nCols [lindex $dim 1] + if {$tcl_platform(platform) == "windows"} { + tixScrolledWindow $itk_interior.scrolled -scrollbar both -sizebox 1 + } else { + tixScrolledWindow $itk_interior.scrolled -scrollbar auto + } + set ScrolledWin [$itk_interior.scrolled subwidget window] + # Create labels + set row 0 + set col 0 + + set regMaxLen 0 + foreach r [gdb_regnames] { + set l [string length $r] + if {$l > $regMaxLen} { + set regMaxLen $l + } + } + + set vmax 0 + foreach r $reg_display_list { + if {[catch {gdb_fetch_registers $reg_display($r,format) $r} values($r)]} { + set values($r) "" + } else { + set values($r) [string trim $values($r) \ ] + } + set l [string length $values($r)] + if {$l > $vmax} { + set vmax $l + } + } + + foreach r $reg_display_list { + if {$row == $nRows} { + grid columnconfigure $ScrolledWin $col -weight 1 + set row 0 + incr col + } + + frame $ScrolledWin.$r -takefocus 1 + bind $ScrolledWin.$r <Up> "$this reg_select_up" + bind $ScrolledWin.$r <Down> "$this reg_select_down" + bind $ScrolledWin.$r <Tab> "$this reg_select_down" + bind $ScrolledWin.$r <Left> "$this reg_select_left" + bind $ScrolledWin.$r <Right> "$this reg_select_right" + if {![pref get gdb/mode]} { + bind $ScrolledWin.$r <Return> "$this edit $r" + } + + label $ScrolledWin.$r.lbl -text [fixLength $reg_display($r,name) $regMaxLen left] \ + -relief solid -bd 1 -font src-font + label $ScrolledWin.$r.val -anchor e -text [fixLength $values($r) $vmax right] \ + -relief ridge -bd 1 -font src-font -bg $tixOption(input1_bg) + + grid $ScrolledWin.$r.lbl $ScrolledWin.$r.val -sticky nsew + grid columnconfigure $ScrolledWin.$r 1 -weight 1 + grid $ScrolledWin.$r -colum $col -row $row -sticky nsew + # grid rowconfigure $ScrolledWin $row -weight 1 + bind $ScrolledWin.$r.val <1> "$this reg_select $r" + bind $ScrolledWin.$r.lbl <1> "$this reg_select $r" + bind $ScrolledWin.$r.val <3> "$this but3 $r %X %Y" + bind $ScrolledWin.$r.lbl <3> "$this but3 $r %X %Y" + if {![pref get gdb/mode]} { + bind $ScrolledWin.$r.lbl <Double-1> "$this edit $r" + bind $ScrolledWin.$r.val <Double-1> "$this edit $r" + } + incr row + } + grid columnconfigure $ScrolledWin $col -weight 1 + + + if { $mbar } { + menu $itk_interior.m -tearoff 0 + [winfo toplevel $itk_interior] configure -menu $itk_interior.m + $itk_interior.m add cascade -menu $itk_interior.m.reg -label "Register" -underline 0 + set m [menu $itk_interior.m.reg] + if {![pref get gdb/mode]} { + $m add command -label "Edit" -underline 0 -state disabled + } + $m add cascade -menu $itk_interior.m.reg.format -label "Format" -underline 0 + set f [menu $itk_interior.m.reg.format] + $f add radio -label "Hex" -value x -underline 0 -state disabled \ + -command "$this update" + $f add radio -label "Decimal" -value d -underline 0 -state disabled \ + -command "$this update" + $f add radio -label "Natural" -value {} -underline 0 -state disabled \ + -command "$this update" + $f add radio -label "Binary" -value t -underline 0 -state disabled \ + -command "$this update" + $f add radio -label "Octal" -value o -underline 0 -state disabled \ + -command "$this update" + $f add radio -label "Raw" -value r -underline 0 -state disabled \ + -command "$this update" + $m add command -label "Remove from Display" -underline 0 -state disabled + $m add separator + $m add command -label "Display All Registers" -underline 0 -state disabled \ + -command "$this display_all" + } + + set Menu [menu $ScrolledWin.pop -tearoff 0] + set disabled_fg [$Menu cget -fg] + $Menu configure -disabledforeground $disabled_fg + + # Clear gdb's changed list + catch {gdb_changed_register_list} + + pack $itk_interior.scrolled -anchor nw -fill both -expand yes + + window_name "Registers" "Regs" +} + +# ------------------------------------------------------------------------------ +# NAME: init_reg_display_vars +# DESC: Initialize the list of registers displayed. +# args - not used +# RETURNS: +# NOTES: +# ------------------------------------------------------------------------------ +body RegWin::init_reg_display_vars {args} { + global reg_display max_regs + set reg_display_list {} + set regnames [gdb_regnames] + set i 1 + set rn 0 + foreach r $regnames { + set reg_display($rn,name) $r + set format [pref getd gdb/reg/$r-format] + if {$format == ""} { set format x } + set reg_display($rn,format) $format + if {$args != "" && [pref getd gdb/reg/$r] == "no"} { + set reg_display($rn,line) 0 + } else { + set reg_display($rn,line) $i + lappend reg_display_list $rn + incr i + } + incr rn + } + set num_regs [expr {$i - 1}] + set max_regs $rn + set reg_names_dirty 0 +} + +body RegWin::handle_set_hook {var value} { + switch $var { + disassembly-flavor { + disassembly_changed + } + } +} + +body RegWin::disassembly_changed {} { + set reg_names_dirty 1 +} +# ------------------------------------------------------------------------------ +# NAME: save_reg_display_vars +# DESC: save the list of displayed registers to the preferences file. +# ------------------------------------------------------------------------------ +body RegWin::save_reg_display_vars {} { + global reg_display max_regs + set rn 0 + while {$rn < $max_regs} { + set name $reg_display($rn,name) + if {$reg_display($rn,line) == 0} { + pref setd gdb/reg/$name no + } else { + pref setd gdb/reg/$name {} + } + if {$reg_display($rn,format) != "x"} { + pref setd gdb/reg/$name-format $reg_display($rn,format) + } else { + pref setd gdb/reg/$name-format {} + } + incr rn + } + pref_save "" +} + +# ------------------------------------------------------------------ +# PUBLIC METHOD: reg_select_up +# ------------------------------------------------------------------ +body RegWin::reg_select_up { } { + if { $selected == -1 || $Running} { + return + } + set current_index [lsearch -exact $reg_display_list $selected] + set new_reg [lindex $reg_display_list [expr {$current_index - 1}]] + if { $new_reg != {} } { + $this reg_select $new_reg + } +} + +# ------------------------------------------------------------------ +# PUBLIC METHOD: reg_select_down +# ------------------------------------------------------------------ +body RegWin::reg_select_down { } { + if { $selected == -1 || $Running} { + return + } + set current_index [lsearch -exact $reg_display_list $selected] + set new_reg [lindex $reg_display_list [expr {$current_index + 1}]] + if { $new_reg != {} } { + $this reg_select $new_reg + } +} + +# ------------------------------------------------------------------ +# PUBLIC METHOD: reg_select_right +# ------------------------------------------------------------------ +body RegWin::reg_select_right { } { + if { $selected == -1 || $Running} { + return + } + set current_index [lsearch -exact $reg_display_list $selected] + set new_reg [lindex $reg_display_list [expr {$current_index + $nRows}]] + if { $new_reg != {} } { + $this reg_select $new_reg + } +} + +# ------------------------------------------------------------------ +# PUBLIC METHOD: reg_select_left +# ------------------------------------------------------------------ +body RegWin::reg_select_left { } { + if { $selected == -1 || $Running} { + return + } + set current_index [lsearch -exact $reg_display_list $selected] + set new_reg [lindex $reg_display_list [expr {$current_index - $nRows}]] + if { $new_reg != {} } { + $this reg_select $new_reg + } +} + +# ------------------------------------------------------------------ +# PUBLIC METHOD: reg_select - select a register +# ------------------------------------------------------------------ +body RegWin::reg_select { r } { + global tixOption + + if {$Running} { return } + if {$selected != -1} { + catch {$ScrolledWin.$selected.lbl configure -fg $tixOption(fg) -bg $tixOption(bg)} + catch {$ScrolledWin.$selected.val configure -fg $tixOption(fg) \ + -bg $tixOption(input1_bg)} + } + + # if we click on the same line, unselect it and return + if {$selected == $r} { + set selected -1 + $itk_interior.m.reg entryconfigure 0 -state disabled + $itk_interior.m.reg entryconfigure 2 -state disabled + for {set i 0} {$i < 6} {incr i} { + $itk_interior.m.reg.format entryconfigure $i -state disabled + } + return + } + + if {$Editing != -1} { + unedit + } + + $ScrolledWin.$r.lbl configure -fg $tixOption(select_fg) -bg $tixOption(select_bg) + $ScrolledWin.$r.val configure -fg $tixOption(fg) -bg $tixOption(bg) + + if {![pref get gdb/mode]} { + $itk_interior.m.reg entryconfigure 0 -state normal -command "$this edit $r" + } + $itk_interior.m.reg entryconfigure 2 -state normal \ + -command "$this delete_from_display_list $r" + for {set i 0} {$i < 6} {incr i} { + $itk_interior.m.reg.format entryconfigure $i -state normal \ + -variable reg_display($r,format) + } + focus -force $ScrolledWin.$r + set selected $r +} + +# ------------------------------------------------------------------ +# PRIVATE METHOD: dimensions - determine square-like dimensions for +# register window +# ------------------------------------------------------------------ +body RegWin::dimensions {} { + set rows 16 + # set rows [expr int(floor(sqrt($num_regs)))] + set cols [expr {int(ceil(sqrt($num_regs)))}] + + return [list $rows $cols] +} + +# ------------------------------------------------------------------------------ +# NAME: +# private method RegWin::fixLength +# +# SYNOPSIS: +# fixLength {s size where} +# +# DESC: +# Makes a string into a fixed-length string, inserting spaces as +# necessary. If 'where' is "left" spaces will be added to the left, +# if 'where' is "right" spaces will be added to the right. +# ARGS: +# s - input string +# size - size of string to output +# where - "left" or "right" +# +# RETURNS: +# Padded string of length 'size' +# +# NOTES: +# This should really be a proc, not a method. +# ------------------------------------------------------------------------------ +body RegWin::fixLength {s size where} { + set blank " " + set len [string length $s] + set bl [expr {$size - $len}] + set b [string range $blank 0 $bl] + + switch $where { + left { set fl "$s$b"} + right { set fl "$b$s"} + } + return $fl +} + +# ------------------------------------------------------------------ +# PUBLIC METHOD: but3 - generate and display a popup window on button 3 +# over the register value +# ------------------------------------------------------------------ +body RegWin::but3 {rn X Y} { + global reg_display max_regs + + if {!$Running} { + $Menu delete 0 end + $Menu add command -label $reg_display($rn,name) -state disabled + $Menu add separator + $Menu add radio -label "Hex" -command "$this update" \ + -value x -variable reg_display($rn,format) + $Menu add radio -label "Decimal" -command "$this update" \ + -value d -variable reg_display($rn,format) + $Menu add radio -label "Natural" -command "$this update" \ + -value {} -variable reg_display($rn,format) + $Menu add radio -label "Binary" -command "$this update" \ + -value t -variable reg_display($rn,format) -underline 0 + $Menu add radio -label "Octal" -command "$this update" \ + -value o -variable reg_display($rn,format) + $Menu add radio -label "Raw" -command "$this update" \ + -value r -variable reg_display($rn,format) + $Menu add separator + $Menu add command -command "$this delete_from_display_list $rn" \ + -label "Remove $reg_display($rn,name) from Display" + if {$max_regs != $num_regs} { + $Menu add separator + $Menu add command -command "$this display_all" \ + -label "Display all registers" + } + tk_popup $Menu $X $Y + } +} + +# ------------------------------------------------------------------ +# PUBLIC METHOD: display_all - add all registers to the display list +# ------------------------------------------------------------------ +body RegWin::display_all {} { + init_reg_display_vars + $itk_interior.m.reg entryconfigure 4 -state disabled + reconfig +} + +# ------------------------------------------------------------------ +# PUBLIC METHOD: delete_from_display_list - remove a register from the +# display list +# ------------------------------------------------------------------ +body RegWin::delete_from_display_list {rn} { + global reg_display max_regs + set reg_display($rn,line) 0 + set reg_display_list {} + set rn 0 + set i 0 + while {$rn < $max_regs} { + if {$reg_display($rn,line) > 0} { + lappend reg_display_list $rn + incr i + set reg_display($rn,line) $i + } + incr rn + } + set num_regs $i + reconfig + $itk_interior.m.reg entryconfigure 4 -state normal +} + +# ------------------------------------------------------------------ +# PUBLIC METHOD: edit - edit a cell +# ------------------------------------------------------------------ +body RegWin::edit {r} { + global reg_display + if {$Running} { return } + unedit + + set Editing $r + set txt [$ScrolledWin.$r.val cget -text] + set len [string length $txt] + set entry [entry $ScrolledWin.$r.ent -width $len -bd 0 -font src-font] + $entry insert 0 $txt + + grid remove $ScrolledWin.$r.val + grid $entry -row 0 -col 1 + bind $entry <Return> "$this acceptEdit $r" + bind $entry <Escape> "$this unedit" + $entry selection to end + focus $entry +} + +# ------------------------------------------------------------------ +# PUBLIC METHOD: acceptEdit - callback invoked when enter key pressed +# in an editing entry +# ------------------------------------------------------------------ +body RegWin::acceptEdit {r} { + global reg_display + + set value [string trimleft [$ScrolledWin.$r.ent get]] + debug "value=${value}=" + if {$value == ""} { + set value 0 + } + if {[catch {gdb_cmd "set \$$reg_display($r,name)=$value"} result]} { + tk_messageBox -icon error -type ok -message $result \ + -title "Error in Expression" -parent $this + focus $ScrolledWin.$r.ent + $ScrolledWin.$r.ent selection to end + } else { + unedit + gdbtk_update + } +} + +# ------------------------------------------------------------------ +# PUBLIC METHOD: unedit - clear any editing entry on the screen +# ------------------------------------------------------------------ +body RegWin::unedit {} { + if {$Editing != -1} { + destroy $ScrolledWin.$Editing.ent + + # Fill the entry with the old label, updating value + grid $ScrolledWin.$Editing.val -column 1 -row 0 + focus -force $ScrolledWin.$Editing + set Editing -1 + update + } +} + +# ------------------------------------------------------------------ +# PRIVATE METHOD: update - update widget when PC changes +# ------------------------------------------------------------------ +body RegWin::update {} { + global reg_display + debug "START REGISTER UPDATE CALLBACK" + if {$reg_display_list == "" + || [catch {eval gdb_changed_register_list $reg_display_list} changed_reg_list]} { + set changed_reg_list {} + } + + set vmax 0 + foreach r $reg_display_list { + if {[catch {gdb_fetch_registers $reg_display($r,format) $r} values($r)]} { + set values($r) "" + } else { + set values($r) [string trim $values($r) \ ] + } + set l [string length $values($r)] + if {$l > $vmax} { + set vmax $l + } + } + + foreach r $reg_display_list { + if {[lsearch -exact $changed_reg_list $r] != -1} { + set fg $HighlightForeground + } else { + set fg $NormalForeground + } + $ScrolledWin.$r.val configure -text [fixLength $values($r) $vmax right] \ + -fg $fg + } + debug "END REGISTER UPDATE CALLBACK" +} + +body RegWin::idle {} { + [winfo toplevel $itk_interior] configure -cursor {} + set Running 0 +} + +# ------------------------------------------------------------------ +# PRIVATE METHOD: reconfig - used when preferences change +# ------------------------------------------------------------------ +body RegWin::reconfig {} { + if {$reg_names_dirty} { + init_reg_display_vars + } + destroy $Menu $itk_interior.g $itk_interior.scrolled $itk_interior.m + gdbtk_busy + build_win + gdbtk_idle +} + +# ------------------------------------------------------------------ +# PRIVATE METHOD: busy - gdb_busy_hook +# ------------------------------------------------------------------ +body RegWin::busy {} { + # Cancel edits + unedit + + # Fencepost + set Running 1 + + # cursor + [winfo toplevel $itk_interior] configure -cursor watch +} |