* gdbtk.tcl: Take .gdbtkinit if it exists. Makes gdbtk match the
[deliverable/binutils-gdb.git] / gdb / gdbtk.tcl
1 # GDB GUI setup for GDB, the GNU debugger.
2 # Copyright 1994, 1995
3 # Free Software Foundation, Inc.
4
5 # Written by Stu Grossman <grossman@cygnus.com> of Cygnus Support.
6
7 # This file is part of GDB.
8
9 # This program is free software; you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation; either version 2 of the License, or
12 # (at your option) any later version.
13
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
18
19 # You should have received a copy of the GNU General Public License
20 # along with this program; if not, write to the Free Software
21 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
22
23 set cfile Blank
24 set wins($cfile) .src.text
25 set current_label {}
26 set screen_height 0
27 set screen_top 0
28 set screen_bot 0
29 set current_output_win .cmd.text
30 set cfunc NIL
31 set line_numbers 1
32 set breakpoint_file(-1) {[garbage]}
33 set disassemble_with_source nosource
34
35 #option add *Foreground Black
36 #option add *Background White
37 #option add *Font -*-*-medium-r-normal--18-*-*-*-m-*-*-1
38 tk colormodel . monochrome
39
40 proc echo string {puts stdout $string}
41
42 if [info exists env(EDITOR)] then {
43 set editor $env(EDITOR)
44 } else {
45 set editor emacs
46 }
47
48 # GDB callbacks
49 #
50 # These functions are called by GDB (from C code) to do various things in
51 # TK-land. All start with the prefix `gdbtk_tcl_' to make them easy to find.
52 #
53
54 #
55 # GDB Callback:
56 #
57 # gdbtk_tcl_fputs (text) - Output text to the command window
58 #
59 # Description:
60 #
61 # GDB calls this to output TEXT to the GDB command window. The text is
62 # placed at the end of the text widget. Note that output may not occur,
63 # due to buffering. Use gdbtk_tcl_flush to cause an immediate update.
64 #
65
66 proc gdbtk_tcl_fputs {arg} {
67 global current_output_win
68
69 $current_output_win insert end "$arg"
70 $current_output_win yview -pickplace end
71 }
72
73 proc gdbtk_tcl_fputs_error {arg} {
74 .cmd.text insert end "$arg"
75 .cmd.text yview -pickplace end
76 }
77
78 #
79 # GDB Callback:
80 #
81 # gdbtk_tcl_flush () - Flush output to the command window
82 #
83 # Description:
84 #
85 # GDB calls this to force all buffered text to the GDB command window.
86 #
87
88 proc gdbtk_tcl_flush {} {
89 global current_output_win
90
91 $current_output_win yview -pickplace end
92 update idletasks
93 }
94
95 #
96 # GDB Callback:
97 #
98 # gdbtk_tcl_query (message) - Create a yes/no query dialog box
99 #
100 # Description:
101 #
102 # GDB calls this to create a yes/no dialog box containing MESSAGE. GDB
103 # is hung while the dialog box is active (ie: no commands will work),
104 # however windows can still be refreshed in case of damage or exposure.
105 #
106
107 proc gdbtk_tcl_query {message} {
108 tk_dialog .query "gdb : query" "$message" {} 1 "No" "Yes"
109 }
110
111 #
112 # GDB Callback:
113 #
114 # gdbtk_start_variable_annotation (args ...) -
115 #
116 # Description:
117 #
118 # Not yet implemented.
119 #
120
121 proc gdbtk_tcl_start_variable_annotation {valaddr ref_type stor_cl cum_expr field type_cast} {
122 echo "gdbtk_tcl_start_variable_annotation $valaddr $ref_type $stor_cl $cum_expr $field $type_cast"
123 }
124
125 #
126 # GDB Callback:
127 #
128 # gdbtk_end_variable_annotation (args ...) -
129 #
130 # Description:
131 #
132 # Not yet implemented.
133 #
134
135 proc gdbtk_tcl_end_variable_annotation {} {
136 echo gdbtk_tcl_end_variable_annotation
137 }
138
139 #
140 # GDB Callback:
141 #
142 # gdbtk_tcl_breakpoint (action bpnum file line) - Notify the TK
143 # interface of changes to breakpoints.
144 #
145 # Description:
146 #
147 # GDB calls this to notify TK of changes to breakpoints. ACTION is one
148 # of:
149 # create - Notify of breakpoint creation
150 # delete - Notify of breakpoint deletion
151 # enable - Notify of breakpoint enabling
152 # disable - Notify of breakpoint disabling
153 #
154 # All actions take the same set of arguments: BPNUM is the breakpoint
155 # number, FILE is the source file and LINE is the line number, and PC is
156 # the pc of the affected breakpoint.
157 #
158
159 proc gdbtk_tcl_breakpoint {action bpnum file line pc} {
160 ${action}_breakpoint $bpnum $file $line $pc
161 }
162
163 proc asm_win_name {funcname} {
164 if {$funcname == "*None*"} {return .asm.text}
165
166 regsub -all {\.} $funcname _ temp
167
168 return .asm.func_${temp}
169 }
170
171 #
172 # Local procedure:
173 #
174 # create_breakpoint (bpnum file line pc) - Record breakpoint info in TK land
175 #
176 # Description:
177 #
178 # GDB calls this indirectly (through gdbtk_tcl_breakpoint) to notify TK
179 # land of breakpoint creation. This consists of recording the file and
180 # line number in the breakpoint_file and breakpoint_line arrays. Also,
181 # if there is already a window associated with FILE, it is updated with
182 # a breakpoint tag.
183 #
184
185 proc create_breakpoint {bpnum file line pc} {
186 global wins
187 global breakpoint_file
188 global breakpoint_line
189 global pos_to_breakpoint
190 global pos_to_bpcount
191 global cfunc
192 global pclist
193
194 # Record breakpoint locations
195
196 set breakpoint_file($bpnum) $file
197 set breakpoint_line($bpnum) $line
198 set pos_to_breakpoint($file:$line) $bpnum
199 if ![info exists pos_to_bpcount($file:$line)] {
200 set pos_to_bpcount($file:$line) 0
201 }
202 incr pos_to_bpcount($file:$line)
203 set pos_to_breakpoint($pc) $bpnum
204 if ![info exists pos_to_bpcount($pc)] {
205 set pos_to_bpcount($pc) 0
206 }
207 incr pos_to_bpcount($pc)
208
209 # If there's a window for this file, update it
210
211 if [info exists wins($file)] {
212 insert_breakpoint_tag $wins($file) $line
213 }
214
215 # If there's an assembly window, update that too
216
217 set win [asm_win_name $cfunc]
218 if [winfo exists $win] {
219 insert_breakpoint_tag $win [pc_to_line $pclist($cfunc) $pc]
220 }
221 }
222
223 #
224 # Local procedure:
225 #
226 # delete_breakpoint (bpnum file line pc) - Delete breakpoint info from TK land
227 #
228 # Description:
229 #
230 # GDB calls this indirectly (through gdbtk_tcl_breakpoint) to notify TK
231 # land of breakpoint destruction. This consists of removing the file and
232 # line number from the breakpoint_file and breakpoint_line arrays. Also,
233 # if there is already a window associated with FILE, the tags are removed
234 # from it.
235 #
236
237 proc delete_breakpoint {bpnum file line pc} {
238 global wins
239 global breakpoint_file
240 global breakpoint_line
241 global pos_to_breakpoint
242 global pos_to_bpcount
243 global cfunc pclist
244
245 # Save line number and file for later
246
247 set line $breakpoint_line($bpnum)
248
249 set file $breakpoint_file($bpnum)
250
251 # Reset breakpoint annotation info
252
253 if {$pos_to_bpcount($file:$line) > 0} {
254 decr pos_to_bpcount($file:$line)
255
256 if {$pos_to_bpcount($file:$line) == 0} {
257 catch "unset pos_to_breakpoint($file:$line)"
258
259 unset breakpoint_file($bpnum)
260 unset breakpoint_line($bpnum)
261
262 # If there's a window for this file, update it
263
264 if [info exists wins($file)] {
265 delete_breakpoint_tag $wins($file) $line
266 }
267 }
268 }
269
270 # If there's an assembly window, update that too
271
272 if {$pos_to_bpcount($pc) > 0} {
273 decr pos_to_bpcount($pc)
274
275 if {$pos_to_bpcount($pc) == 0} {
276 catch "unset pos_to_breakpoint($pc)"
277
278 set win [asm_win_name $cfunc]
279 if [winfo exists $win] {
280 delete_breakpoint_tag $win [pc_to_line $pclist($cfunc) $pc]
281 }
282 }
283 }
284 }
285
286 #
287 # Local procedure:
288 #
289 # enable_breakpoint (bpnum file line pc) - Record breakpoint info in TK land
290 #
291 # Description:
292 #
293 # GDB calls this indirectly (through gdbtk_tcl_breakpoint) to notify TK
294 # land of a breakpoint being enabled. This consists of unstippling the
295 # specified breakpoint indicator.
296 #
297
298 proc enable_breakpoint {bpnum file line pc} {
299 global wins
300 global cfunc pclist
301
302 if [info exists wins($file)] {
303 $wins($file) tag configure $line -fgstipple {}
304 }
305
306 # If there's an assembly window, update that too
307
308 set win [asm_win_name $cfunc]
309 if [winfo exists $win] {
310 $win tag configure [pc_to_line $pclist($cfunc) $pc] -fgstipple {}
311 }
312 }
313
314 #
315 # Local procedure:
316 #
317 # disable_breakpoint (bpnum file line pc) - Record breakpoint info in TK land
318 #
319 # Description:
320 #
321 # GDB calls this indirectly (through gdbtk_tcl_breakpoint) to notify TK
322 # land of a breakpoint being disabled. This consists of stippling the
323 # specified breakpoint indicator.
324 #
325
326 proc disable_breakpoint {bpnum file line pc} {
327 global wins
328 global cfunc pclist
329
330 if [info exists wins($file)] {
331 $wins($file) tag configure $line -fgstipple gray50
332 }
333
334 # If there's an assembly window, update that too
335
336 set win [asm_win_name $cfunc]
337 if [winfo exists $win] {
338 $win tag configure [pc_to_line $pclist($cfunc) $pc] -fgstipple gray50
339 }
340 }
341
342 #
343 # Local procedure:
344 #
345 # insert_breakpoint_tag (win line) - Insert a breakpoint tag in WIN.
346 #
347 # Description:
348 #
349 # GDB calls this indirectly (through gdbtk_tcl_breakpoint) to insert a
350 # breakpoint tag into window WIN at line LINE.
351 #
352
353 proc insert_breakpoint_tag {win line} {
354 $win configure -state normal
355 $win delete $line.0
356 $win insert $line.0 "B"
357 $win tag add $line $line.0
358 $win tag add delete $line.0 "$line.0 lineend"
359 $win tag add margin $line.0 "$line.0 lineend"
360
361 $win configure -state disabled
362 }
363
364 #
365 # Local procedure:
366 #
367 # delete_breakpoint_tag (win line) - Remove a breakpoint tag from WIN.
368 #
369 # Description:
370 #
371 # GDB calls this indirectly (through gdbtk_tcl_breakpoint) to remove a
372 # breakpoint tag from window WIN at line LINE.
373 #
374
375 proc delete_breakpoint_tag {win line} {
376 $win configure -state normal
377 $win delete $line.0
378 if {[string range $win 0 3] == ".src"} then {
379 $win insert $line.0 "\xa4"
380 } else {
381 $win insert $line.0 " "
382 }
383 $win tag delete $line
384 $win tag add delete $line.0 "$line.0 lineend"
385 $win tag add margin $line.0 "$line.0 lineend"
386 $win configure -state disabled
387 }
388
389 proc gdbtk_tcl_busy {} {
390 if [winfo exists .src] {
391 catch {.src.start configure -state disabled}
392 catch {.src.stop configure -state normal}
393 catch {.src.step configure -state disabled}
394 catch {.src.next configure -state disabled}
395 catch {.src.continue configure -state disabled}
396 catch {.src.finish configure -state disabled}
397 catch {.src.up configure -state disabled}
398 catch {.src.down configure -state disabled}
399 catch {.src.bottom configure -state disabled}
400 }
401 if [winfo exists .asm] {
402 catch {.asm.stepi configure -state disabled}
403 catch {.asm.nexti configure -state disabled}
404 catch {.asm.continue configure -state disabled}
405 catch {.asm.finish configure -state disabled}
406 catch {.asm.up configure -state disabled}
407 catch {.asm.down configure -state disabled}
408 catch {.asm.bottom configure -state disabled}
409 catch {.asm.close configure -state disabled}
410 }
411 }
412
413 proc gdbtk_tcl_idle {} {
414 if [winfo exists .src] {
415 catch {.src.start configure -state normal}
416 catch {.src.stop configure -state disabled}
417 catch {.src.step configure -state normal}
418 catch {.src.next configure -state normal}
419 catch {.src.continue configure -state normal}
420 catch {.src.finish configure -state normal}
421 catch {.src.up configure -state normal}
422 catch {.src.down configure -state normal}
423 catch {.src.bottom configure -state normal}
424 }
425
426 if [winfo exists .asm] {
427 catch {.asm.stepi configure -state normal}
428 catch {.asm.nexti configure -state normal}
429 catch {.asm.continue configure -state normal}
430 catch {.asm.finish configure -state normal}
431 catch {.asm.up configure -state normal}
432 catch {.asm.down configure -state normal}
433 catch {.asm.bottom configure -state normal}
434 catch {.asm.close configure -state normal}
435 }
436 }
437
438 #
439 # Local procedure:
440 #
441 # decr (var val) - compliment to incr
442 #
443 # Description:
444 #
445 #
446 proc decr {var {val 1}} {
447 upvar $var num
448 set num [expr $num - $val]
449 return $num
450 }
451
452 #
453 # Local procedure:
454 #
455 # pc_to_line (pclist pc) - convert PC to a line number.
456 #
457 # Description:
458 #
459 # Convert PC to a line number from PCLIST. If exact line isn't found,
460 # we return the first line that starts before PC.
461 #
462 proc pc_to_line {pclist pc} {
463 set line [lsearch -exact $pclist $pc]
464
465 if {$line >= 1} { return $line }
466
467 set line 1
468 foreach linepc [lrange $pclist 1 end] {
469 if {$pc < $linepc} { decr line ; return $line }
470 incr line
471 }
472 return [expr $line - 1]
473 }
474
475 #
476 # Menu:
477 #
478 # file popup menu - Define the file popup menu.
479 #
480 # Description:
481 #
482 # This menu just contains a bunch of buttons that do various things to
483 # the line under the cursor.
484 #
485 # Items:
486 #
487 # Edit - Run the editor (specified by the environment variable EDITOR) on
488 # this file, at the current line.
489 # Breakpoint - Set a breakpoint at the current line. This just shoves
490 # a `break' command at GDB with the appropriate file and line
491 # number. Eventually, GDB calls us back (at gdbtk_tcl_breakpoint)
492 # to notify us of where the breakpoint needs to show up.
493 #
494
495 menu .file_popup -cursor hand2
496 .file_popup add command -label "Not yet set" -state disabled
497 .file_popup add separator
498 .file_popup add command -label "Edit" -command {exec $editor +$selected_line $selected_file &}
499 .file_popup add command -label "Set breakpoint" -command {gdb_cmd "break $selected_file:$selected_line"}
500
501 #
502 # Bindings:
503 #
504 # file popup menu - Define the file popup menu bindings.
505 #
506 # Description:
507 #
508 # This defines the binding for the file popup menu. Currently, there is
509 # only one, which is activated when Button-1 is released. This causes
510 # the menu to be unposted, releases the grab for the menu, and then
511 # unhighlights the line under the cursor. After that, the selected menu
512 # item is invoked.
513 #
514
515 bind .file_popup <Any-ButtonRelease-1> {
516 global selected_win
517
518 # First, remove the menu, and release the pointer
519
520 .file_popup unpost
521 grab release .file_popup
522
523 # Unhighlight the selected line
524
525 $selected_win tag delete breaktag
526
527 # Actually invoke the menubutton here!
528
529 tk_invokeMenu %W
530 }
531
532 #
533 # Local procedure:
534 #
535 # file_popup_menu (win x y xrel yrel) - Popup the file popup menu.
536 #
537 # Description:
538 #
539 # This procedure is invoked as a result of a command binding in the
540 # listing window. It does several things:
541 # o - It highlights the line under the cursor.
542 # o - It pops up the file popup menu which is intended to do
543 # various things to the aforementioned line.
544 # o - Grabs the mouse for the file popup menu.
545 #
546
547 # Button 1 has been pressed in a listing window. Pop up a menu.
548
549 proc file_popup_menu {win x y xrel yrel} {
550 global wins
551 global win_to_file
552 global file_to_debug_file
553 global highlight
554 global selected_line
555 global selected_file
556 global selected_win
557
558 # Map TK window name back to file name.
559
560 set file $win_to_file($win)
561
562 set pos [$win index @$xrel,$yrel]
563
564 # Record selected file and line for menu button actions
565
566 set selected_file $file_to_debug_file($file)
567 set selected_line [lindex [split $pos .] 0]
568 set selected_win $win
569
570 # Highlight the selected line
571
572 eval $win tag config breaktag $highlight
573 $win tag add breaktag "$pos linestart" "$pos linestart + 1l"
574
575 # Post the menu near the pointer, (and grab it)
576
577 .file_popup entryconfigure 0 -label "$selected_file:$selected_line"
578 .file_popup post [expr $x-[winfo width .file_popup]/2] [expr $y-10]
579 grab .file_popup
580 }
581
582 #
583 # Local procedure:
584 #
585 # listing_window_button_1 (win x y xrel yrel) - Handle button 1 in listing window
586 #
587 # Description:
588 #
589 # This procedure is invoked as a result of holding down button 1 in the
590 # listing window. The action taken depends upon where the button was
591 # pressed. If it was in the left margin (the breakpoint column), it
592 # sets or clears a breakpoint. In the main text area, it will pop up a
593 # menu.
594 #
595
596 proc listing_window_button_1 {win x y xrel yrel} {
597 global wins
598 global win_to_file
599 global file_to_debug_file
600 global highlight
601 global selected_line
602 global selected_file
603 global selected_win
604 global pos_to_breakpoint
605
606 # Map TK window name back to file name.
607
608 set file $win_to_file($win)
609
610 set pos [split [$win index @$xrel,$yrel] .]
611
612 # Record selected file and line for menu button actions
613
614 set selected_file $file_to_debug_file($file)
615 set selected_line [lindex $pos 0]
616 set selected_col [lindex $pos 1]
617 set selected_win $win
618
619 # If we're in the margin, then toggle the breakpoint
620
621 if {$selected_col < 8} {
622 set pos_break $selected_file:$selected_line
623 set pos $file:$selected_line
624 set tmp pos_to_breakpoint($pos)
625 if [info exists $tmp] {
626 set bpnum [set $tmp]
627 gdb_cmd "delete $bpnum"
628 } else {
629 gdb_cmd "break $pos_break"
630 }
631 return
632 }
633
634 # Post the menu near the pointer, (and grab it)
635
636 .file_popup entryconfigure 0 -label "$selected_file:$selected_line"
637 .file_popup post [expr $x-[winfo width .file_popup]/2] [expr $y-10]
638 grab .file_popup
639 }
640
641 #
642 # Local procedure:
643 #
644 # asm_window_button_1 (win x y xrel yrel) - Handle button 1 in asm window
645 #
646 # Description:
647 #
648 # This procedure is invoked as a result of holding down button 1 in the
649 # assembly window. The action taken depends upon where the button was
650 # pressed. If it was in the left margin (the breakpoint column), it
651 # sets or clears a breakpoint. In the main text area, it will pop up a
652 # menu.
653 #
654
655 proc asm_window_button_1 {win x y xrel yrel} {
656 global wins
657 global win_to_file
658 global file_to_debug_file
659 global highlight
660 global selected_line
661 global selected_file
662 global selected_win
663 global pos_to_breakpoint
664 global pclist
665 global cfunc
666
667 set pos [split [$win index @$xrel,$yrel] .]
668
669 # Record selected file and line for menu button actions
670
671 set selected_line [lindex $pos 0]
672 set selected_col [lindex $pos 1]
673 set selected_win $win
674
675 # Figure out the PC
676
677 set pc [lindex $pclist($cfunc) $selected_line]
678
679 # If we're in the margin, then toggle the breakpoint
680
681 if {$selected_col < 11} {
682 set tmp pos_to_breakpoint($pc)
683 if [info exists $tmp] {
684 set bpnum [set $tmp]
685 gdb_cmd "delete $bpnum"
686 } else {
687 gdb_cmd "break *$pc"
688 }
689 return
690 }
691
692 # Post the menu near the pointer, (and grab it)
693
694 # .file_popup entryconfigure 0 -label "$selected_file:$selected_line"
695 # .file_popup post [expr $x-[winfo width .file_popup]/2] [expr $y-10]
696 # grab .file_popup
697 }
698
699 #
700 # Local procedure:
701 #
702 # do_nothing - Does absolutely nothing.
703 #
704 # Description:
705 #
706 # This procedure does nothing. It is used as a placeholder to allow
707 # the disabling of bindings that would normally be inherited from the
708 # parent widget. I can't think of any other way to do this.
709 #
710
711 proc do_nothing {} {}
712
713 #
714 # Local procedure:
715 #
716 # not_implemented_yet - warn that a feature is unavailable
717 #
718 # Description:
719 #
720 # This procedure warns that something doesn't actually work yet.
721 #
722
723 proc not_implemented_yet {message} {
724 tk_dialog .unimpl "gdb : unimpl" \
725 "$message: not implemented in the interface yet" \
726 {} 1 "OK"
727 }
728
729 ##
730 # Local procedure:
731 #
732 # create_expr_win - Create expression display window
733 #
734 # Description:
735 #
736 # Create the expression display window.
737 #
738
739 set expr_num 0
740
741 proc add_expr {expr} {
742 global expr_update_list
743 global expr_num
744
745 incr expr_num
746
747 set e .expr.e${expr_num}
748
749 frame $e
750
751 checkbutton $e.update -text " " -relief flat \
752 -variable expr_update_list($expr_num)
753 text $e.expr -width 20 -height 1
754 $e.expr insert 0.0 $expr
755 bind $e.expr <1> "update_expr $expr_num"
756 text $e.val -width 20 -height 1
757
758 update_expr $expr_num
759
760 pack $e.update -side left -anchor nw
761 pack $e.expr $e.val -side left -expand yes -fill x
762
763 pack $e -side top -fill x -anchor w
764 }
765
766 set delete_expr_flag 0
767
768 # This is a krock!!!
769
770 proc delete_expr {} {
771 global delete_expr_flag
772
773 if {$delete_expr_flag == 1} {
774 set delete_expr_flag 0
775 tk_butUp .expr.delete
776 bind .expr.delete <Any-Leave> {}
777 } else {
778 set delete_expr_flag 1
779 bind .expr.delete <Any-Leave> do_nothing
780 tk_butDown .expr.delete
781 }
782 }
783
784 proc update_expr {expr_num} {
785 global delete_expr_flag
786 global expr_update_list
787
788 set e .expr.e${expr_num}
789
790 if {$delete_expr_flag == 1} {
791 set delete_expr_flag 0
792 destroy $e
793 tk_butUp .expr.delete
794 tk_butLeave .expr.delete
795 bind .expr.delete <Any-Leave> {}
796 unset expr_update_list($expr_num)
797 return
798 }
799
800 set expr [$e.expr get 0.0 end]
801
802 $e.val delete 0.0 end
803 if [catch "gdb_eval $expr" val] {
804
805 } else {
806 $e.val insert 0.0 $val
807 }
808 }
809
810 proc update_exprs {} {
811 global expr_update_list
812
813 foreach expr_num [array names expr_update_list] {
814 if $expr_update_list($expr_num) {
815 update_expr $expr_num
816 }
817 }
818 }
819
820 proc create_expr_win {} {
821
822 if [winfo exists .expr] {raise .expr ; return}
823
824 toplevel .expr
825 wm minsize .expr 1 1
826 wm title .expr Expression
827 wm iconname .expr "Reg config"
828
829 frame .expr.entryframe
830
831 entry .expr.entry -borderwidth 2 -relief sunken
832 bind .expr <Enter> {focus .expr.entry}
833 bind .expr.entry <Key-Return> {add_expr [.expr.entry get]
834 .expr.entry delete 0 end }
835
836 label .expr.entrylab -text "Expression: "
837
838 pack .expr.entrylab -in .expr.entryframe -side left
839 pack .expr.entry -in .expr.entryframe -side left -fill x -expand yes
840
841 frame .expr.buts
842
843 button .expr.delete -text Delete
844 bind .expr.delete <1> delete_expr
845
846 button .expr.close -text Close -command {destroy .expr}
847
848 pack .expr.delete -side left -fill x -expand yes -in .expr.buts
849 pack .expr.close -side right -fill x -expand yes -in .expr.buts
850
851 pack .expr.buts -side bottom -fill x
852 pack .expr.entryframe -side bottom -fill x
853
854 frame .expr.labels
855
856 label .expr.updlab -text Update
857 label .expr.exprlab -text Expression
858 label .expr.vallab -text Value
859
860 pack .expr.updlab -side left -in .expr.labels
861 pack .expr.exprlab .expr.vallab -side left -in .expr.labels -expand yes -anchor w
862
863 pack .expr.labels -side top -fill x -anchor w
864 }
865
866 #
867 # Local procedure:
868 #
869 # display_expression (expression) - Display EXPRESSION in display window
870 #
871 # Description:
872 #
873 # Display EXPRESSION and its value in the expression display window.
874 #
875
876 proc display_expression {expression} {
877 create_expr_win
878
879 add_expr $expression
880 }
881
882 #
883 # Local procedure:
884 #
885 # create_file_win (filename) - Create a win for FILENAME.
886 #
887 # Return value:
888 #
889 # The new text widget.
890 #
891 # Description:
892 #
893 # This procedure creates a text widget for FILENAME. It returns the
894 # newly created widget. First, a text widget is created, and given basic
895 # configuration info. Second, all the bindings are setup. Third, the
896 # file FILENAME is read into the text widget. Fourth, margins and line
897 # numbers are added.
898 #
899
900 proc create_file_win {filename debug_file} {
901 global breakpoint_file
902 global breakpoint_line
903 global line_numbers
904
905 # Replace all the dirty characters in $filename with clean ones, and generate
906 # a unique name for the text widget.
907
908 regsub -all {\.} $filename {} temp
909 set win .src.text$temp
910
911 # Open the file, and read it into the text widget
912
913 if [catch "open $filename" fh] {
914 # File can't be read. Put error message into .src.nofile window and return.
915
916 catch {destroy .src.nofile}
917 text .src.nofile -height 25 -width 88 -relief raised \
918 -borderwidth 2 -yscrollcommand textscrollproc \
919 -setgrid true -cursor hand2
920 .src.nofile insert 0.0 $fh
921 .src.nofile configure -state disabled
922 bind .src.nofile <1> do_nothing
923 bind .src.nofile <B1-Motion> do_nothing
924 return .src.nofile
925 }
926
927 # Actually create and do basic configuration on the text widget.
928
929 text $win -height 25 -width 88 -relief raised -borderwidth 2 \
930 -yscrollcommand textscrollproc -setgrid true -cursor hand2
931
932 # Setup all the bindings
933
934 bind $win <Enter> {focus %W}
935 # bind $win <1> {listing_window_button_1 %W %X %Y %x %y}
936 bind $win <1> do_nothing
937 bind $win <B1-Motion> do_nothing
938
939 bind $win n {catch {gdb_cmd next} ; update_ptr}
940 bind $win s {catch {gdb_cmd step} ; update_ptr}
941 bind $win c {catch {gdb_cmd continue} ; update_ptr}
942 bind $win f {catch {gdb_cmd finish} ; update_ptr}
943 bind $win u {catch {gdb_cmd up} ; update_ptr}
944 bind $win d {catch {gdb_cmd down} ; update_ptr}
945
946 $win delete 0.0 end
947 $win insert 0.0 [read $fh]
948 close $fh
949
950 # Add margins (for annotations) and a line number to each line (if requested)
951
952 set numlines [$win index end]
953 set numlines [lindex [split $numlines .] 0]
954 if $line_numbers {
955 for {set i 1} {$i <= $numlines} {incr i} {
956 $win insert $i.0 [format " %4d " $i]
957 $win tag add source $i.8 "$i.0 lineend"
958 }
959 } else {
960 for {set i 1} {$i <= $numlines} {incr i} {
961 $win insert $i.0 " "
962 $win tag add source $i.8 "$i.0 lineend"
963 }
964 }
965
966 # Add the breakdots
967
968 foreach i [gdb_sourcelines $debug_file] {
969 $win delete $i.0
970 $win insert $i.0 "\xa4"
971 $win tag add margin $i.0 $i.8
972 }
973
974 $win tag bind margin <1> {listing_window_button_1 %W %X %Y %x %y}
975 $win tag bind source <1> {
976 %W mark set anchor "@%x,%y wordstart"
977 set last [%W index "@%x,%y wordend"]
978 %W tag remove sel 0.0 anchor
979 %W tag remove sel $last end
980 %W tag add sel anchor $last
981 }
982 # $win tag bind source <Double-Button-1> {
983 # %W mark set anchor "@%x,%y wordstart"
984 # set last [%W index "@%x,%y wordend"]
985 # %W tag remove sel 0.0 anchor
986 # %W tag remove sel $last end
987 # %W tag add sel anchor $last
988 # echo "Selected [selection get]"
989 # }
990 $win tag bind source <B1-Motion> {
991 %W tag remove sel 0.0 anchor
992 %W tag remove sel $last end
993 %W tag add sel anchor @%x,%y
994 }
995 $win tag bind sel <1> do_nothing
996 $win tag bind sel <Double-Button-1> {display_expression [selection get]}
997 $win tag raise sel
998
999
1000 # Scan though the breakpoint data base and install any destined for this file
1001
1002 foreach bpnum [array names breakpoint_file] {
1003 if {$breakpoint_file($bpnum) == $filename} {
1004 insert_breakpoint_tag $win $breakpoint_line($bpnum)
1005 }
1006 }
1007
1008 # Disable the text widget to prevent user modifications
1009
1010 $win configure -state disabled
1011 return $win
1012 }
1013
1014 #
1015 # Local procedure:
1016 #
1017 # create_asm_win (funcname pc) - Create an assembly win for FUNCNAME.
1018 #
1019 # Return value:
1020 #
1021 # The new text widget.
1022 #
1023 # Description:
1024 #
1025 # This procedure creates a text widget for FUNCNAME. It returns the
1026 # newly created widget. First, a text widget is created, and given basic
1027 # configuration info. Second, all the bindings are setup. Third, the
1028 # function FUNCNAME is read into the text widget.
1029 #
1030
1031 proc create_asm_win {funcname pc} {
1032 global breakpoint_file
1033 global breakpoint_line
1034 global current_output_win
1035 global pclist
1036 global disassemble_with_source
1037
1038 # Replace all the dirty characters in $filename with clean ones, and generate
1039 # a unique name for the text widget.
1040
1041 set win [asm_win_name $funcname]
1042
1043 # Actually create and do basic configuration on the text widget.
1044
1045 text $win -height 25 -width 80 -relief raised -borderwidth 2 \
1046 -setgrid true -cursor hand2 -yscrollcommand asmscrollproc
1047
1048 # Setup all the bindings
1049
1050 bind $win <Enter> {focus %W}
1051 bind $win <1> {asm_window_button_1 %W %X %Y %x %y}
1052 bind $win <B1-Motion> do_nothing
1053 bind $win n {catch {gdb_cmd nexti} ; update_ptr}
1054 bind $win s {catch {gdb_cmd stepi} ; update_ptr}
1055 bind $win c {catch {gdb_cmd continue} ; update_ptr}
1056 bind $win f {catch {gdb_cmd finish} ; update_ptr}
1057 bind $win u {catch {gdb_cmd up} ; update_ptr}
1058 bind $win d {catch {gdb_cmd down} ; update_ptr}
1059
1060 # Disassemble the code, and read it into the new text widget
1061
1062 set temp $current_output_win
1063 set current_output_win $win
1064 catch "gdb_disassemble $disassemble_with_source $pc"
1065 set current_output_win $temp
1066
1067 set numlines [$win index end]
1068 set numlines [lindex [split $numlines .] 0]
1069 decr numlines
1070
1071 # Delete the first and last lines, cuz these contain useless info
1072
1073 # $win delete 1.0 2.0
1074 # $win delete {end - 1 lines} end
1075 # decr numlines 2
1076
1077 # Add margins (for annotations) and note the PC for each line
1078
1079 catch "unset pclist($funcname)"
1080 lappend pclist($funcname) Unused
1081 for {set i 1} {$i <= $numlines} {incr i} {
1082 scan [$win get $i.0 "$i.0 lineend"] "%s " pc
1083 lappend pclist($funcname) $pc
1084 $win insert $i.0 " "
1085 }
1086
1087 # Scan though the breakpoint data base and install any destined for this file
1088
1089 # foreach bpnum [array names breakpoint_file] {
1090 # if {$breakpoint_file($bpnum) == $filename} {
1091 # insert_breakpoint_tag $win $breakpoint_line($bpnum)
1092 # }
1093 # }
1094
1095 # Disable the text widget to prevent user modifications
1096
1097 $win configure -state disabled
1098 return $win
1099 }
1100
1101 #
1102 # Local procedure:
1103 #
1104 # asmscrollproc (WINHEIGHT SCREENHEIGHT SCREENTOP SCREENBOT) - Update the
1105 # asm window scrollbar.
1106 #
1107 # Description:
1108 #
1109 # This procedure is called to update the assembler window's scrollbar.
1110 #
1111
1112 proc asmscrollproc {args} {
1113 global asm_screen_height asm_screen_top asm_screen_bot
1114
1115 eval ".asm.scroll set $args"
1116 set asm_screen_height [lindex $args 1]
1117 set asm_screen_top [lindex $args 2]
1118 set asm_screen_bot [lindex $args 3]
1119 }
1120
1121 #
1122 # Local procedure:
1123 #
1124 # update_listing (linespec) - Update the listing window according to
1125 # LINESPEC.
1126 #
1127 # Description:
1128 #
1129 # This procedure is called from various places to update the listing
1130 # window based on LINESPEC. It is usually invoked with the result of
1131 # gdb_loc.
1132 #
1133 # It will move the cursor, and scroll the text widget if necessary.
1134 # Also, it will switch to another text widget if necessary, and update
1135 # the label widget too.
1136 #
1137 # LINESPEC is a list of the form:
1138 #
1139 # { DEBUG_FILE FUNCNAME FILENAME LINE }, where:
1140 #
1141 # DEBUG_FILE - is the abbreviated form of the file name. This is usually
1142 # the file name string given to the cc command. This is
1143 # primarily needed for breakpoint commands, and when an
1144 # abbreviated for of the filename is desired.
1145 # FUNCNAME - is the name of the function.
1146 # FILENAME - is the fully qualified (absolute) file name. It is usually
1147 # the same as $PWD/$DEBUG_FILE, where PWD is the working dir
1148 # at the time the cc command was given. This is used to
1149 # actually locate the file to be displayed.
1150 # LINE - The line number to be displayed.
1151 #
1152 # Usually, this procedure will just move the cursor one line down to the
1153 # next line to be executed. However, if the cursor moves out of range
1154 # or into another file, it will scroll the text widget so that the line
1155 # of interest is in the middle of the viewable portion of the widget.
1156 #
1157
1158 proc update_listing {linespec} {
1159 global pointers
1160 global screen_height
1161 global screen_top
1162 global screen_bot
1163 global wins cfile
1164 global current_label
1165 global win_to_file
1166 global file_to_debug_file
1167 global .src.label
1168
1169 # Rip the linespec apart
1170
1171 set line [lindex $linespec 3]
1172 set filename [lindex $linespec 2]
1173 set funcname [lindex $linespec 1]
1174 set debug_file [lindex $linespec 0]
1175
1176 # Sometimes there's no source file for this location
1177
1178 if {$filename == ""} {set filename Blank}
1179
1180 # If we want to switch files, we need to unpack the current text widget, and
1181 # stick in the new one.
1182
1183 if {$filename != $cfile} then {
1184 pack forget $wins($cfile)
1185 set cfile $filename
1186
1187 # Create a text widget for this file if necessary
1188
1189 if ![info exists wins($cfile)] then {
1190 set wins($cfile) [create_file_win $cfile $debug_file]
1191 if {$wins($cfile) != ".src.nofile"} {
1192 set win_to_file($wins($cfile)) $cfile
1193 set file_to_debug_file($cfile) $debug_file
1194 set pointers($cfile) 1.1
1195 }
1196 }
1197
1198 # Pack the text widget into the listing widget, and scroll to the right place
1199
1200 pack $wins($cfile) -side left -expand yes -in .src.info \
1201 -fill both -after .src.scroll
1202
1203 # Make the scrollbar point at the new text widget
1204
1205 .src.scroll configure -command "$wins($cfile) yview"
1206
1207 $wins($cfile) yview [expr $line - $screen_height / 2]
1208 }
1209
1210 # Update the label widget in case the filename or function name has changed
1211
1212 if {$current_label != "$filename.$funcname"} then {
1213 set tail [expr [string last / $filename] + 1]
1214 set .src.label "[string range $filename $tail end] : ${funcname}()"
1215 # .src.label configure -text "[string range $filename $tail end] : ${funcname}()"
1216 set current_label $filename.$funcname
1217 }
1218
1219 # Update the pointer, scrolling the text widget if necessary to keep the
1220 # pointer in an acceptable part of the screen.
1221
1222 if [info exists pointers($cfile)] then {
1223 $wins($cfile) configure -state normal
1224 set pointer_pos $pointers($cfile)
1225 $wins($cfile) configure -state normal
1226 $wins($cfile) delete $pointer_pos "$pointer_pos + 2 char"
1227 $wins($cfile) insert $pointer_pos " "
1228
1229 set pointer_pos [$wins($cfile) index $line.1]
1230 set pointers($cfile) $pointer_pos
1231
1232 $wins($cfile) delete $pointer_pos "$pointer_pos + 2 char"
1233 $wins($cfile) insert $pointer_pos "->"
1234
1235 if {$line < $screen_top + 1
1236 || $line > $screen_bot} then {
1237 $wins($cfile) yview [expr $line - $screen_height / 2]
1238 }
1239
1240 $wins($cfile) configure -state disabled
1241 }
1242 }
1243
1244 #
1245 # Local procedure:
1246 #
1247 # create_asm_window - Open up the assembly window.
1248 #
1249 # Description:
1250 #
1251 # Create an assembly window if it doesn't exist.
1252 #
1253
1254 proc create_asm_window {} {
1255 global cfunc
1256
1257 if [winfo exists .asm] {raise .asm ; return}
1258
1259 set cfunc *None*
1260 set win [asm_win_name $cfunc]
1261
1262 build_framework .asm Assembly "*NIL*"
1263
1264 # First, delete all the old menu entries
1265
1266 .asm.menubar.view.menu delete 0 last
1267
1268 .asm.text configure -yscrollcommand asmscrollproc
1269
1270 frame .asm.row1
1271 frame .asm.row2
1272
1273 button .asm.stepi -width 6 -text Stepi \
1274 -command {catch {gdb_cmd stepi} ; update_ptr}
1275 button .asm.nexti -width 6 -text Nexti \
1276 -command {catch {gdb_cmd nexti} ; update_ptr}
1277 button .asm.continue -width 6 -text Cont \
1278 -command {catch {gdb_cmd continue} ; update_ptr}
1279 button .asm.finish -width 6 -text Finish \
1280 -command {catch {gdb_cmd finish} ; update_ptr}
1281 button .asm.up -width 6 -text Up -command {catch {gdb_cmd up} ; update_ptr}
1282 button .asm.down -width 6 -text Down \
1283 -command {catch {gdb_cmd down} ; update_ptr}
1284 button .asm.bottom -width 6 -text Bottom \
1285 -command {catch {gdb_cmd {frame 0}} ; update_ptr}
1286
1287 pack .asm.stepi .asm.continue .asm.up .asm.bottom -side left -padx 3 -pady 5 -in .asm.row1
1288 pack .asm.nexti .asm.finish .asm.down -side left -padx 3 -pady 5 -in .asm.row2
1289
1290 pack .asm.row2 .asm.row1 -side bottom -anchor w -before .asm.info
1291
1292 update
1293
1294 update_assembly [gdb_loc]
1295
1296 # We do this update_assembly to get the proper value of disassemble-from-exec.
1297
1298 # exec file menu item
1299 .asm.menubar.view.menu add radiobutton -label "Exec file" \
1300 -variable disassemble-from-exec -value 1
1301 # target memory menu item
1302 .asm.menubar.view.menu add radiobutton -label "Target memory" \
1303 -variable disassemble-from-exec -value 0
1304
1305 # Disassemble with source
1306 .asm.menubar.view.menu add checkbutton -label "Source" \
1307 -variable disassemble_with_source -onvalue source \
1308 -offvalue nosource -command {
1309 foreach asm [info command .asm.func_*] {
1310 destroy $asm
1311 }
1312 set cfunc NIL
1313 update_assembly [gdb_loc]
1314 }
1315 }
1316
1317 proc reg_config_menu {} {
1318 catch {destroy .reg.config}
1319 toplevel .reg.config
1320 wm geometry .reg.config +300+300
1321 wm title .reg.config "Register configuration"
1322 wm iconname .reg.config "Reg config"
1323 set regnames [gdb_regnames]
1324 set num_regs [llength $regnames]
1325
1326 frame .reg.config.buts
1327
1328 button .reg.config.done -text " Done " -command "
1329 recompute_reg_display_list $num_regs
1330 populate_reg_window
1331 update_registers all
1332 destroy .reg.config "
1333
1334 button .reg.config.update -text Update -command "
1335 recompute_reg_display_list $num_regs
1336 populate_reg_window
1337 update_registers all "
1338
1339 pack .reg.config.buts -side bottom -fill x
1340
1341 pack .reg.config.done -side left -fill x -expand yes -in .reg.config.buts
1342 pack .reg.config.update -side right -fill x -expand yes -in .reg.config.buts
1343
1344 # Since there can be lots of registers, we build the window with no more than
1345 # 32 rows, and as many columns as needed.
1346
1347 # First, figure out how many columns we need and create that many column frame
1348 # widgets
1349
1350 set ncols [expr ($num_regs + 31) / 32]
1351
1352 for {set col 0} {$col < $ncols} {incr col} {
1353 frame .reg.config.col$col
1354 pack .reg.config.col$col -side left -anchor n
1355 }
1356
1357 # Now, create the checkbutton widgets and pack them in the appropriate columns
1358
1359 set col 0
1360 set row 0
1361 for {set regnum 0} {$regnum < $num_regs} {incr regnum} {
1362 set regname [lindex $regnames $regnum]
1363 checkbutton .reg.config.col$col.$row -text $regname -pady 0 \
1364 -variable regena($regnum) -relief flat -anchor w -bd 1
1365
1366 pack .reg.config.col$col.$row -side top -fill both
1367
1368 incr row
1369 if {$row >= 32} {
1370 incr col
1371 set row 0
1372 }
1373 }
1374 }
1375
1376 #
1377 # Local procedure:
1378 #
1379 # create_registers_window - Open up the register display window.
1380 #
1381 # Description:
1382 #
1383 # Create the register display window, with automatic updates.
1384 #
1385
1386 proc create_registers_window {} {
1387 global reg_format
1388
1389 if [winfo exists .reg] {raise .reg ; return}
1390
1391 # Create an initial register display list consisting of all registers
1392
1393 if ![info exists reg_format] {
1394 global reg_display_list
1395 global changed_reg_list
1396 global regena
1397
1398 set reg_format {}
1399 set num_regs [llength [gdb_regnames]]
1400 for {set regnum 0} {$regnum < $num_regs} {incr regnum} {
1401 set regena($regnum) 1
1402 }
1403 recompute_reg_display_list $num_regs
1404 set changed_reg_list $reg_display_list
1405 }
1406
1407 build_framework .reg Registers
1408
1409 # First, delete all the old menu entries
1410
1411 .reg.menubar.view.menu delete 0 last
1412
1413 # Hex menu item
1414 .reg.menubar.view.menu add radiobutton -variable reg_format \
1415 -label Hex -value x -command {update_registers all}
1416
1417 # Decimal menu item
1418 .reg.menubar.view.menu add radiobutton -variable reg_format \
1419 -label Decimal -value d -command {update_registers all}
1420
1421 # Octal menu item
1422 .reg.menubar.view.menu add radiobutton -variable reg_format \
1423 -label Octal -value o -command {update_registers all}
1424
1425 # Natural menu item
1426 .reg.menubar.view.menu add radiobutton -variable reg_format \
1427 -label Natural -value {} -command {update_registers all}
1428
1429 # Config menu item
1430 .reg.menubar.view.menu add separator
1431
1432 .reg.menubar.view.menu add command -label Config -command {
1433 reg_config_menu }
1434
1435 destroy .reg.label
1436
1437 # Install the reg names
1438
1439 populate_reg_window
1440 update_registers all
1441 }
1442
1443 # Convert regena into a list of the enabled $regnums
1444
1445 proc recompute_reg_display_list {num_regs} {
1446 global reg_display_list
1447 global regmap
1448 global regena
1449
1450 catch {unset reg_display_list}
1451
1452 set line 1
1453 for {set regnum 0} {$regnum < $num_regs} {incr regnum} {
1454
1455 if {[set regena($regnum)] != 0} {
1456 lappend reg_display_list $regnum
1457 set regmap($regnum) $line
1458 incr line
1459 }
1460 }
1461 }
1462
1463 # Fill out the register window with the names of the regs specified in
1464 # reg_display_list.
1465
1466 proc populate_reg_window {} {
1467 global max_regname_width
1468 global reg_display_list
1469
1470 .reg.text configure -state normal
1471
1472 .reg.text delete 0.0 end
1473
1474 set regnames [eval gdb_regnames $reg_display_list]
1475
1476 # Figure out the longest register name
1477
1478 set max_regname_width 0
1479
1480 foreach reg $regnames {
1481 set len [string length $reg]
1482 if {$len > $max_regname_width} {set max_regname_width $len}
1483 }
1484
1485 set width [expr $max_regname_width + 15]
1486
1487 set height [llength $regnames]
1488
1489 if {$height > 60} {set height 60}
1490
1491 .reg.text configure -height $height -width $width
1492
1493 foreach reg $regnames {
1494 .reg.text insert end [format "%-*s \n" $max_regname_width ${reg}]
1495 }
1496
1497 .reg.text yview 0
1498 .reg.text configure -state disabled
1499 }
1500
1501 #
1502 # Local procedure:
1503 #
1504 # update_registers - Update the registers window.
1505 #
1506 # Description:
1507 #
1508 # This procedure updates the registers window.
1509 #
1510
1511 proc update_registers {which} {
1512 global max_regname_width
1513 global reg_format
1514 global reg_display_list
1515 global changed_reg_list
1516 global highlight
1517 global regmap
1518
1519 set margin [expr $max_regname_width + 1]
1520 set win .reg.text
1521 set winwidth [lindex [$win configure -width] 4]
1522 set valwidth [expr $winwidth - $margin]
1523
1524 $win configure -state normal
1525
1526 if {$which == "all"} {
1527 set lineindex 1
1528 foreach regnum $reg_display_list {
1529 set regval [gdb_fetch_registers $reg_format $regnum]
1530 set regval [format "%-*s" $valwidth $regval]
1531 $win delete $lineindex.$margin "$lineindex.0 lineend"
1532 $win insert $lineindex.$margin $regval
1533 incr lineindex
1534 }
1535 $win configure -state disabled
1536 return
1537 }
1538
1539 # Unhighlight the old values
1540
1541 foreach regnum $changed_reg_list {
1542 $win tag delete $win.$regnum
1543 }
1544
1545 # Now, highlight the changed values of the interesting registers
1546
1547 set changed_reg_list [eval gdb_changed_register_list $reg_display_list]
1548
1549 set lineindex 1
1550 foreach regnum $changed_reg_list {
1551 set regval [gdb_fetch_registers $reg_format $regnum]
1552 set regval [format "%-*s" $valwidth $regval]
1553
1554 set lineindex $regmap($regnum)
1555 $win delete $lineindex.$margin "$lineindex.0 lineend"
1556 $win insert $lineindex.$margin $regval
1557 $win tag add $win.$regnum $lineindex.0 "$lineindex.0 lineend"
1558 eval $win tag configure $win.$regnum $highlight
1559 }
1560
1561 $win configure -state disabled
1562 }
1563
1564 #
1565 # Local procedure:
1566 #
1567 # update_assembly - Update the assembly window.
1568 #
1569 # Description:
1570 #
1571 # This procedure updates the assembly window.
1572 #
1573
1574 proc update_assembly {linespec} {
1575 global asm_pointers
1576 global screen_height
1577 global screen_top
1578 global screen_bot
1579 global wins cfunc
1580 global current_label
1581 global win_to_file
1582 global file_to_debug_file
1583 global current_asm_label
1584 global pclist
1585 global asm_screen_height asm_screen_top asm_screen_bot
1586 global .asm.label
1587
1588 # Rip the linespec apart
1589
1590 set pc [lindex $linespec 4]
1591 set line [lindex $linespec 3]
1592 set filename [lindex $linespec 2]
1593 set funcname [lindex $linespec 1]
1594 set debug_file [lindex $linespec 0]
1595
1596 set win [asm_win_name $cfunc]
1597
1598 # Sometimes there's no source file for this location
1599
1600 if {$filename == ""} {set filename Blank}
1601
1602 # If we want to switch funcs, we need to unpack the current text widget, and
1603 # stick in the new one.
1604
1605 if {$funcname != $cfunc } {
1606 set oldwin $win
1607 set cfunc $funcname
1608
1609 set win [asm_win_name $cfunc]
1610
1611 # Create a text widget for this func if necessary
1612
1613 if {![winfo exists $win]} {
1614 create_asm_win $cfunc $pc
1615 set asm_pointers($cfunc) 1.1
1616 set current_asm_label NIL
1617 }
1618
1619 # Pack the text widget, and scroll to the right place
1620
1621 pack forget $oldwin
1622 pack $win -side left -expand yes -fill both \
1623 -after .asm.scroll
1624 .asm.scroll configure -command "$win yview"
1625 set line [pc_to_line $pclist($cfunc) $pc]
1626 update
1627 $win yview [expr $line - $asm_screen_height / 2]
1628 }
1629
1630 # Update the label widget in case the filename or function name has changed
1631
1632 if {$current_asm_label != "$pc $funcname"} then {
1633 set .asm.label "$pc $funcname"
1634 set current_asm_label "$pc $funcname"
1635 }
1636
1637 # Update the pointer, scrolling the text widget if necessary to keep the
1638 # pointer in an acceptable part of the screen.
1639
1640 if [info exists asm_pointers($cfunc)] then {
1641 $win configure -state normal
1642 set pointer_pos $asm_pointers($cfunc)
1643 $win configure -state normal
1644 $win delete $pointer_pos "$pointer_pos + 2 char"
1645 $win insert $pointer_pos " "
1646
1647 # Map the PC back to a line in the window
1648
1649 set line [pc_to_line $pclist($cfunc) $pc]
1650
1651 if {$line == -1} {
1652 echo "Can't find PC $pc"
1653 return
1654 }
1655
1656 set pointer_pos [$win index $line.1]
1657 set asm_pointers($cfunc) $pointer_pos
1658
1659 $win delete $pointer_pos "$pointer_pos + 2 char"
1660 $win insert $pointer_pos "->"
1661
1662 if {$line < $asm_screen_top + 1
1663 || $line > $asm_screen_bot} then {
1664 $win yview [expr $line - $asm_screen_height / 2]
1665 }
1666
1667 $win configure -state disabled
1668 }
1669 }
1670
1671 #
1672 # Local procedure:
1673 #
1674 # update_ptr - Update the listing window.
1675 #
1676 # Description:
1677 #
1678 # This routine will update the listing window using the result of
1679 # gdb_loc.
1680 #
1681
1682 proc update_ptr {} {
1683 update_listing [gdb_loc]
1684 if [winfo exists .asm] {
1685 update_assembly [gdb_loc]
1686 }
1687 if [winfo exists .reg] {
1688 update_registers changed
1689 }
1690 if [winfo exists .expr] {
1691 update_exprs
1692 }
1693 }
1694
1695 # Make toplevel window disappear
1696
1697 wm withdraw .
1698
1699 proc files_command {} {
1700 toplevel .files_window
1701
1702 wm minsize .files_window 1 1
1703 # wm overrideredirect .files_window true
1704 listbox .files_window.list -geometry 30x20 -setgrid true
1705 button .files_window.close -text Close -command {destroy .files_window}
1706 tk_listboxSingleSelect .files_window.list
1707 eval .files_window.list insert 0 [lsort [gdb_listfiles]]
1708 pack .files_window.list -side top -fill both -expand yes
1709 pack .files_window.close -side bottom -fill x -expand no -anchor s
1710 bind .files_window.list <Any-ButtonRelease-1> {
1711 set file [%W get [%W curselection]]
1712 gdb_cmd "list $file:1,0"
1713 update_listing [gdb_loc $file:1]
1714 destroy .files_window}
1715 }
1716
1717 button .files -text Files -command files_command
1718
1719 proc apply_filespec {label default command} {
1720 set filename [FSBox $label $default]
1721 if {$filename != ""} {
1722 if [catch {gdb_cmd "$command $filename"} retval] {
1723 tk_dialog .filespec_error "gdb : $label error" \
1724 "Error in command \"$command $filename\"" {} 0 Dismiss
1725 return
1726 }
1727 update_ptr
1728 }
1729 }
1730
1731 # Setup command window
1732
1733 proc build_framework {win {title GDBtk} {label {}}} {
1734 global ${win}.label
1735
1736 toplevel ${win}
1737 wm title ${win} $title
1738 wm minsize ${win} 1 1
1739
1740 frame ${win}.menubar
1741
1742 menubutton ${win}.menubar.file -padx 12 -text File \
1743 -menu ${win}.menubar.file.menu -underline 0
1744
1745 menu ${win}.menubar.file.menu
1746 ${win}.menubar.file.menu add command -label File... \
1747 -command {apply_filespec File a.out file}
1748 ${win}.menubar.file.menu add command -label Target... \
1749 -command { not_implemented_yet "target" }
1750 ${win}.menubar.file.menu add command -label Edit \
1751 -command {exec $editor +[expr ($screen_top + $screen_bot)/2] $cfile &}
1752 ${win}.menubar.file.menu add separator
1753 ${win}.menubar.file.menu add command -label "Exec File..." \
1754 -command {apply_filespec {Exec File} a.out exec-file}
1755 ${win}.menubar.file.menu add command -label "Symbol File..." \
1756 -command {apply_filespec {Symbol File} a.out symbol-file}
1757 ${win}.menubar.file.menu add command -label "Add Symbol File..." \
1758 -command { not_implemented_yet "menu item, add symbol file" }
1759 ${win}.menubar.file.menu add command -label "Core File..." \
1760 -command {apply_filespec {Core File} core core-file}
1761
1762 ${win}.menubar.file.menu add separator
1763 ${win}.menubar.file.menu add command -label Close \
1764 -command "destroy ${win}"
1765 ${win}.menubar.file.menu add separator
1766 ${win}.menubar.file.menu add command -label Quit \
1767 -command { catch { gdb_cmd quit } }
1768
1769 menubutton ${win}.menubar.commands -padx 12 -text Commands \
1770 -menu ${win}.menubar.commands.menu -underline 0
1771
1772 menu ${win}.menubar.commands.menu
1773 ${win}.menubar.commands.menu add command -label Run \
1774 -command { catch {gdb_cmd run } ; update_ptr }
1775 ${win}.menubar.commands.menu add command -label Step \
1776 -command { catch { gdb_cmd step } ; update_ptr }
1777 ${win}.menubar.commands.menu add command -label Next \
1778 -command { catch { gdb_cmd next } ; update_ptr }
1779 ${win}.menubar.commands.menu add command -label Continue \
1780 -command { catch { gdb_cmd continue } ; update_ptr }
1781 ${win}.menubar.commands.menu add separator
1782 ${win}.menubar.commands.menu add command -label Stepi \
1783 -command { catch { gdb_cmd stepi } ; update_ptr }
1784 ${win}.menubar.commands.menu add command -label Nexti \
1785 -command { catch { gdb_cmd nexti } ; update_ptr }
1786
1787 menubutton ${win}.menubar.view -padx 12 -text Options \
1788 -menu ${win}.menubar.view.menu -underline 0
1789
1790 menu ${win}.menubar.view.menu
1791 ${win}.menubar.view.menu add command -label Hex \
1792 -command {echo Hex}
1793 ${win}.menubar.view.menu add command -label Decimal \
1794 -command {echo Decimal}
1795 ${win}.menubar.view.menu add command -label Octal \
1796 -command {echo Octal}
1797
1798 menubutton ${win}.menubar.window -padx 12 -text Window \
1799 -menu ${win}.menubar.window.menu -underline 0
1800
1801 menu ${win}.menubar.window.menu
1802 ${win}.menubar.window.menu add command -label Command \
1803 -command create_command_window
1804 ${win}.menubar.window.menu add separator
1805 ${win}.menubar.window.menu add command -label Source \
1806 -command {create_source_window ; update_ptr}
1807 ${win}.menubar.window.menu add command -label Assembly \
1808 -command {create_asm_window ; update_ptr}
1809 ${win}.menubar.window.menu add separator
1810 ${win}.menubar.window.menu add command -label Registers \
1811 -command {create_registers_window ; update_ptr}
1812 ${win}.menubar.window.menu add command -label Expressions \
1813 -command {create_expr_win ; update_ptr}
1814
1815 # ${win}.menubar.window.menu add separator
1816 # ${win}.menubar.window.menu add command -label Files \
1817 # -command { not_implemented_yet "files window" }
1818
1819 menubutton ${win}.menubar.help -padx 12 -text Help \
1820 -menu ${win}.menubar.help.menu -underline 0
1821
1822 menu ${win}.menubar.help.menu
1823 ${win}.menubar.help.menu add command -label "with GDBtk" \
1824 -command {echo "with GDBtk"}
1825 ${win}.menubar.help.menu add command -label "with this window" \
1826 -command {echo "with this window"}
1827 ${win}.menubar.help.menu add command -label "Report bug" \
1828 -command {exec send-pr}
1829
1830 tk_menuBar ${win}.menubar \
1831 ${win}.menubar.file \
1832 ${win}.menubar.view \
1833 ${win}.menubar.window \
1834 ${win}.menubar.help
1835 pack ${win}.menubar.file \
1836 ${win}.menubar.view \
1837 ${win}.menubar.window -side left
1838 pack ${win}.menubar.help -side right
1839
1840 frame ${win}.info
1841 text ${win}.text -height 25 -width 80 -relief raised -borderwidth 2 \
1842 -setgrid true -cursor hand2 -yscrollcommand "${win}.scroll set"
1843
1844 set ${win}.label $label
1845 label ${win}.label -textvariable ${win}.label -borderwidth 2 -relief raised
1846
1847 scrollbar ${win}.scroll -orient vertical -command "${win}.text yview"
1848
1849 pack ${win}.label -side bottom -fill x -in ${win}.info
1850 pack ${win}.scroll -side right -fill y -in ${win}.info
1851 pack ${win}.text -side left -expand yes -fill both -in ${win}.info
1852
1853 pack ${win}.menubar -side top -fill x
1854 pack ${win}.info -side top -fill both -expand yes
1855 }
1856
1857 proc create_source_window {} {
1858 global wins
1859 global cfile
1860
1861 if [winfo exists .src] {raise .src ; return}
1862
1863 build_framework .src Source "*No file*"
1864
1865 # First, delete all the old view menu entries
1866
1867 .src.menubar.view.menu delete 0 last
1868
1869 # Source file selection
1870 .src.menubar.view.menu add command -label "Select source file" \
1871 -command files_command
1872
1873 # Line numbers enable/disable menu item
1874 .src.menubar.view.menu add checkbutton -variable line_numbers \
1875 -label "Line numbers" -onvalue 1 -offvalue 0 -command {
1876 foreach source [array names wins] {
1877 if {$source == "Blank"} continue
1878 destroy $wins($source)
1879 unset wins($source)
1880 }
1881 set cfile Blank
1882 update_listing [gdb_loc]
1883 }
1884
1885 frame .src.row1
1886 frame .src.row2
1887
1888 button .src.start -width 6 -text Start -command \
1889 {catch {gdb_cmd {break main}}
1890 catch {gdb_cmd {enable delete $bpnum}}
1891 catch {gdb_cmd run}
1892 update_ptr }
1893 button .src.stop -width 6 -text Stop -fg red -activeforeground red \
1894 -state disabled -command gdb_stop
1895 button .src.step -width 6 -text Step \
1896 -command {catch {gdb_cmd step} ; update_ptr}
1897 button .src.next -width 6 -text Next \
1898 -command {catch {gdb_cmd next} ; update_ptr}
1899 button .src.continue -width 6 -text Cont \
1900 -command {catch {gdb_cmd continue} ; update_ptr}
1901 button .src.finish -width 6 -text Finish \
1902 -command {catch {gdb_cmd finish} ; update_ptr}
1903 button .src.up -width 6 -text Up \
1904 -command {catch {gdb_cmd up} ; update_ptr}
1905 button .src.down -width 6 -text Down \
1906 -command {catch {gdb_cmd down} ; update_ptr}
1907 button .src.bottom -width 6 -text Bottom \
1908 -command {catch {gdb_cmd {frame 0}} ; update_ptr}
1909
1910 pack .src.start .src.step .src.continue .src.up .src.bottom \
1911 -side left -padx 3 -pady 5 -in .src.row1
1912 pack .src.stop .src.next .src.finish .src.down -side left -padx 3 \
1913 -pady 5 -in .src.row2
1914
1915 pack .src.row2 .src.row1 -side bottom -anchor w -before .src.info
1916
1917 $wins($cfile) insert 0.0 " This page intentionally left blank."
1918 $wins($cfile) configure -width 88 -state disabled \
1919 -yscrollcommand textscrollproc
1920
1921 proc textscrollproc {args} {global screen_height screen_top screen_bot
1922 eval ".src.scroll set $args"
1923 set screen_height [lindex $args 1]
1924 set screen_top [lindex $args 2]
1925 set screen_bot [lindex $args 3]}
1926 }
1927
1928 proc create_command_window {} {
1929 global command_line
1930
1931 if [winfo exists .cmd] {raise .cmd ; return}
1932
1933 build_framework .cmd Command "* Command Buffer *"
1934
1935 set command_line {}
1936
1937 gdb_cmd {set language c}
1938 gdb_cmd {set height 0}
1939 gdb_cmd {set width 0}
1940
1941 bind .cmd.text <Enter> {focus %W}
1942 bind .cmd.text <Delete> {delete_char %W}
1943 bind .cmd.text <BackSpace> {delete_char %W}
1944 bind .cmd.text <Control-u> {delete_line %W}
1945 bind .cmd.text <Any-Key> {
1946 global command_line
1947
1948 %W insert end %A
1949 %W yview -pickplace end
1950 append command_line %A
1951 }
1952 bind .cmd.text <Key-Return> {
1953 global command_line
1954
1955 %W insert end \n
1956 %W yview -pickplace end
1957 catch "gdb_cmd [list $command_line]"
1958 set command_line {}
1959 update_ptr
1960 %W insert end "(gdb) "
1961 %W yview -pickplace end
1962 }
1963 bind .cmd.text <Button-2> {
1964 global command_line
1965
1966 %W insert end [selection get]
1967 %W yview -pickplace end
1968 append command_line [selection get]
1969 }
1970 proc delete_char {win} {
1971 global command_line
1972
1973 tk_textBackspace $win
1974 $win yview -pickplace insert
1975 set tmp [expr [string length $command_line] - 2]
1976 set command_line [string range $command_line 0 $tmp]
1977 }
1978 proc delete_line {win} {
1979 global command_line
1980
1981 $win delete {end linestart + 6 chars} end
1982 $win yview -pickplace insert
1983 set command_line {}
1984 }
1985 }
1986
1987 #
1988 # fileselect.tcl --
1989 # simple file selector.
1990 #
1991 # Mario Jorge Silva msilva@cs.Berkeley.EDU
1992 # University of California Berkeley Ph: +1(510)642-8248
1993 # Computer Science Division, 571 Evans Hall Fax: +1(510)642-5775
1994 # Berkeley CA 94720
1995 #
1996 #
1997 # Copyright 1993 Regents of the University of California
1998 # Permission to use, copy, modify, and distribute this
1999 # software and its documentation for any purpose and without
2000 # fee is hereby granted, provided that this copyright
2001 # notice appears in all copies. The University of California
2002 # makes no representations about the suitability of this
2003 # software for any purpose. It is provided "as is" without
2004 # express or implied warranty.
2005 #
2006
2007
2008 # names starting with "fileselect" are reserved by this module
2009 # no other names used.
2010 # Hack - FSBox is defined instead of fileselect for backwards compatibility
2011
2012
2013 # this is the proc that creates the file selector box
2014 # purpose - comment string
2015 # defaultName - initial value for name
2016 # cmd - command to eval upon OK
2017 # errorHandler - command to eval upon Cancel
2018 # If neither cmd or errorHandler are specified, the return value
2019 # of the FSBox procedure is the selected file name.
2020
2021 proc FSBox {{purpose "Select file:"} {defaultName ""} {cmd ""} {errorHandler
2022 ""}} {
2023 global fileselect
2024 set w .fileSelect
2025 if [Exwin_Toplevel $w "Select File" FileSelect] {
2026 # path independent names for the widgets
2027
2028 set fileselect(list) $w.file.sframe.list
2029 set fileselect(scroll) $w.file.sframe.scroll
2030 set fileselect(direntry) $w.file.f1.direntry
2031 set fileselect(entry) $w.file.f2.entry
2032 set fileselect(ok) $w.but.ok
2033 set fileselect(cancel) $w.but.cancel
2034 set fileselect(msg) $w.label
2035
2036 set fileselect(result) "" ;# value to return if no callback procedures
2037
2038 # widgets
2039 Widget_Label $w label {top fillx pady 10 padx 20} -anchor w -width 24
2040 Widget_Frame $w file Dialog {left expand fill} -bd 10
2041
2042 Widget_Frame $w.file f1 Exmh {top fillx}
2043 Widget_Label $w.file.f1 label {left} -text "Dir"
2044 Widget_Entry $w.file.f1 direntry {right fillx expand} -width 30
2045
2046 Widget_Frame $w.file sframe
2047
2048 scrollbar $w.file.sframe.yscroll -relief sunken \
2049 -command [list $w.file.sframe.list yview]
2050 listbox $w.file.sframe.list -relief sunken \
2051 -yscroll [list $w.file.sframe.yscroll set] -setgrid 1
2052 pack append $w.file.sframe \
2053 $w.file.sframe.yscroll {right filly} \
2054 $w.file.sframe.list {left expand fill}
2055
2056 Widget_Frame $w.file f2 Exmh {top fillx}
2057 Widget_Label $w.file.f2 label {left} -text Name
2058 Widget_Entry $w.file.f2 entry {right fillx expand}
2059
2060 # buttons
2061 $w.but.quit configure -text Cancel \
2062 -command [list fileselect.cancel.cmd $w]
2063
2064 Widget_AddBut $w.but ok OK \
2065 [list fileselect.ok.cmd $w $cmd $errorHandler] {left padx 1}
2066
2067 Widget_AddBut $w.but list List \
2068 [list fileselect.list.cmd $w] {left padx 1}
2069 Widget_CheckBut $w.but listall "List all" fileselect(pattern)
2070 $w.but.listall configure -onvalue "{*,.*}" -offvalue "*" \
2071 -command {fileselect.list.cmd $fileselect(direntry)}
2072 $w.but.listall deselect
2073
2074 # Set up bindings for the browser.
2075 foreach ww [list $w $fileselect(entry)] {
2076 bind $ww <Return> [list $fileselect(ok) invoke]
2077 bind $ww <Control-c> [list $fileselect(cancel) invoke]
2078 }
2079 bind $fileselect(direntry) <Return> [list fileselect.list.cmd %W]
2080 bind $fileselect(direntry) <Tab> [list fileselect.tab.dircmd]
2081 bind $fileselect(entry) <Tab> [list fileselect.tab.filecmd]
2082
2083 tk_listboxSingleSelect $fileselect(list)
2084
2085
2086 bind $fileselect(list) <Button-1> {
2087 # puts stderr "button 1 release"
2088 %W select from [%W nearest %y]
2089 $fileselect(entry) delete 0 end
2090 $fileselect(entry) insert 0 [%W get [%W nearest %y]]
2091 }
2092
2093 bind $fileselect(list) <Key> {
2094 %W select from [%W nearest %y]
2095 $fileselect(entry) delete 0 end
2096 $fileselect(entry) insert 0 [%W get [%W nearest %y]]
2097 }
2098
2099 bind $fileselect(list) <Double-ButtonPress-1> {
2100 # puts stderr "double button 1"
2101 %W select from [%W nearest %y]
2102 $fileselect(entry) delete 0 end
2103 $fileselect(entry) insert 0 [%W get [%W nearest %y]]
2104 $fileselect(ok) invoke
2105 }
2106
2107 bind $fileselect(list) <Return> {
2108 %W select from [%W nearest %y]
2109 $fileselect(entry) delete 0 end
2110 $fileselect(entry) insert 0 [%W get [%W nearest %y]]
2111 $fileselect(ok) invoke
2112 }
2113 }
2114 set fileselect(text) $purpose
2115 $fileselect(msg) configure -text $purpose
2116 $fileselect(entry) delete 0 end
2117 $fileselect(entry) insert 0 [file tail $defaultName]
2118
2119 if {[info exists fileselect(lastDir)] && ![string length $defaultName]} {
2120 set dir $fileselect(lastDir)
2121 } else {
2122 set dir [file dirname $defaultName]
2123 }
2124 set fileselect(pwd) [pwd]
2125 fileselect.cd $dir
2126 $fileselect(direntry) delete 0 end
2127 $fileselect(direntry) insert 0 [pwd]/
2128
2129 $fileselect(list) delete 0 end
2130 $fileselect(list) insert 0 "Big directory:"
2131 $fileselect(list) insert 1 $dir
2132 $fileselect(list) insert 2 "Press Return for Listing"
2133
2134 fileselect.list.cmd $fileselect(direntry) startup
2135
2136 # set kbd focus to entry widget
2137
2138 # Exwin_ToplevelFocus $w $fileselect(entry)
2139
2140 # Wait for button hits if no callbacks are defined
2141
2142 if {"$cmd" == "" && "$errorHandler" == ""} {
2143 # wait for the box to be destroyed
2144 update idletask
2145 grab $w
2146 tkwait variable fileselect(result)
2147 grab release $w
2148
2149 set path $fileselect(result)
2150 set fileselect(lastDir) [pwd]
2151 fileselect.cd $fileselect(pwd)
2152 return [string trimright [string trim $path] /]
2153 }
2154 fileselect.cd $fileselect(pwd)
2155 return ""
2156 }
2157
2158 proc fileselect.cd { dir } {
2159 global fileselect
2160 if [catch {cd $dir} err] {
2161 fileselect.yck $dir
2162 cd
2163 }
2164 }
2165 # auxiliary button procedures
2166
2167 proc fileselect.yck { {tag {}} } {
2168 global fileselect
2169 $fileselect(msg) configure -text "Yck! $tag"
2170 }
2171 proc fileselect.ok {} {
2172 global fileselect
2173 $fileselect(msg) configure -text $fileselect(text)
2174 }
2175
2176 proc fileselect.cancel.cmd {w} {
2177 global fileselect
2178 set fileselect(result) {}
2179 destroy $w
2180 }
2181
2182 proc fileselect.list.cmd {w {state normal}} {
2183 global fileselect
2184 set seldir [$fileselect(direntry) get]
2185 if {[catch {glob $seldir} dir]} {
2186 fileselect.yck "glob failed"
2187 return
2188 }
2189 if {[llength $dir] > 1} {
2190 set dir [file dirname $seldir]
2191 set pat [file tail $seldir]
2192 } else {
2193 set pat $fileselect(pattern)
2194 }
2195 fileselect.ok
2196 update idletasks
2197 if [file isdirectory $dir] {
2198 fileselect.getfiles $dir $pat $state
2199 focus $fileselect(entry)
2200 } else {
2201 fileselect.yck "not a dir"
2202 }
2203 }
2204
2205 proc fileselect.ok.cmd {w cmd errorHandler} {
2206 global fileselect
2207 set selname [$fileselect(entry) get]
2208 set seldir [$fileselect(direntry) get]
2209
2210 if [string match /* $selname] {
2211 set selected $selname
2212 } else {
2213 if [string match ~* $selname] {
2214 set selected $selname
2215 } else {
2216 set selected $seldir/$selname
2217 }
2218 }
2219
2220 # some nasty file names may cause "file isdirectory" to return an error
2221 if [catch {file isdirectory $selected} isdir] {
2222 fileselect.yck "isdirectory failed"
2223 return
2224 }
2225 if [catch {glob $selected} globlist] {
2226 if ![file isdirectory [file dirname $selected]] {
2227 fileselect.yck "bad pathname"
2228 return
2229 }
2230 set globlist $selected
2231 }
2232 fileselect.ok
2233 update idletasks
2234
2235 if {[llength $globlist] > 1} {
2236 set dir [file dirname $selected]
2237 set pat [file tail $selected]
2238 fileselect.getfiles $dir $pat
2239 return
2240 } else {
2241 set selected $globlist
2242 }
2243 if [file isdirectory $selected] {
2244 fileselect.getfiles $selected $fileselect(pattern)
2245 $fileselect(entry) delete 0 end
2246 return
2247 }
2248
2249 if {$cmd != {}} {
2250 $cmd $selected
2251 } else {
2252 set fileselect(result) $selected
2253 }
2254 destroy $w
2255 }
2256
2257 proc fileselect.getfiles { dir {pat *} {state normal} } {
2258 global fileselect
2259 $fileselect(msg) configure -text Listing...
2260 update idletasks
2261
2262 set currentDir [pwd]
2263 fileselect.cd $dir
2264 if [catch {set files [lsort [glob -nocomplain $pat]]} err] {
2265 $fileselect(msg) configure -text $err
2266 $fileselect(list) delete 0 end
2267 update idletasks
2268 return
2269 }
2270 switch -- $state {
2271 normal {
2272 # Normal case - show current directory
2273 $fileselect(direntry) delete 0 end
2274 $fileselect(direntry) insert 0 [pwd]/
2275 }
2276 opt {
2277 # Directory already OK (tab related)
2278 }
2279 newdir {
2280 # Changing directory (tab related)
2281 fileselect.cd $currentDir
2282 }
2283 startup {
2284 # Avoid listing huge directories upon startup.
2285 $fileselect(direntry) delete 0 end
2286 $fileselect(direntry) insert 0 [pwd]/
2287 if {[llength $files] > 32} {
2288 fileselect.ok
2289 return
2290 }
2291 }
2292 }
2293
2294 # build a reordered list of the files: directories are displayed first
2295 # and marked with a trailing "/"
2296 if [string compare $dir /] {
2297 fileselect.putfiles $files [expr {($pat == "*") ? 1 : 0}]
2298 } else {
2299 fileselect.putfiles $files
2300 }
2301 fileselect.ok
2302 }
2303
2304 proc fileselect.putfiles {files {dotdot 0} } {
2305 global fileselect
2306
2307 $fileselect(list) delete 0 end
2308 if {$dotdot} {
2309 $fileselect(list) insert end "../"
2310 }
2311 foreach i $files {
2312 if {[file isdirectory $i]} {
2313 $fileselect(list) insert end $i/
2314 } else {
2315 $fileselect(list) insert end $i
2316 }
2317 }
2318 }
2319
2320 proc FileExistsDialog { name } {
2321 set w .fileExists
2322 global fileExists
2323 set fileExists(ok) 0
2324 {
2325 message $w.msg -aspect 1000
2326 pack $w.msg -side top -fill both -padx 20 -pady 20
2327 $w.but.quit config -text Cancel -command {FileExistsCancel}
2328 button $w.but.ok -text OK -command {FileExistsOK}
2329 pack $w.but.ok -side left
2330 bind $w.msg <Return> {FileExistsOK}
2331 }
2332 $w.msg config -text "Warning: file exists
2333 $name
2334 OK to overwrite it?"
2335
2336 set fileExists(focus) [focus]
2337 focus $w.msg
2338 grab $w
2339 tkwait variable fileExists(ok)
2340 grab release $w
2341 destroy $w
2342 return $fileExists(ok)
2343 }
2344 proc FileExistsCancel {} {
2345 global fileExists
2346 set fileExists(ok) 0
2347 }
2348 proc FileExistsOK {} {
2349 global fileExists
2350 set fileExists(ok) 1
2351 }
2352
2353 proc fileselect.getfiledir { dir {basedir [pwd]} } {
2354 global fileselect
2355
2356 set path [$fileselect(direntry) get]
2357 set returnList {}
2358
2359 if {$dir != 0} {
2360 if {[string index $path 0] == "~"} {
2361 set path $path/
2362 }
2363 } else {
2364 set path [$fileselect(entry) get]
2365 }
2366 if [catch {set listFile [glob -nocomplain $path*]}] {
2367 return $returnList
2368 }
2369 foreach el $listFile {
2370 if {$dir != 0} {
2371 if [file isdirectory $el] {
2372 lappend returnList [file tail $el]
2373 }
2374 } elseif ![file isdirectory $el] {
2375 lappend returnList [file tail $el]
2376 }
2377 }
2378
2379 return $returnList
2380 }
2381
2382 proc fileselect.gethead { list } {
2383 set returnHead ""
2384
2385 for {set i 0} {[string length [lindex $list 0]] > $i}\
2386 {incr i; set returnHead $returnHead$thisChar} {
2387 set thisChar [string index [lindex $list 0] $i]
2388 foreach el $list {
2389 if {[string length $el] < $i} {
2390 return $returnHead
2391 }
2392 if {$thisChar != [string index $el $i]} {
2393 return $returnHead
2394 }
2395 }
2396 }
2397 return $returnHead
2398 }
2399
2400 proc fileselect.expand.tilde { } {
2401 global fileselect
2402
2403 set entry [$fileselect(direntry) get]
2404 set dir [string range $entry 1 [string length $entry]]
2405
2406 if {$dir == ""} {
2407 return
2408 }
2409
2410 set listmatch {}
2411
2412 ## look in /etc/passwd
2413 if [file exists /etc/passwd] {
2414 if [catch {set users [exec cat /etc/passwd | sed s/:.*//]} err] {
2415 puts "Error\#1 $err"
2416 return
2417 }
2418 set list [split $users "\n"]
2419 }
2420 if {[lsearch -exact $list "+"] != -1} {
2421 if [catch {set users [exec ypcat passwd | sed s/:.*//]} err] {
2422 puts "Error\#2 $err"
2423 return
2424 }
2425 set list [concat $list [split $users "\n"]]
2426 }
2427 $fileselect(list) delete 0 end
2428 foreach el $list {
2429 if [string match $dir* $el] {
2430 lappend listmatch $el
2431 $fileselect(list) insert end $el
2432 }
2433 }
2434 set addings [fileselect.gethead $listmatch]
2435 if {$addings == ""} {
2436 return
2437 }
2438 $fileselect(direntry) delete 0 end
2439 if {[llength $listmatch] == 1} {
2440 $fileselect(direntry) insert 0 [file dirname ~$addings/]
2441 fileselect.getfiles [$fileselect(direntry) get]
2442 } else {
2443 $fileselect(direntry) insert 0 ~$addings
2444 }
2445 }
2446
2447 proc fileselect.tab.dircmd { } {
2448 global fileselect
2449
2450 set dir [$fileselect(direntry) get]
2451 if {$dir == ""} {
2452 $fileselect(direntry) delete 0 end
2453 $fileselect(direntry) insert 0 [pwd]
2454 if [string compare [pwd] "/"] {
2455 $fileselect(direntry) insert end /
2456 }
2457 return
2458 }
2459 if [catch {set tmp [file isdirectory [file dirname $dir]]}] {
2460 if {[string index $dir 0] == "~"} {
2461 fileselect.expand.tilde
2462 }
2463 return
2464 }
2465 if {!$tmp} {
2466 return
2467 }
2468 set dirFile [fileselect.getfiledir 1 $dir]
2469 if ![llength $dirFile] {
2470 return
2471 }
2472 if {[llength $dirFile] == 1} {
2473 $fileselect(direntry) delete 0 end
2474 $fileselect(direntry) insert 0 [file dirname $dir]
2475 if [string compare [file dirname $dir] /] {
2476 $fileselect(direntry) insert end /[lindex $dirFile 0]/
2477 } else {
2478 $fileselect(direntry) insert end [lindex $dirFile 0]/
2479 }
2480 fileselect.getfiles [$fileselect(direntry) get] \
2481 "[file tail [$fileselect(direntry) get]]$fileselect(pattern)" opt
2482 return
2483 }
2484 set headFile [fileselect.gethead $dirFile]
2485 $fileselect(direntry) delete 0 end
2486 $fileselect(direntry) insert 0 [file dirname $dir]
2487 if [string compare [file dirname $dir] /] {
2488 $fileselect(direntry) insert end /$headFile
2489 } else {
2490 $fileselect(direntry) insert end $headFile
2491 }
2492 if {$headFile == "" && [file isdirectory $dir]} {
2493 fileselect.getfiles $dir\
2494 "[file tail [$fileselect(direntry) get]]$fileselect(pattern)" opt
2495 } else {
2496 fileselect.getfiles [file dirname $dir]\
2497 "[file tail [$fileselect(direntry) get]]*" newdir
2498 }
2499 }
2500
2501 proc fileselect.tab.filecmd { } {
2502 global fileselect
2503
2504 set dir [$fileselect(direntry) get]
2505 if {$dir == ""} {
2506 set dir [pwd]
2507 }
2508 if {![file isdirectory $dir]} {
2509 error "dir $dir doesn't exist"
2510 }
2511 set listFile [fileselect.getfiledir 0 $dir]
2512 puts $listFile
2513 if ![llength $listFile] {
2514 return
2515 }
2516 if {[llength $listFile] == 1} {
2517 $fileselect(entry) delete 0 end
2518 $fileselect(entry) insert 0 [lindex $listFile 0]
2519 return
2520 }
2521 set headFile [fileselect.gethead $listFile]
2522 $fileselect(entry) delete 0 end
2523 $fileselect(entry) insert 0 $headFile
2524 fileselect.getfiles $dir "[$fileselect(entry) get]$fileselect(pattern)" opt
2525 }
2526
2527 proc Exwin_Toplevel { path name {class Dialog} {dismiss yes}} {
2528 global exwin
2529 if [catch {wm state $path} state] {
2530 set t [Widget_Toplevel $path $name $class]
2531 if ![info exists exwin(toplevels)] {
2532 set exwin(toplevels) [option get . exwinPaths {}]
2533 }
2534 set ix [lsearch $exwin(toplevels) $t]
2535 if {$ix < 0} {
2536 lappend exwin(toplevels) $t
2537 }
2538 if {$dismiss == "yes"} {
2539 set f [Widget_Frame $t but Menubar {top fill}]
2540 Widget_AddBut $f quit "Dismiss" [list Exwin_Dismiss $path]
2541 }
2542 return 1
2543 } else {
2544 if {$state != "normal"} {
2545 catch {
2546 wm geometry $path $exwin(geometry,$path)
2547 # Exmh_Debug Exwin_Toplevel $path $exwin(geometry,$path)
2548 }
2549 wm deiconify $path
2550 } else {
2551 catch {raise $path}
2552 }
2553 return 0
2554 }
2555 }
2556
2557 proc Exwin_Dismiss { path {geo ok} } {
2558 global exwin
2559 case $geo {
2560 "ok" {
2561 set exwin(geometry,$path) [wm geometry $path]
2562 }
2563 "nosize" {
2564 set exwin(geometry,$path) [string trimleft [wm geometry $path] 0123456789x]
2565 }
2566 default {
2567 catch {unset exwin(geometry,$path)}
2568 }
2569 }
2570 wm withdraw $path
2571 }
2572
2573 proc Widget_Toplevel { path name {class Dialog} {x {}} {y {}} } {
2574 set self [toplevel $path -class $class]
2575 set usergeo [option get $path position Position]
2576 if {$usergeo != {}} {
2577 if [catch {wm geometry $self $usergeo} err] {
2578 # Exmh_Debug Widget_Toplevel $self $usergeo => $err
2579 }
2580 } else {
2581 if {($x != {}) && ($y != {})} {
2582 # Exmh_Debug Event position $self +$x+$y
2583 wm geometry $self +$x+$y
2584 }
2585 }
2586 wm title $self $name
2587 wm group $self .
2588 return $self
2589 }
2590
2591 proc Widget_Frame {par child {class GDB} {where {top expand fill}} args } {
2592 if {$par == "."} {
2593 set self .$child
2594 } else {
2595 set self $par.$child
2596 }
2597 eval {frame $self -class $class} $args
2598 pack append $par $self $where
2599 return $self
2600 }
2601
2602 proc Widget_AddBut {par but txt cmd {where {right padx 1}} } {
2603 # Create a Packed button. Return the button pathname
2604 set cmd2 [list button $par.$but -text $txt -command $cmd]
2605 if [catch $cmd2 t] {
2606 puts stderr "Widget_AddBut (warning) $t"
2607 eval $cmd2 {-font fixed}
2608 }
2609 pack append $par $par.$but $where
2610 return $par.$but
2611 }
2612 proc Widget_CheckBut {par but txt var {where {right padx 1}} } {
2613 # Create a check button. Return the button pathname
2614 set cmd [list checkbutton $par.$but -text $txt -variable $var]
2615 if [catch $cmd t] {
2616 puts stderr "Widget_CheckBut (warning) $t"
2617 eval $cmd {-font fixed}
2618 }
2619 pack append $par $par.$but $where
2620 return $par.$but
2621 }
2622
2623 proc Widget_Label { frame {name label} {where {left fill}} args} {
2624 set cmd [list label $frame.$name ]
2625 if [catch [concat $cmd $args] t] {
2626 puts stderr "Widget_Label (warning) $t"
2627 eval $cmd $args {-font fixed}
2628 }
2629 pack append $frame $frame.$name $where
2630 return $frame.$name
2631 }
2632 proc Widget_Entry { frame {name entry} {where {left fill}} args} {
2633 set cmd [list entry $frame.$name ]
2634 if [catch [concat $cmd $args] t] {
2635 puts stderr "Widget_Entry (warning) $t"
2636 eval $cmd $args {-font fixed}
2637 }
2638 pack append $frame $frame.$name $where
2639 return $frame.$name
2640 }
2641
2642 # End of fileselect.tcl.
2643
2644 # Setup the initial windows
2645
2646 create_source_window
2647
2648 if {[tk colormodel .src.text] == "color"} {
2649 set highlight "-background red2 -borderwidth 2 -relief sunk"
2650 } else {
2651 set fg [lindex [.src.text config -foreground] 4]
2652 set bg [lindex [.src.text config -background] 4]
2653 set highlight "-foreground $bg -background $fg -borderwidth 0"
2654 }
2655
2656 create_command_window
2657
2658 # Create a copyright window
2659
2660 toplevel .c
2661 wm geometry .c +300+300
2662 wm overrideredirect .c true
2663
2664 text .t
2665 set temp $current_output_win
2666 set current_output_win .t
2667 gdb_cmd "show version"
2668 set current_output_win $temp
2669
2670 message .c.m -text [.t get 0.0 end] -aspect 500 -relief raised
2671 destroy .t
2672 pack .c.m
2673 bind .c.m <Leave> {destroy .c}
2674
2675 if [file exists ~/.gdbtkinit] {
2676 source ~/.gdbtkinit
2677 }
2678
2679 update
This page took 0.082343 seconds and 5 git commands to generate.