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