* stabsread.c (get_substring): Declare second arg as int.
[deliverable/binutils-gdb.git] / gdb / gdbtk.tcl
index 5709a57dcd0078e8acf7518d3c4802e54020b514..bd08669e734b723e35b16ebcc8415804c224e0df 100644 (file)
@@ -27,8 +27,10 @@ set cfunc NIL
 set line_numbers 1
 set breakpoint_file(-1) {[garbage]}
 set disassemble_with_source nosource
-set expr_update_list(0) 0
+set gdb_prompt "(gdb) "
 
+# Hint: The following can be toggled from a tclsh window after
+# using the gdbtk "tk tclsh" command to open the window.
 set debug_interface 0
 
 #option add *Foreground Black
@@ -65,7 +67,7 @@ proc decr {var {val 1}} {
 #
 # Center a window on the screen.
 #
-proc center_window toplevel {
+proc center_window {toplevel} {
   # Withdraw and update, to ensure geometry computations are finished.
   wm withdraw $toplevel
   update idletasks
@@ -264,6 +266,103 @@ proc gdbtk_tcl_breakpoint {action bpnum} {
        ${action}_breakpoint $bpnum $file $line $pc
 }
 
+#
+# GDB Callback:
+#
+#      gdbtk_tcl_readline_begin (message) - Notify Tk to open an interaction
+#      window and start gathering user input
+#
+# Description:
+#
+#      GDB calls this to notify TK that it needs to open an interaction
+#      window, displaying the given message, and be prepared to accept
+#      calls to gdbtk_tcl_readline to gather user input.
+
+proc gdbtk_tcl_readline_begin {message} {
+    global readline_text
+
+    # If another readline window already exists, just bring it to the front.
+    if {[winfo exists .rl]} {raise .rl ; return}
+
+    # Create top level frame with scrollbar and text widget.
+    toplevel .rl
+    wm title .rl "Interaction Window"
+    wm iconname .rl "Input"
+    message .rl.msg -text $message -aspect 7500 -justify left
+    text .rl.text -width 80 -height 20 -setgrid true -cursor hand2 \
+           -yscrollcommand {.rl.scroll set}
+    scrollbar .rl.scroll -command {.rl.text yview}
+    pack .rl.msg -side top -fill x
+    pack .rl.scroll -side right -fill y
+    pack .rl.text -side left -fill both -expand true
+
+    # When the user presses return, get the text from the command start mark to the
+    # current insert point, stash it in the readline text variable, and update the
+    # command start mark to the current insert point
+    bind .rl.text <Return> {
+       set readline_text [.rl.text get cmdstart {end - 1 char}]
+       .rl.text mark set cmdstart insert
+    }
+    bind .rl.text <BackSpace> {
+       if [%W compare insert > cmdstart] {
+           %W delete {insert - 1 char} insert
+       } else {
+           bell
+       }
+       break
+    }
+    bind .rl.text <Any-Key> {
+       if [%W compare insert < cmdstart] {
+           %W mark set insert end
+       }
+    }
+    bind .rl.text <Control-u> {
+       %W delete cmdstart "insert lineend"
+       %W see insert
+    }
+    bindtags .rl.text {.rl.text Text all}
+}
+
+#
+# GDB Callback:
+#
+#      gdbtk_tcl_readline (prompt) - Get one user input line
+#
+# Description:
+#
+#      GDB calls this to get one line of input from the user interaction
+#      window, using "prompt" as the command line prompt.
+
+proc gdbtk_tcl_readline {prompt} {
+    global readline_text
+
+    .rl.text insert end $prompt
+    .rl.text mark set cmdstart insert
+    .rl.text mark gravity cmdstart left
+    .rl.text see insert
+
+    # Make this window the current one for input.
+    focus .rl.text
+    grab .rl
+    tkwait variable readline_text
+    grab release .rl
+    return $readline_text
+}
+
+#
+# GDB Callback:
+#
+#      gdbtk_tcl_readline_end  - Terminate a user interaction
+#
+# Description:
+#
+#      GDB calls this when it is done getting interactive user input.
+#      Destroy the interaction window.
+
+proc gdbtk_tcl_readline_end {} {
+    if {[winfo exists .rl]} { destroy .rl }
+}
+
 proc create_breakpoints_window {} {
        global bpframe_lasty
 
@@ -305,7 +404,7 @@ proc create_breakpoints_window {} {
 
 # Create a frame for bpnum in the .breakpoints canvas
 
-proc add_breakpoint_frame bpnum {
+proc add_breakpoint_frame {bpnum} {
   global bpframe_lasty
   global enabled
   global disposition
@@ -404,7 +503,7 @@ proc add_breakpoint_frame bpnum {
 
 # Delete a breakpoint frame
 
-proc delete_breakpoint_frame bpnum {
+proc delete_breakpoint_frame {bpnum} {
        global bpframe_lasty
 
        if {![winfo exists .breakpoints]} return
@@ -989,9 +1088,6 @@ proc not_implemented_yet {message} {
 #      Create the expression display window.
 #
 
-set expr_num 0
-set delete_expr_num 0
-
 # Set delete_expr_num, and set -state of Delete button.
 proc expr_update_button {num} {
   global delete_expr_num
@@ -1035,13 +1131,14 @@ proc add_expr {expr} {
 
 proc delete_expr {} {
   global delete_expr_num
+  global expr_update_list
+
   if {$delete_expr_num > 0} then {
     set e .expr.exprs
     set f e${delete_expr_num}
 
     destroy $e.updates.$f $e.expressions.$f $e.values.$f
-
-    # FIXME should we unset an element of expr_update_list here?
+    unset expr_update_list($delete_expr_num)
   }
 }
 
@@ -1071,9 +1168,21 @@ proc update_exprs {} {
 }
 
 proc create_expr_window {} {
+       global expr_num
+       global delete_expr_num
+       global expr_update_list
 
        if {[winfo exists .expr]} {raise .expr ; return}
 
+       # All the state about individual expressions is stored in the
+       # expression window widgets, so when it is deleted, the
+       # previous values of the expression global variables become
+       # invalid.  Reset to a known initial state.
+       set expr_num 0
+       set delete_expr_num 0
+       catch {unset expr_update_list}
+       set expr_update_list(0) 0
+
        toplevel .expr
        wm title .expr "GDB Expressions"
        wm iconname .expr "Expressions"
@@ -1666,60 +1775,155 @@ proc reg_config_menu {} {
 #
 
 proc create_registers_window {} {
-       global reg_format
+    global reg_format_natural
+    global reg_format_decimal
+    global reg_format_hex
+    global reg_format_octal
+    global reg_format_raw
+    global reg_format_binary
+    global reg_format_unsigned
 
-       if {[winfo exists .reg]} {raise .reg ; return}
+    # If we already have a register window, just use that one.
 
-# Create an initial register display list consisting of all registers
+    if {[winfo exists .reg]} {raise .reg ; return}
 
-       if {![info exists reg_format]} {
-               global reg_display_list
-               global changed_reg_list
-               global regena
+    # Create an initial register display list consisting of all registers
 
-               set reg_format {}
-               set num_regs [llength [gdb_regnames]]
-               for {set regnum 0} {$regnum < $num_regs} {incr regnum} {
-                       set regena($regnum) 1
-               }
-               recompute_reg_display_list $num_regs
-               set changed_reg_list $reg_display_list
-       }
+    init_reg_info
 
-       build_framework .reg Registers
+    build_framework .reg Registers
 
-# First, delete all the old menu entries
+    # First, delete all the old menu entries
+
+    .reg.menubar.view.menu delete 0 last
+
+    # Natural menu item
+    .reg.menubar.view.menu add checkbutton -label $reg_format_natural(label) \
+           -variable reg_format_natural(enable) -onvalue on -offvalue off \
+           -command {update_registers redraw}
+
+    # Decimal menu item
+    .reg.menubar.view.menu add checkbutton -label $reg_format_decimal(label) \
+           -variable reg_format_decimal(enable) -onvalue on -offvalue off \
+           -command {update_registers redraw}
 
-       .reg.menubar.view.menu delete 0 last
+    # Hex menu item
+    .reg.menubar.view.menu add checkbutton -label $reg_format_hex(label) \
+           -variable reg_format_hex(enable) -onvalue on -offvalue off \
+           -command {update_registers redraw}
 
-# Hex menu item
-       .reg.menubar.view.menu add radiobutton -label Hex \
-               -command {set reg_format x ; update_registers all}
+    # Octal menu item
+    .reg.menubar.view.menu add checkbutton -label $reg_format_octal(label) \
+           -variable reg_format_octal(enable) -onvalue on -offvalue off \
+           -command {update_registers redraw}
 
-# Decimal menu item
-       .reg.menubar.view.menu add radiobutton -label Decimal \
-               -command {set reg_format d ; update_registers all}
+    # Binary menu item
+    .reg.menubar.view.menu add checkbutton -label $reg_format_binary(label) \
+           -variable reg_format_binary(enable) -onvalue on -offvalue off \
+           -command {update_registers redraw}
 
-# Octal menu item
-       .reg.menubar.view.menu add radiobutton -label Octal \
-               -command {set reg_format o ; update_registers all}
+    # Unsigned menu item
+    .reg.menubar.view.menu add checkbutton -label $reg_format_unsigned(label) \
+           -variable reg_format_unsigned(enable) -onvalue on -offvalue off \
+           -command {update_registers redraw}
 
-# Natural menu item
-       .reg.menubar.view.menu add radiobutton -label Natural \
-               -command {set reg_format {} ; update_registers all}
+    # Raw menu item
+    .reg.menubar.view.menu add checkbutton -label $reg_format_raw(label) \
+           -variable reg_format_raw(enable) -onvalue on -offvalue off \
+           -command {update_registers redraw}
 
-# Config menu item
-       .reg.menubar.view.menu add separator
+    # Config menu item
+    .reg.menubar.view.menu add separator
 
-       .reg.menubar.view.menu add command -label Config -command {
-               reg_config_menu }
+    .reg.menubar.view.menu add command -label Config \
+           -command { reg_config_menu }
 
-       destroy .reg.label
+    destroy .reg.label
 
-# Install the reg names
+    # Install the reg names
 
-       populate_reg_window
-       update_registers all
+    populate_reg_window
+    update_registers all
+}
+
+proc init_reg_info {} {
+    global reg_format_natural
+    global reg_format_decimal
+    global reg_format_hex
+    global reg_format_octal
+    global reg_format_raw
+    global reg_format_binary
+    global reg_format_unsigned
+    global long_size
+    global double_size
+
+    if {![info exists reg_format_hex]} {
+       global reg_display_list
+       global changed_reg_list
+       global regena
+
+       set long_size [lindex [gdb_cmd {p sizeof(long)}] 2]
+       set double_size [lindex [gdb_cmd {p sizeof(double)}] 2]
+
+       # The natural format may print floats or doubles as floating point,
+       # which typically takes more room that printing ints on the same
+       # machine.  We assume that if longs are 8 bytes that this is
+       # probably a 64 bit machine.  (FIXME)
+       set reg_format_natural(label) Natural
+       set reg_format_natural(enable) on
+       set reg_format_natural(format) {}
+       if {$long_size == 8} then {
+           set reg_format_natural(width) 25
+       } else {
+           set reg_format_natural(width) 16
+       }
+
+       set reg_format_decimal(label) Decimal
+       set reg_format_decimal(enable) off
+       set reg_format_decimal(format) d
+       if {$long_size == 8} then {
+           set reg_format_decimal(width) 21
+       } else {
+           set reg_format_decimal(width) 12
+       }
+
+       set reg_format_hex(label) Hex
+       set reg_format_hex(enable) off
+       set reg_format_hex(format) x
+       set reg_format_hex(width) [expr $long_size * 2 + 3]
+
+       set reg_format_octal(label) Octal
+       set reg_format_octal(enable) off
+       set reg_format_octal(format) o
+       set reg_format_octal(width) [expr $long_size * 8 / 3 + 3]
+
+       set reg_format_raw(label) Raw
+       set reg_format_raw(enable) off
+       set reg_format_raw(format) r
+       set reg_format_raw(width) [expr $double_size * 2 + 3]
+
+       set reg_format_binary(label) Binary
+       set reg_format_binary(enable) off
+       set reg_format_binary(format) t
+       set reg_format_binary(width) [expr $long_size * 8 + 1]
+
+       set reg_format_unsigned(label) Unsigned
+       set reg_format_unsigned(enable) off
+       set reg_format_unsigned(format) u
+       if {$long_size == 8} then {
+           set reg_format_unsigned(width) 21
+       } else {
+           set reg_format_unsigned(width) 11
+       }
+
+       set num_regs [llength [gdb_regnames]]
+       for {set regnum 0} {$regnum < $num_regs} {incr regnum} {
+           set regena($regnum) 1
+       }
+       recompute_reg_display_list $num_regs
+       #set changed_reg_list $reg_display_list
+       set changed_reg_list {}
+    }
 }
 
 # Convert regena into a list of the enabled $regnums
@@ -1730,8 +1934,9 @@ proc recompute_reg_display_list {num_regs} {
        global regena
 
        catch {unset reg_display_list}
+       set reg_display_list {}
 
-       set line 1
+       set line 2
        for {set regnum 0} {$regnum < $num_regs} {incr regnum} {
 
                if {[set regena($regnum)] != 0} {
@@ -1746,38 +1951,56 @@ proc recompute_reg_display_list {num_regs} {
 # reg_display_list.
 
 proc populate_reg_window {} {
-       global max_regname_width
-       global reg_display_list
-
-       .reg.text configure -state normal
-
-       .reg.text delete 0.0 end
-
+    global reg_format_natural
+    global reg_format_decimal
+    global reg_format_hex
+    global reg_format_octal
+    global reg_format_raw
+    global reg_format_binary
+    global reg_format_unsigned
+    global max_regname_width
+    global reg_display_list
+
+    set win .reg.text
+    $win configure -state normal
+
+    # Clear the entire widget and insert a blank line at the top where
+    # the column labels will appear.
+    $win delete 0.0 end
+    $win insert end "\n"
+
+    if {[llength $reg_display_list] > 0} {
        set regnames [eval gdb_regnames $reg_display_list]
+    } else {
+       set regnames {}
+    }
 
-# Figure out the longest register name
-
-       set max_regname_width 0
+    # Figure out the longest register name
 
-       foreach reg $regnames {
-               set len [string length $reg]
-               if {$len > $max_regname_width} {set max_regname_width $len}
-       }
+    set max_regname_width 0
 
-       set width [expr $max_regname_width + 15]
+    foreach reg $regnames {
+       set len [string length $reg]
+       if {$len > $max_regname_width} {set max_regname_width $len}
+    }
 
-       set height [llength $regnames]
+    set width [expr $max_regname_width + 15]
 
-       if {$height > 60} {set height 60}
+    set height [expr [llength $regnames] + 1]
 
-       .reg.text configure -height $height -width $width
+    if {$height > 60} {set height 60}
 
-       foreach reg $regnames {
-               .reg.text insert end [format "%-*s \n" $max_regname_width ${reg}]
-       }
+    $win configure -height $height -width $width
+    foreach reg $regnames {
+       $win insert end [format "%-*s\n" $width ${reg}]
+    }
 
-       .reg.text yview 0
-       .reg.text configure -state disabled
+    #Delete the blank line left at end by last insertion.
+    if {[llength $regnames] > 0} {
+       $win delete {end - 1 char} end
+    }
+    $win yview 0
+    $win configure -state disabled
 }
 
 #
@@ -1787,60 +2010,91 @@ proc populate_reg_window {} {
 #
 # Description:
 #
-#      This procedure updates the registers window.
+#      This procedure updates the registers window according to the value of
+#      the "which" arg.
 #
 
 proc update_registers {which} {
-       global max_regname_width
-       global reg_format
-       global reg_display_list
-       global changed_reg_list
-       global highlight
-       global regmap
-
-       set margin [expr $max_regname_width + 1]
-       set win .reg.text
-       set winwidth [lindex [$win configure -width] 4]
-       set valwidth [expr $winwidth - $margin]
-
-       $win configure -state normal
-
-       if {$which == "all"} {
-               set lineindex 1
-               foreach regnum $reg_display_list {
-                       set regval [gdb_fetch_registers $reg_format $regnum]
-                       set regval [format "%-*s" $valwidth $regval]
-                       $win delete $lineindex.$margin "$lineindex.0 lineend"
-                       $win insert $lineindex.$margin $regval
-                       incr lineindex
-               }
-               $win configure -state disabled
-               return
+    global max_regname_width
+    global reg_format_natural
+    global reg_format_decimal
+    global reg_format_hex
+    global reg_format_octal
+    global reg_format_binary
+    global reg_format_unsigned
+    global reg_format_raw
+    global reg_display_list
+    global changed_reg_list
+    global highlight
+    global regmap
+
+    # margin is the column where we start printing values
+    set margin [expr $max_regname_width + 1]
+    set win .reg.text
+    $win configure -state normal
+
+    if {$which == "all" || $which == "redraw"} {
+       set display_list $reg_display_list
+       $win delete 1.0 1.end
+       $win insert 1.0 [format "%*s" $max_regname_width " "]
+       foreach format {natural decimal unsigned hex octal raw binary } {
+           set field (enable)
+           set var reg_format_$format$field
+           if {[set $var] == "on"} {
+               set field (label)
+               set var reg_format_$format$field
+               set label [set $var]
+               set field (width)
+               set var reg_format_$format$field
+               set var [format "%*s" [set $var] $label]
+               $win insert 1.end $var
+           }
        }
-
-# Unhighlight the old values
-
+    } else {
+       # Unhighlight the old values
        foreach regnum $changed_reg_list {
-               $win tag delete $win.$regnum
+           $win tag delete $win.$regnum
        }
-
-# Now, highlight the changed values of the interesting registers
-
        set changed_reg_list [eval gdb_changed_register_list $reg_display_list]
-
-       set lineindex 1
+       set display_list $changed_reg_list
+    }
+    foreach regnum $display_list {
+       set lineindex $regmap($regnum)
+       $win delete $lineindex.$margin "$lineindex.0 lineend"
+       foreach format {natural decimal unsigned hex octal raw binary } {
+           set field (enable)
+           set var reg_format_$format$field
+           if {[set $var] == "on"} {
+               set field (format)
+               set var reg_format_$format$field
+               set regval [gdb_fetch_registers [set $var] $regnum]
+               set field (width)
+               set var reg_format_$format$field
+               set regval [format "%*s" [set $var] $regval]
+               $win insert $lineindex.end $regval
+           }
+       }
+    }
+    # Now, highlight the changed values of the interesting registers
+    if {$which != "all"} {
        foreach regnum $changed_reg_list {
-               set regval [gdb_fetch_registers $reg_format $regnum]
-               set regval [format "%-*s" $valwidth $regval]
-
-               set lineindex $regmap($regnum)
-               $win delete $lineindex.$margin "$lineindex.0 lineend"
-               $win insert $lineindex.$margin $regval
-               $win tag add $win.$regnum $lineindex.0 "$lineindex.0 lineend"
-               eval $win tag configure $win.$regnum $highlight
+           set lineindex $regmap($regnum)
+           $win tag add $win.$regnum $lineindex.0 "$lineindex.0 lineend"
+           eval $win tag configure $win.$regnum $highlight
        }
-
-       $win configure -state disabled
+    }
+    set winwidth $margin
+    foreach format {natural decimal unsigned hex octal raw binary} {
+       set field (enable)
+       set var reg_format_$format$field
+       if {[set $var] == "on"} {
+           set field (width)
+           set var reg_format_$format$field
+           set winwidth [expr $winwidth + [set $var]]
+       }
+    }
+    $win configure -width $winwidth
+    $win configure -state disabled
 }
 
 #
@@ -1973,7 +2227,7 @@ proc files_command {} {
 
   wm minsize .files_window 1 1
   #    wm overrideredirect .files_window true
-  listbox .files_window.list -geometry 30x20 -setgrid true \
+  listbox .files_window.list -width 30 -height 20 -setgrid true \
     -yscrollcommand {.files_window.scroll set} -relief sunken \
     -borderwidth 2
   scrollbar .files_window.scroll -orient vertical \
@@ -1981,31 +2235,23 @@ proc files_command {} {
   button .files_window.close -text Close -command {destroy .files_window}
   .files_window.list configure -selectmode single
 
-  # Get the file list from GDB, sort it, and format it as one entry per line.
-  set lastSeen {};                     # Value that won't appear in
-                                       # list.
-  set fileList {}
-  foreach file [lsort [gdb_listfiles]] {
-    if {$file != $lastSeen} then {
-      lappend fileList $file
-      set lastSeen $file
-    }
-  }
-  set filelist [join [lsort [gdb_listfiles]] "\n"]
-
-  # Insert the file list into the widget
-
-  eval .files_window.list insert 0 $filelist
+  # Get the file list from GDB, sort it, and insert into the widget.
+  eval .files_window.list insert 0 [lsort [gdb_listfiles]]
 
   pack .files_window.close -side bottom -fill x -expand no -anchor s
   pack .files_window.scroll -side right -fill both
   pack .files_window.list -side left -fill both -expand yes
-  bind .files_window.list <Any-ButtonRelease-1> {
+  bind .files_window.list <ButtonRelease-1> {
     set file [%W get [%W curselection]]
     gdb_cmd "list $file:1,0"
     update_listing [gdb_loc $file:1]
     destroy .files_window
   }
+  # We must execute the listbox binding first, because it
+  # references the widget that will be destroyed by the widget
+  # binding for Button-Release-1.  Otherwise we try to use
+  # .files_window.list after the .files_window is destroyed.
+  bind_widget_after_class .files_window.list
 }
 
 button .files -text Files -command files_command
@@ -2304,6 +2550,7 @@ proc find_completion {cmd completions} {
 proc create_command_window {} {
        global command_line
        global saw_tab
+       global gdb_prompt
 
        set saw_tab 0
        if {[winfo exists .cmd]} {raise .cmd ; return}
@@ -2326,7 +2573,7 @@ proc create_command_window {} {
         set bsBinding [bind Text <BackSpace>]
         bind .cmd.text <Delete> "delete_char %W ; $bsBinding; break"
        bind .cmd.text <BackSpace> {
-         if {([%W get -state] == "disabled")} { break }
+         if {([%W cget -state] == "disabled")} { break }
          delete_char %W
        }
        bind .cmd.text <Control-u> {
@@ -2353,7 +2600,7 @@ proc create_command_window {} {
          # %W insert end $result
          set command_line {}
          # update_ptr
-         %W insert end "(gdb) "
+         %W insert end "$gdb_prompt"
          %W see end
          break
        }
@@ -2404,25 +2651,34 @@ proc create_command_window {} {
            if {[regexp ".* " $command_line prefix]} {
              regsub -all $prefix $choices {} choices
            }
-           %W insert end "\n[join $choices { }]\n(gdb) $command_line"
+           %W insert end "\n[join $choices { }]\n$gdb_prompt$command_line"
            %W see end
          }
          break
        }
 }
 
+# Trim one character off the command line.  The argument is ignored.
+
 proc delete_char {win} {
   global command_line
   set tmp [expr [string length $command_line] - 2]
   set command_line [string range $command_line 0 $tmp]
 }
 
+# FIXME: This should actually check that the first characters of the current
+# line  match the gdb prompt, since the user can move the insertion point
+# anywhere.  It should also check that the insertion point is in the last
+# line of the text widget.
+
 proc delete_line {win} {
-  global command_line
+    global command_line
+    global gdb_prompt
 
-  $win delete {end linestart + 6 chars} end
-  $win see insert
-  set command_line {}
+    set tmp [string length $gdb_prompt]
+    $win delete "insert linestart + $tmp chars" "insert lineend"
+    $win see insert
+    set command_line {}
 }
 
 #
@@ -3107,6 +3363,91 @@ proc create_copyright_window {} {
   center_window .c
 }
 
+# Begin support primarily for debugging the tcl/tk portion of gdbtk.  You can
+# start gdbtk, and then issue the command "tk tclsh" and a window will pop up
+# giving you direct access to the tcl interpreter.  With this, it is very easy
+# to examine the values of global variables, directly invoke routines that are
+# part of the gdbtk interface, replace existing proc's with new ones, etc.
+# This code was inspired from example 11-3 in Brent Welch's "Practical
+# Programming in Tcl and Tk"
+
+set tcl_prompt "tcl> "
+
+# Get the current command that user has typed, from cmdstart to end of text
+# widget.  Evaluate it, insert result back into text widget, issue a new
+# prompt, update text widget and update command start mark.
+
+proc evaluate_tcl_command { twidget } {
+    global tcl_prompt
+
+    set command [$twidget get cmdstart end]
+    if [info complete $command] {
+       set err [catch {uplevel #0 $command} result]
+       $twidget insert insert \n$result\n
+       $twidget insert insert $tcl_prompt
+       $twidget see insert
+       $twidget mark set cmdstart insert
+       return
+    }
+}
+
+# Create the evaluation window and set up the keybindings to evaluate the
+# last single line entered by the user.  FIXME: allow multiple lines?
+
+proc tclsh {} {
+    global tcl_prompt
+
+    # If another evaluation window already exists, just bring it to the front.
+    if {[winfo exists .eval]} {raise .eval ; return}
+
+    # Create top level frame with scrollbar and text widget.
+    toplevel .eval
+    wm title .eval "Tcl Evaluation"
+    wm iconname .eval "Tcl"
+    text .eval.text -width 80 -height 20 -setgrid true -cursor hand2 \
+           -yscrollcommand {.eval.scroll set}
+    scrollbar .eval.scroll -command {.eval.text yview}
+    pack .eval.scroll -side right -fill y
+    pack .eval.text -side left -fill both -expand true
+
+    # Insert the tcl_prompt and initialize the cmdstart mark
+    .eval.text insert insert $tcl_prompt
+    .eval.text mark set cmdstart insert
+    .eval.text mark gravity cmdstart left
+
+    # Make this window the current one for input.
+    focus .eval.text
+
+    # Keybindings that limit input and evaluate things
+    bind .eval.text <Return> { evaluate_tcl_command .eval.text ; break }
+    bind .eval.text <BackSpace> {
+       if [%W compare insert > cmdstart] {
+           %W delete {insert - 1 char} insert
+       } else {
+           bell
+       }
+       break
+    }
+    bind .eval.text <Any-Key> {
+       if [%W compare insert < cmdstart] {
+           %W mark set insert end
+       }
+    }
+    bind .eval.text <Control-u> {
+       %W delete cmdstart "insert lineend"
+       %W see insert
+    }
+    bindtags .eval.text {.eval.text Text all}
+}
+
+# This proc is executed just prior to falling into the Tk main event loop.
+proc gdbtk_tcl_preloop {} {
+    global gdb_prompt
+    .cmd.text insert end "$gdb_prompt"
+    .cmd.text see end
+    update
+}
+
 # FIXME need to handle mono here.  In Tk4 that is more complicated.
 set highlight "-background red2 -borderwidth 2 -relief sunken"
 
This page took 0.031976 seconds and 4 git commands to generate.