summaryrefslogtreecommitdiff
path: root/gdb/gdbtk/library/bpwin.itb
blob: 6ab96c71305c0062c49a80f9b182612725fd004b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
# Breakpoint window for Insight.
# Copyright 1997, 1998, 1999, 2001, 2002, 2003 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License (GPL) as published by
# the Free Software Foundation; either version 2 of the License, or (at
# your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.


# ------------------------------------------------------------------
#  CONSTRUCTOR:  create the main breakpoint window
# ------------------------------------------------------------------
itcl::body BpWin::constructor {args} {
  window_name "Breakpoints" "BPs"
  
  if {[pref getd gdb/bp/menu] != ""} {
    set mbar 0
  }
  set show_threads [pref get gdb/bp/show_threads]
  debug "Ready to build"
  build_win
  eval itk_initialize $args 

  # The scrolledframe uses a canvas, which doesn't properly
  # calculate an initial size, so we must set a default
  # window size here. ManagedWin could override this still
  # if there is a user preference for the geometry.
  wm geometry $_top 350x165
  debug "done building"
}

# ------------------------------------------------------------------
#  DESTRUCTOR:  destroy the breakpoint window
# ------------------------------------------------------------------
itcl::body BpWin::destructor {} {}


# ------------------------------------------------------------------
#  METHOD:  build_win - build the main breakpoint window
# ------------------------------------------------------------------
itcl::body BpWin::build_win {} {
  global _bp_en _bp_disp tcl_platform
  set bg1 $::Colors(bg)

  set hsmode dynamic
  set vsmode dynamic

  # FIXME: The iwidgets scrolled frame is pretty useless.
  # When we get BLT, use its hiertable to do this.
  itk_component add sframe {
    iwidgets::scrolledframe $itk_interior.sf \
      -hscrollmode $hsmode -vscrollmode $vsmode
  }

  set twin [$itk_component(sframe) childsite]

  # write header
  if {$tracepoints} {
    label $twin.num0 -text "Num" -relief raised -bd 2 -anchor center \
      -font global/fixed
  } 
  label $twin.thread0 -text "Thread" -relief raised -bd 2 -anchor center \
    -font global/fixed
  label $twin.addr0 -text "Address" -relief raised -bd 2 -anchor center \
    -font global/fixed
  label $twin.file0 -text "File" -relief raised -bd 2 -anchor center \
    -font global/fixed
  label $twin.line0 -text "Line" -relief raised -bd 2 -anchor center \
    -font global/fixed
  label $twin.func0 -text "Function" -relief raised -bd 2 -anchor center \
    -font global/fixed

  if {$tracepoints} {
    label $twin.pass0 -text "PassCount" -relief raised -borderwidth 2 \
      -anchor center -font global/fixed
    grid x $twin.num0 $twin.addr0 $twin.file0 $twin.line0 $twin.func0 $twin.pass0 \
      -sticky new
  } else {
    if {$show_threads} {
      grid x $twin.thread0 $twin.addr0 $twin.file0 $twin.line0 $twin.func0 -sticky new
      # Let the File and Function columns expand; no others.
      grid columnconfigure $twin 3 -weight 1
      grid columnconfigure $twin 5 -weight 1
    } else {
      grid x $twin.addr0 $twin.file0 $twin.line0 $twin.func0 -sticky new
      # Let the File and Function columns expand; no others.
      grid columnconfigure $twin 2 -weight 1
      grid columnconfigure $twin 4 -weight 1
    }
  }


  # The last row must always suck up all the leftover vertical
  # space.
  set next_row 1
  grid rowconfigure $twin $next_row -weight 1

  if { $mbar } {
    menu $itk_interior.m -tearoff 0
    [winfo toplevel $itk_interior] configure -menu $itk_interior.m
    if { $tracepoints == 0 } {
      $itk_interior.m add cascade -menu $itk_interior.m.bp -label "Breakpoint" -underline 0
    } else {
      $itk_interior.m add cascade -menu $itk_interior.m.bp -label "Tracepoint" -underline 0
    }
    set m [menu $itk_interior.m.bp]
    if { $tracepoints == 0 } {
      $m add radio -label "Normal" -variable _bp_disp($selected) \
	-value donttouch -underline 0 -state disabled
      $m add radio -label "Temporary" -variable _bp_disp($selected) \
	-value delete -underline 0 -state disabled
    } else {
      $m add command -label "Actions" -underline 0 -state disabled
    }

    $m add separator
    $m add radio -label "Enabled" -variable _bp_en($selected) -value 1 \
      -underline 0 -state disabled
    $m add radio -label "Disabled" -variable _bp_en($selected) -value 0 \
      -underline 0 -state disabled
    $m add separator
    $m add command -label "Remove" -underline 0 -state disabled
    $itk_interior.m add cascade -menu $itk_interior.m.all -label "Global" \
      -underline 0
    set m [menu $itk_interior.m.all]
    $m add check -label " Show Threads" \
      -variable [pref varname gdb/bp/show_threads] \
      -underline 1 -command "$this toggle_threads"
    $m add separator
    $m add command -label "Disable All" -underline 0 \
      -command "$this bp_all disable"
    $m add command -label "Enable All" -underline 0 \
      -command "$this bp_all enable"
    $m add separator
    $m add command -label "Remove All" -underline 0 \
      -command "$this bp_all delete"
    $m add separator
    $m add command -label "Store Breakpoints..." -underline 0 \
      -command [code $this bp_store]
    $m add command -label "Restore Breakpoints..." -underline 3 \
      -command [code $this bp_restore]
  }

  set Menu [menu $itk_interior.pop -tearoff 0]
  
  if { $tracepoints == 0 } {
    $Menu add radio -label "Normal" -variable _bp_disp($selected) \
      -value donttouch -underline 0
    $Menu add radio -label "Temporary" -variable _bp_disp($selected) \
      -value delete -underline 0
  } else {
    $Menu add command -label "Actions" -underline 0 
  }
  $Menu add separator
  $Menu add radio -label "Enabled" -variable _bp_en($selected) -value 1 -underline 0
  $Menu add radio -label "Disabled" -variable _bp_en($selected) -value 0 -underline 0
  $Menu add separator
  $Menu add command -label "Remove" -underline 0
  $Menu add cascade -menu $Menu.all -label "Global" -underline 0
  set m [menu $Menu.all]
  $m add check -label " Show Threads" -variable [pref varname gdb/bp/show_threads] \
    -underline 1 -command "$this toggle_threads"
  $m add separator
  $m add command -label "Disable All" -underline 0 -command "$this bp_all disable"
  $m add command -label "Enable All" -underline 0 -command "$this bp_all enable"
  $m add separator
  $m add command -label "Remove All" -underline 0 -command "$this bp_all delete"

  if { $tracepoints == 0 } {
    # insert all breakpoints
    foreach i [gdb_get_breakpoint_list] {
      set e [BreakpointEvent \#auto -action create -number $i]
      bp_add $e
      delete object $e
    }
  } else {
    # insert all tracepoints
    foreach i [gdb_get_tracepoint_list] {
      set e [TracepointEvent \#auto -action create -number $i]
      bp_add $e 1
      delete object $e
    }
  }

  pack $itk_component(sframe) -side left -expand true -fill both
}

# ------------------------------------------------------------------
#  METHOD:  bp_add - add a breakpoint entry
# ------------------------------------------------------------------
itcl::body BpWin::bp_add {bp_event {tracepoint 0}} {
  global _bp_en _bp_disp tcl_platform _files

  set number [$bp_event get number]
  set thread [$bp_event get thread]
  set disposition [$bp_event get disposition]
  set file [$bp_event get file]

  if {$tracepoint} {
    set diposition tracepoint
    set bptype tracepoint
  } else {
    set bptype breakpoint
  }

  debug "bp_add bpnum=$number thread=$thread show=$show_threads"
  set i $next_row
  set _bp_en($i) [$bp_event get enabled]
  set _bp_disp($i) $disposition
  set temp($i) ""
  switch $disposition {
    donttouch { set color [pref get gdb/src/bp_fg] }
    delete { 
      set color [pref get gdb/src/temp_bp_fg]
      set temp($i) delete
    }
    tracepoint {
      set color [pref get gdb/src/trace_fg]
    }
    default { set color yellow }
  }
  
  if {$thread != "-1"} {set color [pref get gdb/src/thread_fg]}

  if {$tcl_platform(platform) == "windows"} {
    checkbutton $twin.en$i -relief flat -variable _bp_en($i) \
      -activebackground $bg1 -command "$this bp_able $i" -fg $color 
  } else {
    checkbutton $twin.en$i -relief flat -variable _bp_en($i) \
      -command "$this bp_able $i" -activebackground $bg1 \
      -selectcolor $color -highlightbackground $bg1
  }

  if {$tracepoints} {
    label $twin.num$i -text "$number " -relief flat -anchor w -font global/fixed
  }
  label $twin.addr$i -text "[gdb_CA_to_TAS [$bp_event get address]] " -relief flat -anchor w -font global/fixed -bg $bg1
  if {[info exists _files(short,$file)]} {
    set file $_files(short,$file)
  } else {
    # FIXME.  Really need to do better than this.
    set file [::file tail $file]
  }
  if {$show_threads} {
    if {$thread == "-1"} {set thread "ALL"}
    label $twin.thread$i -text "$thread " -relief flat -anchor w -font global/fixed
  }
  label $twin.file$i -text "$file " -relief flat -anchor w -font global/fixed 
  label $twin.line$i -text "[$bp_event get line] " -relief flat -anchor w -font global/fixed
  label $twin.func$i -text "[$bp_event get function] " -relief flat -anchor w -font global/fixed 
  if {$tracepoints} {
    label $twin.pass$i -text "[$bp_event get pass_count] " -relief flat -anchor w -font global/fixed
  }

  if {$mbar} {
    set zz [list addr file func line]
    if {$tracepoints} {lappend zz num pass}
    if {$show_threads} {lappend zz thread}
    foreach thing $zz {
      bind $twin.${thing}${i} <1> "$this bp_select $i"
      bind $twin.${thing}${i} <Double-1> "$this goto_bp $i"
      bind $twin.${thing}${i} <3> [code $this _select_and_popup $i %X %Y]
    }
  }

  if {$tracepoints} {
    grid $twin.en$i $twin.num$i $twin.addr$i $twin.file$i $twin.line$i \
      $twin.func$i $twin.pass$i -sticky new -ipadx 4 -ipady 2
  } else {
    if {$show_threads} {
      grid $twin.en$i $twin.thread$i $twin.addr$i $twin.file$i $twin.line$i \
	$twin.func$i -sticky new -ipadx 4 -ipady 2
    } else {
      grid $twin.en$i $twin.addr$i $twin.file$i $twin.line$i \
	$twin.func$i -sticky new -ipadx 4 -ipady 2
    }
  }

  # This used to be the last row.  Fix it vertically again.
  grid rowconfigure $twin $i -weight 0

  set index_to_bpnum($i) $number
  set Index_to_bptype($i) $bptype
  incr i
  set next_row $i
  grid rowconfigure $twin $i -weight 1
}

# ------------------------------------------------------------------
#  METHOD:  bp_store - stores away the breakpoints in a file of gdb
#                      commands
# ------------------------------------------------------------------
itcl::body BpWin::bp_store {} {
  set out_file [tk_getSaveFile]
  if {$out_file == ""} {
    return
  }
  if {[catch {::open $out_file w} outH]} {
    tk_messageBox -message "Could not open $out_file: $outH"
    return
  }
  foreach breakpoint [gdb_get_breakpoint_list] {
    # This is an lassign
    foreach {file function line_no address type \
	       enable_p disp ignore cmds thread hit_count user_spec} \
      [gdb_get_breakpoint_info $breakpoint] {
	break
      }

    if {$user_spec != ""} {
      set bp_specifier $user_spec
    } elseif {$file != ""} {
      set filename [file tail $file]
      set bp_specifier $filename:$line_no
    } else {
      set bp_specifier *$address
    }

    # FIXME: doesn't handle watchpoints.
    if {[string compare $disp "delete"] == 0} {
      puts $outH "tbreak $bp_specifier"
    } else {
      puts $outH "break $bp_specifier"
    }
      
    if {!$enable_p} {
      puts $outH "disable \$bpnum"
    }
    if {$ignore > 0} {
      puts $outH "ignore \$bpnum $ignore"
    }
  }
  close $outH
}

# ------------------------------------------------------------------
#  METHOD:  bp_restore - restore the breakpoints from a file of gdb
#                      commands
# ------------------------------------------------------------------
itcl::body BpWin::bp_restore {} {
  set inH [tk_getOpenFile]
  if {$inH == ""} {
    return
  }
  bp_all delete
  if {[catch {gdb_cmd "source $inH"} err]} {
    tk_messageBox -message "Error sourcing in BP file $inH: \"$err\""
  }
}

# ------------------------------------------------------------------
#  METHOD:  bp_select - select a row in the grid
# ------------------------------------------------------------------
itcl::body BpWin::bp_select { r } {
  global _bp_en _bp_disp

  set zz [list addr file func line]
  if {$tracepoints} {lappend zz num pass}
  if {$show_threads} {lappend zz thread}
  
  if {$selected} {
    set i $selected
    
    foreach thing $zz {
      $twin.${thing}${i}  configure -fg $::Colors(fg) -bg $bg1
    }
  }

  # if we click on the same line, unselect it and return
  if {$selected == $r} {
    set selected 0

    if {$tracepoints == 0} {
      $itk_interior.m.bp entryconfigure "Normal" -state disabled
      $itk_interior.m.bp entryconfigure "Temporary" -state disabled
    } else {
      $itk_interior.m.bp entryconfigure "Actions" -state disabled
    }
    $itk_interior.m.bp entryconfigure "Enabled" -state disabled
    $itk_interior.m.bp entryconfigure "Disabled" -state disabled
    $itk_interior.m.bp entryconfigure "Remove" -state disabled
    
    return
  }

  foreach thing $zz {
    $twin.${thing}${r} configure -fg $::Colors(sfg) -bg $::Colors(sbg)
  }
  
  if {$tracepoints == 0} {
    $itk_interior.m.bp entryconfigure "Normal" -variable _bp_disp($r) \
      -command "$this bp_type $r" -state normal
    $itk_interior.m.bp entryconfigure "Temporary" -variable _bp_disp($r) \
      -command "$this bp_type $r" -state normal
    $Menu entryconfigure "Normal" -variable _bp_disp($r)      \
      -command "$this bp_type $r" -state normal
    $Menu entryconfigure "Temporary" -variable _bp_disp($r)      \
      -command "$this bp_type $r" -state normal
  } else {
    $itk_interior.m.bp entryconfigure "Actions" -command "$this get_actions $r" -state normal
    $Menu entryconfigure "Actions" -command "$this get_actions $r" -state normal
  }
  $itk_interior.m.bp entryconfigure "Enabled" -variable _bp_en($r)   \
    -command "$this bp_able $r" -state normal
  $itk_interior.m.bp entryconfigure "Disabled" -variable _bp_en($r)   \
    -command "$this bp_able $r" -state normal
  $itk_interior.m.bp entryconfigure "Remove" -command "$this bp_remove $r" -state normal
  $Menu entryconfigure "Enabled" -variable _bp_en($r)        \
    -command "$this bp_able $r" -state normal
  $Menu entryconfigure "Disabled" -variable _bp_en($r)        \
    -command "$this bp_able $r" -state normal
  $Menu entryconfigure "Remove" -command "$this bp_remove $r" -state normal
  
  set selected $r
}

# ------------------------------------------------------------------
#  NAME:         private method BpWin::_select_and_popup
#  DESCRIPTION:  Select the given breakpoint and popup the options
#                menu at the given location.
#
#  ARGUMENTS:    None
#  RETURNS:      Nothing
# ------------------------------------------------------------------
itcl::body BpWin::_select_and_popup {bp X Y} {
  if {$selected != $bp} {
    bp_select $bp
  }
  tk_popup $Menu $X $Y
}

# ------------------------------------------------------------------
#  METHOD:  bp_modify - modify a breakpoint entry
# ------------------------------------------------------------------
itcl::body BpWin::bp_modify {bp_event {tracepoint 0}} {
  global _bp_en _bp_disp tcl_platform _files

  set number [$bp_event get number]
  set thread [$bp_event get thread]
  set disposition [$bp_event get disposition]
  set file [$bp_event get file]

  if {$tracepoint} {
    set disposition tracepoint
    set bptype tracepoint
  } else {
    set bptype breakpoint
  }

  set found 0
  for {set i 1} {$i < $next_row} {incr i} {
    if { $number == $index_to_bpnum($i)
	 && "$Index_to_bptype($i)" == "$bptype"} {
      incr found
      break
    }
  }

  if {!$found} {
    debug "ERROR: breakpoint number $number not found!"
    return
  }

  if {$_bp_en($i) != [$bp_event get enabled]} {
    set _bp_en($i) [$bp_event get enabled]
  }

  if {$_bp_disp($i) != $disposition} {
    set _bp_disp($i) $disposition
  }

  switch $disposition {
    donttouch { set color [pref get gdb/src/bp_fg] }
    delete { 
      set color [pref get gdb/src/temp_bp_fg]
    }
    tracepoint { set color [pref get gdb/src/trace_fg] }
    default { set color yellow}
  }

  if {$thread != "-1"} {set color [pref get gdb/src/thread_fg]}

  if {$tcl_platform(platform) == "windows"} then {
    $twin.en$i configure -fg $color 
  } else {
    $twin.en$i configure -selectcolor $color
  }
  if {$tracepoints} {
    $twin.num$i configure  -text "$number "
  }
  $twin.addr$i configure -text "[gdb_CA_to_TAS [$bp_event get address]] "
  if {[info exists _files(short,$file)]} {
    set file $_files(short,$file)
  } else {
    # FIXME.  Really need to do better than this.
    set file [::file tail $file]
  }
  if {$show_threads} {
    if {$thread == "-1"} {set thread "ALL"}
    $twin.thread$i configure -text "$thread "
  }
  $twin.file$i configure -text "$file "
  $twin.line$i configure  -text "[$bp_event get line] "
  $twin.func$i configure  -text "[$bp_event get function] "
  if {$tracepoints} {
    $twin.pass$i configure  -text "[$bp_event get pass_count] "
  }
}

# ------------------------------------------------------------------
#  METHOD:  bp_able - enable/disable a breakpoint
# ------------------------------------------------------------------
itcl::body BpWin::bp_able { i } {
  global _bp_en
  
  bp_select $i

  switch $Index_to_bptype($i) {
    breakpoint {set type {}}
    tracepoint {set type "tracepoint"}
  }

  if {$_bp_en($i) == "1"} {
    set command "enable $type $temp($i) "
  } else {
    set command "disable $type "
  }

  append command  "$index_to_bpnum($i)"
  gdb_cmd "$command"
}

# ------------------------------------------------------------------
#  METHOD:  bp_remove - remove a breakpoint
# ------------------------------------------------------------------
itcl::body BpWin::bp_remove { i } {

  bp_select $i

  switch $Index_to_bptype($i) {
    breakpoint { set type {} }
    tracepoint { set type "tracepoint" }
  }

  gdb_cmd "delete $type $index_to_bpnum($i)"
}

# ------------------------------------------------------------------
#  METHOD:  bp_type - change the breakpoint type (disposition)
# ------------------------------------------------------------------
itcl::body BpWin::bp_type { i } {
  
  if {$Index_to_bptype($i) != "breakpoint"} {
    return
  }

  set bpnum $index_to_bpnum($i)
  #debug "bp_type $i $bpnum"
  set bpinfo [gdb_get_breakpoint_info $bpnum]
  lassign $bpinfo file func line pc type enabled disposition \
    ignore_count commands cond thread hit_count user_spec
  bp_select $i
  switch $disposition {
    delete {  
      gdb_cmd "delete $bpnum"
      gdb_cmd "break *$pc"
    }
    donttouch {
      gdb_cmd "delete $bpnum"
      gdb_cmd "tbreak *$pc"
    }
    default { debug "Unknown breakpoint disposition: $disposition" }
  }
}

# ------------------------------------------------------------------
#  METHOD:  bp_delete - delete a breakpoint
# ------------------------------------------------------------------
itcl::body BpWin::bp_delete {bp_event} {
  set number [$bp_event get number]
  for {set i 1} {$i < $next_row} {incr i} {
    if { $number == $index_to_bpnum($i) } {
      if {$tracepoints} {
	grid forget $twin.en$i $twin.num$i $twin.addr$i $twin.file$i \
	  $twin.line$i $twin.func$i $twin.pass$i
	destroy $twin.en$i $twin.num$i $twin.addr$i $twin.file$i \
	  $twin.line$i $twin.func$i $twin.pass$i
      } else {
	if {$show_threads} {
	  grid forget $twin.thread$i
	  destroy $twin.thread$i
	}
	grid forget $twin.en$i $twin.addr$i $twin.file$i $twin.line$i $twin.func$i
	destroy $twin.en$i $twin.addr$i $twin.file$i $twin.line$i $twin.func$i
      }
      if {$selected == $i} {
	set selected 0
      }
      return
    }
  }
}

# ------------------------------------------------------------------
#  PUBLIC METHOD:  breakpoint - Update widget when a breakpoint
#                   event is received from the backend.
# ------------------------------------------------------------------
itcl::body BpWin::breakpoint {bp_event} {

  set action [$bp_event get action]
  #debug "bp update $action [$bp_event get number] [$bp_event get type]"

  switch $action {
    modify  { bp_modify $bp_event 0 }
    create  { bp_add $bp_event 0 }
    delete  { bp_delete $bp_event }
    default { dbug E "Unknown breakpoint action: $action" }
  }
}

# ------------------------------------------------------------------
#  METHOD:  tracepoint - Update widget when a tracepoint event
#            is received from the backend.
# ------------------------------------------------------------------
itcl::body BpWin::tracepoint {tp_event} {

  set action [$tp_event get action]
  #debug "tp update $action [$tp_event get number]"

  switch $action {
    modify  { bp_modify $tp_event 1 }
    create  { bp_add $tp_event 1 }
    delete  { bp_delete $tp_event }
    default { dbug E "Unknown tracepoint action: $action" }
  }
}

# ------------------------------------------------------------------
#  METHOD:  bp_all - perform a command on all breakpoints
# ------------------------------------------------------------------
itcl::body BpWin::bp_all { command } {

  if {!$tracepoints} {
    # Do all breakpoints
    foreach bpnum [gdb_get_breakpoint_list] {
      if { $command == "enable"} {
	for {set i 1} {$i < $next_row} {incr i} {
	  if { $bpnum == $index_to_bpnum($i)
	       && "$Index_to_bptype($i)" == "breakpoint"} {
	    gdb_cmd "enable $temp($i) $bpnum"
	    break
	  }
	}
      } else {
	gdb_cmd "$command $bpnum"
      }
    }
  } else {
    # Do all tracepoints
    foreach bpnum [gdb_get_tracepoint_list] {
      if { $command == "enable"} {
	for {set i 1} {$i < $next_row} {incr i} {
	  if { $bpnum == $index_to_bpnum($i)
	       && "$Index_to_bptype($i)" == "tracepoint"} {
	    gdb_cmd "enable tracepoint $bpnum"
	    break
	  }
	}
      } else {
	gdb_cmd "$command tracepoint $bpnum"
      }
    }
  }
}

# ------------------------------------------------------------------
#  METHOD:  get_actions - pops up the add trace dialog on a selected 
#                         tracepoint
# ------------------------------------------------------------------
itcl::body BpWin::get_actions {bpnum} {
  set bpnum $index_to_bpnum($bpnum)
  set bpinfo [gdb_get_tracepoint_info $bpnum]
  lassign $bpinfo file func line pc enabled pass_count \
    step_count thread hit_count actions

  set filename [::file tail $file]
  ManagedWin::open TraceDlg -File $filename -Lines $line
}

# ------------------------------------------------------------------
#  METHOD:  toggle_threads - callback when show_threads is toggled
# ------------------------------------------------------------------
itcl::body BpWin::toggle_threads {} {
  set show_threads [pref get gdb/bp/show_threads]
  reconfig
}

# ------------------------------------------------------------------
#  METHOD:  reconfig - used when preferences change
# ------------------------------------------------------------------
itcl::body BpWin::reconfig {} {
  if {[winfo exists $itk_interior.f]} { destroy $itk_interior.f }
  if {[winfo exists $itk_interior.m]} { destroy $itk_interior.m }
  if {[winfo exists $itk_interior.sbox]} { destroy $itk_interior.sbox }
  if {[winfo exists $itk_interior.sf]} { destroy $itk_interior.sf }
  if {[winfo exists $itk_interior.pop]} { destroy $itk_interior.pop }
  build_win
}

# ------------------------------------------------------------------
#  METHOD:  goto_bp - show bp in source window
# ------------------------------------------------------------------
itcl::body BpWin::goto_bp {r} {
  set bpnum $index_to_bpnum($r)
  if {$tracepoints} {
    set bpinfo [gdb_get_tracepoint_info $bpnum]
  } else {
    set bpinfo [gdb_get_breakpoint_info $bpnum]
  }
  set pc [lindex $bpinfo 3]

  SrcWin::choose_and_display BROWSE_TAG [gdb_loc *$pc]
}