#   Copyright (C) 1987-2007 by Jeffery P. Hansen
#
#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License 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.
#
#   You should have received a copy of the GNU General Public License
#   along with this program; if not, write to the Free Software
#   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# Last edit by hansen on Sun Jan 28 20:17:55 2007
#

set find_type 3
set find_target ""

set clock_line_len	320.0


set edgat_wires {}
set edgat_wops {}
set edgat_dtype "huh?"
set edgat_type "huh?"
set edgat_name "huh?"
set edgat_hideName 1
set edgat_cpbreak 0
set edgat_anchor 0
set edgat_xpos 0
set edgat_ypos 0
set edgat_blockFunc "huh?"
set edgat_newBlock 0
set edgat_newPort 0
set edgat_geom "+0+0"
set ecpOmega 100
set ecpPhi 50
set ecpDuty 50
set edgat_switch 0
set edgat_extbar 0
set edgat_dip 0
set edgat_tap 0
set edgat_memFile ""
set edgat_ok 0
set edgat_commentLen 0
set edgat_dolink 0
set edgat_link ""
set edport_hidename 0

set edport_ok 0
set edport_idx 0
set edport_sig "huh"
set edport_port "huh"
set edport_basePort "huh"
set edport_type "huh"
set edport_bits "huh"

set clkFrame [list]

proc edgatPortView args {
  global edgatio_w

  eval "$edgatio_w.box.name.lb yview $args"
  eval "$edgatio_w.box.port.lb yview $args"
  eval "$edgatio_w.box.type.lb yview $args"
  eval "$edgatio_w.box.sizesb.lbsb.lb yview $args"
}

######################################################
#
# Count the number of ports in the variable port group
# of a gate.
#
proc edgat_count_var_ports {} {
  global edgatio_w

  set Q 0
  set X ""
  set B ""
  set N ""
  set L [$edgatio_w.box.name.lb size]
  for {set i 0} {$i < $L} {incr i} {
    set P [$edgatio_w.box.port.lb get $i]
    if {[regexp {^([A-Za-z]+)([0-9]+)$} $P X B N]} {
      incr Q
    }
  }
  return $Q
}

proc edgat_is_selected {} {
  global edgatio_w

  set sel ""
  catch { set sel [selection own] }
  if { $sel != "$edgatio_w.box.name.lb" && $sel != "$edgatio_w.box.port.lb"
       && $sel != "$edgatio_w.box.type.lb" && $sel != "$edgatio_w.box.sizesb.lbsb.lb" } {
    return 0
  }
  return 1
}


#############################################################################
#
# Return non-zero if ports can be added to this gate.
#
proc can_add_ports {} {
  global edgat_type

  if {[edgat_count_var_ports] > 0 && $edgat_type != "Module" } {
    return 1
  }
  return 0
}

#############################################################################
#
# Return non-zero if ports can be deleted from this gate.
#
proc can_del_ports {} {
  global edgat_type

  if {[edgat_count_var_ports] > 1 && $edgat_type != "Module" && [edgat_is_selected]} {
    return 1
  }

  return 0
}

#############################################################################
#
# Return non-zero if ports can be deleted from this gate.
#
proc can_edit_ports {} {
  return [edgat_is_selected]
}

#############################################################################
#
# Update selectability status of buttons
#
proc edgateUpdateButtons {} {
    global edgatio_w
    set can_add normal
    set can_edit normal
    set can_delete normal
    if {![can_edit_ports]} { set can_edit disabled }
    if {![can_add_ports]} { set can_add disabled }
    if {![can_del_ports]} { set can_delete disabled }

    $edgatio_w.but.edit configure -state $can_edit
    $edgatio_w.but.add  configure -state $can_add
    $edgatio_w.but.delete configure -state $can_delete
}

proc edgatAddPort {i name port type size} {
  global edgatio_w

  $edgatio_w.box.name.lb insert $i $name
  $edgatio_w.box.port.lb insert $i $port
  $edgatio_w.box.type.lb insert $i $type
  $edgatio_w.box.sizesb.lbsb.lb insert $i $size
  edgateUpdateButtons
}

proc edgatIOBoxReplace {i name port type size} {
  global edport_type
  global edgatio_w

  if { $name == "" || $name == "*unnamed*" } { 
    set name "*unnamed*"
  } elseif { ![regexp {^[A-Za-z0-9_]*$} $name] } {
    errmsg "Illegal signal name '$name'.  Please correct."
    return 0
  }

  if { $edport_type == "Module" } {
    if { $port == "" || $port == "*unnamed*" || ![regexp {^[A-Za-z0-9_]*$} $port] } {
      errmsg "Illegal port name '$port' for block."
      return 0
    }
  } else {
    if { $port == "" || $port == "*unnamed*" } { 
      set port "*unnamed*"
    } elseif { ![regexp {^[A-Za-z_]+[0-9_]*(:[A-Za-z_][A-Za-z_0-9]*)?$} $port] } {
      errmsg "Illegal port name '$port'.  Please correct."
      return 0
    }
  }

  if { ![regexp {^-?[0-9]+$} $size] } {
    errmsg "Bit size '$size' is not a number.  Please correct."
    return 0
  }
  if { $size < 1 || $size > 32 } {
    errmsg "Bit size must be between 1 and 32.  Please correct."
    return 0
  }

  $edgatio_w.box.name.lb delete $i
  $edgatio_w.box.port.lb delete $i
  $edgatio_w.box.type.lb delete $i
  $edgatio_w.box.sizesb.lbsb.lb delete $i

  $edgatio_w.box.name.lb insert $i $name
  $edgatio_w.box.port.lb insert $i $port
  $edgatio_w.box.type.lb insert $i $type
  $edgatio_w.box.sizesb.lbsb.lb insert $i $size

  edgateUpdateButtons

  return 1
}


proc portEditOK {inGateEdit} {
  global edport_idx edport_sig edport_port edport_basePort edport_type edport_bits edport_ok

  if { $inGateEdit } {
    if { [edgatIOBoxReplace $edport_idx $edport_sig "$edport_basePort$edport_port" $edport_type $edport_bits] } {
      destroy .edport 
    }
  } {
    set edport_ok 1
    destroy .edport 
  }
}

########################################
#
# Throw up a dialog box for changing port values
#
proc edgatPortEdit {inGateEdit pos} {
  global edport_idx edport_sig edport_basePort edport_port edport_type edport_bits edport_hidename
  global edgat_type edgat_wops edport_ok
  global edgatio_w

  if { $inGateEdit } {
    set sel ""
    catch { set sel [selection own] }

    if { $sel != "$edgatio_w.box.name.lb" && $sel != "$edgatio_w.box.port.lb"
      && $sel != "$edgatio_w.box.type.lb" && $sel != "$edgatio_w.box.sizesb.lbsb.lb" } {

      errmsg [m err.noport]
      return;
    }

    set edport_idx [$sel curselection] 
    set edport_sig  [$edgatio_w.box.name.lb get $edport_idx]
    set edport_port [$edgatio_w.box.port.lb get $edport_idx]
    set edport_type [$edgatio_w.box.type.lb get $edport_idx]
    set edport_bits [$edgatio_w.box.sizesb.lbsb.lb get $edport_idx]
  }

  set edport_ok 0
  set oldPort $edport_port
  set edport_hidename 1

  set p [string first ":" $edport_port]
  if { $p > 0 } {
    set edport_basePort [string range $edport_port 0 $p]
    set edport_port [string range $edport_port [expr $p + 1] end]
    set isBlock 1
  } {
    set edport_basePort ""
    set isBlock 0
  }

  toplevel .edport
  wm transient .edport .

  wm resizable .edport 0 0
  wm title .edport "TKGate: Port Parameters"

  wm geometry .edport $pos

  frame .edport.box -relief raised -bd 2
  label .edport.box.siglab  -text "[m db.gate.signam]:"
#  label .edport.box.hidenlab   -text "[m db.gate.hidenam]:"
  label .edport.box.portlab -text "[m db.gate.portnam]:"
  label .edport.box.iolab   -text "[m db.gate.iotype]:"
  label .edport.box.bitlab  -text "[m b.bitw]:"
  entry .edport.box.sig     -textvariable edport_sig
#  checkbutton .edport.box.hiden -variable edport_hidename
  entry .edport.box.port    -textvariable edport_port

  frame .edport.box.io
  radiobutton .edport.box.io.in -text [m b.in] -variable edport_type -value in
  radiobutton .edport.box.io.out -text [m b.out] -variable edport_type -value out
  radiobutton .edport.box.io.bdir -text [m b.inout] -variable edport_type -value inout
  pack .edport.box.io.in .edport.box.io.out .edport.box.io.bdir -side left

  entry .edport.box.bit     -textvariable edport_bits

  bind .edport.box.sig <KeyPress-Return> "portEditOK $inGateEdit"
  bind .edport.box.port <KeyPress-Return> "portEditOK $inGateEdit"
  bind .edport.box.bit <KeyPress-Return> "portEditOK $inGateEdit"

  if { !$isBlock && $inGateEdit } {
    .edport.box.io.in   configure -state disabled
    .edport.box.port    configure -state disabled
    .edport.box.io.out  configure -state disabled
    .edport.box.io.bdir configure -state disabled
  }

  grid .edport.box.siglab   -column 0 -row 0 -sticky e -padx 5 -pady 2
  grid .edport.box.sig      -column 1 -row 0 -sticky w -padx 5 -pady 2
#  grid .edport.box.hidenlab -column 0 -row 1 -sticky e -padx 5 -pady 2
#  grid .edport.box.hiden    -column 1 -row 1 -sticky w -padx 5 -pady 2
  grid .edport.box.portlab  -column 0 -row 2 -sticky e -padx 5 -pady 2
  grid .edport.box.port     -column 1 -row 2 -sticky w -padx 5 -pady 2
  grid .edport.box.iolab    -column 0 -row 3 -sticky e -padx 5 -pady 2
  grid .edport.box.io       -column 1 -row 3 -sticky w -padx 5 -pady 2
  grid .edport.box.bitlab   -column 0 -row 4 -sticky e -padx 5 -pady 2
  grid .edport.box.bit      -column 1 -row 4 -sticky w -padx 5 -pady 2

  frame  .edport.confirm -relief raised -bd 2
  button .edport.confirm.ok     -text [m b.ok] -command "portEditOK $inGateEdit"
  button .edport.confirm.cancel -text [m b.cancel] -command { destroy .edport }
  pack .edport.confirm.ok -side left -padx 5 -pady 5
  pack .edport.confirm.cancel -side right -padx 5 -pady 5

  pack .edport.box .edport.confirm -fill both

  if { $edport_sig == "*unnamed*" } {
    .edport.box.sig selection range 0 end
    .edport.box.sig icursor end
    focus .edport.box.sig
  }

  helpon .edport.box.siglab  [m ho.edgat.signam]
  helpon .edport.box.portlab [m ho.edgat.port]
  helpon .edport.box.iolab   [m ho.edgat.iolab]
  helpon .edport.box.bitlab  [m ho.edgat.bitlab]

  if { !$inGateEdit } {
    .edport.box.port selection range 0 end
    focus .edport.box.port
  }

  update
  grab set .edport
  tkwait window .edport
  grab release .edport

  if { $inGateEdit } {
    lappend edgat_wops [list edit $oldPort $edport_sig "$edport_basePort$edport_port" $edport_type $edport_bits ]
    edgatSaveWireList
  }

  return $edport_ok
}

proc edgatSaveWireList {} {
  global edgatio_w edgat_wires

  set edgat_wires {}
  set L [$edgatio_w.box.name.lb size]
  for {set i 0} {$i < $L} {incr i} {
    set N [$edgatio_w.box.name.lb get $i]
    set P [$edgatio_w.box.port.lb get $i]
    set T [$edgatio_w.box.type.lb get $i]
    set S [$edgatio_w.box.sizesb.lbsb.lb get $i]

    lappend edgat_wires [list $N $P $T $S]
  }
}

########################################
#
# Throw up a dialog box for a new signal, or issue
# an error if ports can not be added to the current
# gate.
#
proc edgatPortAdd {} {
  global edgat_wops
  global edgatio_w

  set Q -1
  set X ""
  set B ""
  set N ""
  set T ""
  set L [$edgatio_w.box.name.lb size]
  for {set i 0} {$i < $L} {incr i} {
    set P [$edgatio_w.box.port.lb get $i]
    if {[regexp {^([A-Za-z]+)([0-9]+)$} $P X B N]} {
      set T [$edgatio_w.box.type.lb get $i]
      set Q $i
    }
  }
  if { $Q < 0 } {
      errmsg [m err.badportadd]
    return
  }
  set N [expr $N + 1]
  incr Q
  edgatAddPort $Q "*unnamed*" $B$N $T 1
  selection clear
  $edgatio_w.box.name.lb selection set $Q

  lappend edgat_wops [list add $B]
  edgatPortEdit 1 [offsetgeometry .edgat 50 50 ]
}

########################################
#
# Throw up a dialog box to delete a port.  Issue an
# error if the port is undeletable.
#
proc edgatPortDelete {} {
  global edgat_wops
  global edgatio_w

  catch { set sel [selection own] }

  if { $sel != "$edgatio_w.box.name.lb" && $sel != "$edgatio_w.box.port.lb"
    && $sel != "$edgatio_w.box.type.lb" && $sel != "$edgatio_w.box.sizesb.lbsb.lb" } {

    errmsg [m err.noport] 
    return;
  }
  set edport_idx [$sel curselection] 

  set port [$edgatio_w.box.port.lb get $edport_idx]

  if {![regexp {^([A-Za-z]+)([0-9]+)$} $port X B N]} {
    errmsg [m err.badportdel]
    return
  }

  set X [$edgatio_w.box.port.lb get [expr $edport_idx + 1]]
  set Y ${B}1
  if { $N == 0 && $X != $Y } {
    errmsg [m err.badportdel]
    return
  }

  selection clear

  $edgatio_w.box.name.lb delete $edport_idx
  $edgatio_w.box.port.lb delete $edport_idx
  $edgatio_w.box.type.lb delete $edport_idx
  $edgatio_w.box.sizesb.lbsb.lb delete $edport_idx

  set L [$edgatio_w.box.port.lb size]
  set j 0
  for {set i 0} {$i < $L} {incr i} {
    set P [$edgatio_w.box.port.lb get $i]
    if {[regexp {^([A-Za-z]+)([0-9]+)$} $P X Bj Nj]} {
      $edgatio_w.box.port.lb delete $i
      $edgatio_w.box.port.lb insert $i $Bj$j
      incr j
    }
  }

  edgateUpdateButtons

  lappend edgat_wops [list delete $port]
  edgatSaveWireList
}

#################################################
#
# Select interval and total width from an omega value.
#
#     P		Power of ten >= to omega
#     Q		Normalized omega value
#     V         Size of interval
#
proc edgatChooseW {omega} {

  set omega [expr 1.2*$omega ]
  if { $omega < 10 } {set omega 10 }

  for {set P 1.0} {$P < $omega} {set P [expr $P * 10.0]} {}

  set Q [expr ($P - $omega)/$P ]

  if { $Q >= 0.8 } {
     set V $P*0.02
  } elseif { $Q >= 0.6 } {
     set V $P*0.05
  } else {
     set V $P*0.1
  }

  set W 0
  for {set I 0} { $W <= $omega } { incr I } {
    set W [expr int($I * $V) ]
  }
  set W [expr int($I * $V) ]

  return [list $I $W]
}

proc edgatClockFrame {w} {
  global ecpI ecpW clock_line_len

  $w.wave delete frame
  set clkFrame [list]
  for {set i 0} {$i <= $ecpI } {incr i} {
    set x [expr 15 + ($i)*$clock_line_len/$ecpI ]
    $w.wave create line ${x} 75 ${x} 85 -tag frame
    $w.wave create text ${x} 100 -text [expr $i*$ecpW/$ecpI ] -anchor s -tag frame
  }
}

########################################
#
# Update clock display from value change
#
proc edgatSetClockTrace {w} {
  global ecpl1 ecpl2 ecpl3 ecpl4 ecpl5
  global ecpE0 ecpE1 ecpE2
  $w.wave coords $ecpl1 $ecpE0  5 $ecpE0 75
  $w.wave coords $ecpl2 15     65 $ecpE1 65
  $w.wave coords $ecpl3 $ecpE1 65 $ecpE1 15
  $w.wave coords $ecpl4 $ecpE1 15 $ecpE2 15
  $w.wave coords $ecpl5 $ecpE2 15 $ecpE2 65
}

########################################
#
# Translate movement of a clock graph component to actual new positons
# and new parameter values.
#
#
proc edgatMoveClock {w x} {
  global ecpS ecpE0 ecpE1 ecpE2
  global ecpl1 ecpl2 ecpl3 ecpl4 ecpl5
  global ecpPhi ecpDuty ecpOmega ecpW clock_line_len

  trace vdelete ecpOmega w edgatClockPUpdate
  trace vdelete ecpPhi w edgatClockPUpdate
  trace vdelete ecpDuty w edgatClockPUpdate

  if { $ecpS == $ecpl1 } {
    set ecpE0 $x
    if { $ecpE0 < 15 }      { set ecpE0 15 }
    if { $ecpE0 >= $ecpE2 } { set ecpE0 $ecpE2 }
    set ecpPhi [expr 100*($ecpE0 - 15)/($ecpE2 - 15) ]
  } elseif { $ecpS == $ecpl3 } {
    set ecpE1 $x
    if { $ecpE1 <= 15 }     { set ecpE1 15 }
    if { $ecpE1 >= $ecpE2 } { set ecpE1 [expr $ecpE2 - 1] }
    set ecpDuty [expr 100*($ecpE1 - 15)/($ecpE2 - 15) ]
  } elseif { $ecpS == $ecpl5 } {
    set ecpE2 $x
    if { $ecpE2 <= $ecpE1 } { set ecpE2 [expr $ecpE1 + 1] }
    if { $ecpE2 <= $ecpE0 } { set ecpE2 [expr $ecpE0 + 1] }
    if { $ecpE2 >= [expr $clock_line_len + 15] }    { set ecpE2 [expr $clock_line_len + 15] }
    set ecpE0 [expr 15 + int($ecpPhi*($ecpE2-15.0)/100.0)]
    set ecpE1 [expr 15 + int($ecpDuty*($ecpE2-15.0)/100.0)]
    set ecpOmega [expr int($ecpW*($ecpE2 - 15)/$clock_line_len) ]
  }

  trace variable ecpOmega w edgatClockPUpdate
  trace variable ecpPhi w edgatClockPUpdate
  trace variable ecpDuty w edgatClockPUpdate

  edgatSetClockTrace $w
}


########################################
#
# Translate change in parameter values to change in graph
#
proc edgatClockPUpdate args {
  global ecpl1 ecpl2 ecpl3 ecpl4 ecpl5
  global ecpE0 ecpE1 ecpE2
  global ecpW ecpI ecpOmega ecpPhi ecpDuty
  global edgatclk_w clock_line_len

  catch {

    if { [scan $ecpPhi "%d" P] != 1 } { set P 0 }
    if { [scan $ecpDuty "%d" D] != 1 } { set D 50 }
    if { [scan $ecpOmega "%d" O] != 1 } { set O $ecpW }

    set IW [edgatChooseW $ecpOmega]
    set ecpI [lindex $IW 0]
    set ecpW [lindex $IW 1]

    if { $P <= 0 } { set P 0 }
    if { $P >= 99 } { set P 99 }
    if { $D <= 0 } { set D 1 }
    if { $D >= 99 } { set D 99 }
    if { $O <= 0 } { set O 1 }

    set X [expr $clock_line_len*$O/$ecpW ]

    set ecpE2 [expr 15 + $X ]
    set ecpE0 [expr 15 + $X*$P/100 ]
    set ecpE1 [expr 15 + $X*$D/100 ]

    edgatClockFrame $edgatclk_w
    edgatSetClockTrace $edgatclk_w
  }
}

########################################
#
# Clock parameter edit window
#
proc  edgatClockParms {w omega phi duty} {
  global ecpS ecpl1 ecpl2 ecpl3 ecpl4 ecpl5
  global ecpE0 ecpE1 ecpE2
  global ecpW ecpI ecpOmega ecpPhi ecpDuty
  global edgatclk_w clock_line_len

  set edgatclk_w $w

  set IW [edgatChooseW $omega]
  set ecpI [lindex $IW 0]
  set ecpW [lindex $IW 1]

  set ecpOmega $omega
  set ecpPhi $phi
  set ecpDuty $duty

  frame $edgatclk_w.cycle
  label $edgatclk_w.cycle.lab -text "[m db.gate.cyclew]: " -anchor e -width 18
  entry $edgatclk_w.cycle.ent -width 6 -textvariable ecpOmega
  pack $edgatclk_w.cycle.lab $edgatclk_w.cycle.ent -side left -pady 2

  frame $edgatclk_w.phase
  label $edgatclk_w.phase.lab -text "[m db.gate.phase](%): " -anchor e -width 18
  entry $edgatclk_w.phase.ent -width 6 -textvariable ecpPhi
  pack $edgatclk_w.phase.lab $edgatclk_w.phase.ent -side left -pady 2

  frame $edgatclk_w.duty
  label $edgatclk_w.duty.lab -text "[m db.gate.duty](%): " -anchor e -width 18
  entry $edgatclk_w.duty.ent -width 6 -textvariable ecpDuty
  pack $edgatclk_w.duty.lab $edgatclk_w.duty.ent -side left -pady 2

  bind $edgatclk_w.cycle.ent <KeyPress-Return> "edgatOK"
  bind $edgatclk_w.phase.ent <KeyPress-Return> "edgatOK"
  bind $edgatclk_w.duty.ent <KeyPress-Return> "edgatOK"

  canvas $edgatclk_w.wave -width [expr  $clock_line_len + 30] -height 110 -closeenough 5.0
  $edgatclk_w.wave create line 15 75 [expr $clock_line_len + 15] 75
  edgatClockFrame $w

  set ecpl1 [$edgatclk_w.wave create line 0 0 0 0 -tags edge ]
  set ecpl2 [$edgatclk_w.wave create line 0 0 0 0 ]
  set ecpl3 [$edgatclk_w.wave create line 0 0 0 0 -tags edge ]
  set ecpl4 [$edgatclk_w.wave create line 0 0 0 0 ]
  set ecpl5 [$edgatclk_w.wave create line 0 0 0 0 -tags edge ]

  edgatClockPUpdate

  $edgatclk_w.wave bind edge <Button-1> {
    set ecpS [$edgatclk_w.wave find withtag current]
  }
  $edgatclk_w.wave bind edge <B1-Motion> "edgatMoveClock $w %x"
  $edgatclk_w.wave bind edge <ButtonRelease-1> "edgatClockPUpdate"

  pack $edgatclk_w.wave 
  pack $edgatclk_w.cycle $edgatclk_w.phase $edgatclk_w.duty -anchor w

  pack $edgatclk_w -fill both -padx 5 -pady 20

  helpon $edgatclk_w.cycle.lab [m ho.edgat.cycle]
  helpon $edgatclk_w.phase.lab [m ho.edgat.phase]
  helpon $edgatclk_w.duty.lab [m ho.edgat.duty]
}

proc edgatIO {w} {
  global edgatio_w edgat_wires

  frame $w.io
  set edgatio_w $w.io

  frame $edgatio_w.box
  frame $edgatio_w.but
  pack $edgatio_w.box $edgatio_w.but -padx 5 -pady 5

  frame $edgatio_w.box.name
  frame $edgatio_w.box.port
  frame $edgatio_w.box.type
  frame $edgatio_w.box.sizesb
  frame $edgatio_w.box.sizesb.lbsb
  label $edgatio_w.box.name.la -text [m db.gate.signam]
  label $edgatio_w.box.port.la -text [m db.gate.port]
  label $edgatio_w.box.type.la -text [m db.gate.iotype]
  label $edgatio_w.box.sizesb.la -text [m db.gate.bitws]
  listbox $edgatio_w.box.name.lb -width 15 -height 10 -yscrollcommand "$edgatio_w.box.sizesb.lbsb.vert set"
  listbox $edgatio_w.box.port.lb -width 10 -height 10
  listbox $edgatio_w.box.type.lb -width 5 -height 10
  listbox   $edgatio_w.box.sizesb.lbsb.lb -width 5 -height 10
  scrollbar $edgatio_w.box.sizesb.lbsb.vert -command "edgatPortView"
  pack $edgatio_w.box.sizesb.lbsb.lb $edgatio_w.box.sizesb.lbsb.vert -side left -fill y
  pack $edgatio_w.box.name.la $edgatio_w.box.name.lb -anchor w
  pack $edgatio_w.box.port.la $edgatio_w.box.port.lb -anchor w
  pack $edgatio_w.box.type.la $edgatio_w.box.type.lb -anchor w
  pack $edgatio_w.box.sizesb.la $edgatio_w.box.sizesb.lbsb -anchor w
  pack $edgatio_w.box.name $edgatio_w.box.port $edgatio_w.box.type $edgatio_w.box.sizesb -side left -fill both

  bind $edgatio_w.box.name.lb <ButtonRelease-1> edgateUpdateButtons
  bind $edgatio_w.box.port.lb <ButtonRelease-1> edgateUpdateButtons
  bind $edgatio_w.box.type.lb <ButtonRelease-1> edgateUpdateButtons
  bind $edgatio_w.box.sizesb.lbsb.lb <ButtonPress-1> edgateUpdateButtons

  bind $edgatio_w.box.name.lb <Double-ButtonRelease-1> "edgatPortEdit 1 [offsetgeometry .edgat 50 50 ]"
  bind $edgatio_w.box.port.lb <Double-ButtonRelease-1> "edgatPortEdit 1 [offsetgeometry .edgat 50 50 ]"
  bind $edgatio_w.box.type.lb <Double-ButtonRelease-1> "edgatPortEdit 1 [offsetgeometry .edgat 50 50 ]"
  bind $edgatio_w.box.sizesb.lbsb.lb <Double-ButtonRelease-1> "edgatPortEdit 1 [offsetgeometry .edgat 50 50 ]"

  button $edgatio_w.but.edit -text [m b.edit] -command "edgatPortEdit 1 [offsetgeometry .edgat 50 50 ]"
  button $edgatio_w.but.add -text [m b.add] -command edgatPortAdd 
  button $edgatio_w.but.delete -text [m b.delete] -command edgatPortDelete
  pack $edgatio_w.but.edit $edgatio_w.but.add $edgatio_w.but.delete -padx 5 -pady 5 -side left

  pack $edgatio_w -fill both -padx 5 -pady 20

  helpon $edgatio_w.box.name.la [m ho.edgat.cname]
  helpon $edgatio_w.box.port.la [m ho.edgat.cport]
  helpon $edgatio_w.box.type.la [m ho.edgat.ctype]
  helpon $edgatio_w.box.sizesb.la [m ho.edgat.cbitw]

  helpon $edgatio_w.but.edit [m ho.edgat.cedit]
  helpon $edgatio_w.but.add [m ho.edgat.cadd]
  helpon $edgatio_w.but.delete [m ho.edgat.cdel]

  foreach p $edgat_wires {
    eval "edgatAddPort end $p"
  }
}

proc edgatBasic {w args} {
  global edgat_type edgat_name edgat_hideName edgat_blockFunc

  if { [lindex $args 0] == "-raised" } {
    frame $w.basic -bd 2 -relief raised
  } else {
    frame $w.basic
  }
  set wb $w.basic

  frame $wb.type
  frame $wb.name
  frame $wb.hide
  frame $wb.anchor
  frame $wb.cpbreak 

  label $wb.type.lab -text "[m db.gate.gtype]:" -width 24 -anchor e
  label $wb.type.ent -text "$edgat_type" -width 12 -anchor w
  pack $wb.type.lab $wb.type.ent -padx 5 -pady 5 -side left 
  pack $wb.type -anchor w

  label $wb.name.lab -text "[m db.gate.gname]:" -width 24 -anchor e
  entry $wb.name.ent -width 15 -textvariable edgat_name
  pack $wb.name.lab $wb.name.ent -padx 5 -pady 5 -side left 
  pack $wb.name -anchor w
 

  if { $edgat_type != "COMMENT"  &&  $edgat_type != "Frame" } {
    label $wb.hide.lab -text "[m db.gate.hidenam]:" -width 24 -anchor e
    checkbutton $wb.hide.ent -variable edgat_hideName
    pack $wb.hide.lab $wb.hide.ent -padx 5 -pady 5 -side left 
    pack $wb.hide -anchor w
    helpon $wb.hide.lab [m ho.edgat.hide]
  }

  label $wb.anchor.lab -text "[m db.gate.anchor]:" -width 24 -anchor e
  checkbutton $wb.anchor.ent -variable edgat_anchor
  label $wb.anchor.xlab -text "X:"
  entry $wb.anchor.xent -width 4 -textvariable edgat_xpos
  label $wb.anchor.ylab -text "Y:"
  entry $wb.anchor.yent -width 4 -textvariable edgat_ypos
  pack $wb.anchor.lab $wb.anchor.ent $wb.anchor.xlab -padx 5 -pady 5 -side left 
  pack $wb.anchor.xent $wb.anchor.ylab $wb.anchor.yent -padx 5 -pady 5 -side left 
  pack $wb.anchor -anchor w

  if { $edgat_type != "Module" } {
    label $wb.cpbreak.lab -text "[m db.gate.cpbreak]:" -width 24 -anchor e
    checkbutton $wb.cpbreak.ent -variable edgat_cpbreak
    pack $wb.cpbreak.lab $wb.cpbreak.ent -padx 5 -pady 5 -side left   
    pack $wb.cpbreak -anchor w
  }

#  checkbutton $w.  

  bind $wb.name.ent <KeyPress-Return> "edgatOK"

  
  if { [lindex $args 0] == "-raised" } {
    pack $wb -fill both
  } else {
    pack $wb -padx 5 -pady 20
  }

  helpon $wb.type.lab [m ho.edgat.gtype]
  helpon $wb.name.lab [m ho.edgat.gname]
  helpon $wb.anchor.lab [m ho.edgat.ganchor]
  helpon $wb.anchor.xlab [m ho.edgat.gx]
  helpon $wb.anchor.ylab [m ho.edgat.gy]
}

proc dvalSetState {w} {
  global edgat_delays edgat_dtype

  catch {
    if { $edgat_dtype == "tech" } {
      set state "disabled"
    } else {
      set state "normal"
    }

    set r 0
    set c 0
    set tdtw $w.tech.dtab
    set dtw $w.cust.dtab
    foreach d $edgat_delays {
      $dtw.e${r}_$c configure -state $state

      if { $state == "normal" } {
        $dtw.e${r}_$c configure -foreground black
        $dtw.l${r}_$c configure -foreground black
        $tdtw.e${r}_$c configure -foreground dimgray
        $tdtw.l${r}_$c configure -foreground dimgray
      } else {
        $dtw.e${r}_$c configure -foreground dimgray
        $dtw.l${r}_$c configure -foreground dimgray
        $tdtw.e${r}_$c configure -foreground black
        $tdtw.l${r}_$c configure -foreground black
      }

      incr c
      if { $c == 3 } {
	set c 0
	incr r
      }
    }
  }
}

proc trace_edgat_tech args {
  global edgat_tech edgatdelay_w edgat_techdelay
  gat_setGateTechDelays $edgat_tech
}

proc edgatDelay {w} {
  global edgat_delays edgat_dtype edgat_techList edgat_tech edgat_techdelay

  frame $w.delay
  set wd $w.delay

  frame $wd.tech -bd 2 -relief groove
  radiobutton $wd.tech.b -text [m db.gate.stddelay] -variable edgat_dtype -value tech -command "dvalSetState $wd"
  eval "tk_optionMenu $wd.tech.opt edgat_tech $edgat_techList"

  set idx 0
  set r 0
  set c 0
  frame $wd.tech.dtab
  set dtw $wd.tech.dtab
  foreach d $edgat_delays {
    label $dtw.l${r}_$c -text "$d:"
    label $dtw.e${r}_$c -textvariable edgat_techdelay($d) -width 4 -justify left

    grid $dtw.l${r}_$c -row $r -column [expr 3*$c] -padx 2 -pady 3  -sticky  e
    grid $dtw.e${r}_$c -row $r -column [expr 3*$c+1] -padx 2 -pady 3 -sticky w

    incr idx
    incr c
    if { $c == 3 } {
      set c 0
      incr r
    }
  }
  grid columnconfigure $wd.tech.dtab 2 -minsize 20
  grid columnconfigure $wd.tech.dtab 5 -minsize 20
  pack $wd.tech.dtab -padx 5 -pady 5 -side bottom
  pack $wd.tech.b -padx 5 -pady 5 -anchor w -side left
  pack $wd.tech.opt  -padx 5 -pady 5 -anchor w -side left

  frame $wd.cust -bd 2 -relief groove
  radiobutton $wd.cust.b -text [m db.gate.custdelay] -variable edgat_dtype -value cust -command  "dvalSetState $wd"
  pack $wd.cust.b -padx 5 -pady 5 -anchor w


  set r 0
  set c 0
  frame $wd.cust.dtab
  set dtw $wd.cust.dtab
  foreach d $edgat_delays {
    label $dtw.l${r}_$c -text "$d:" 
    entry $dtw.e${r}_$c -width 4 -textvariable edgat_delayvalue($d)

    grid $dtw.l${r}_$c -row $r -column [expr 3*$c] -padx 2 -pady 3 -sticky e
    grid $dtw.e${r}_$c -row $r -column [expr 3*$c+1] -padx 2 -pady 3

    incr c
    if { $c == 3 } {
      set c 0
      incr r
    }
  }
  grid columnconfigure $wd.cust.dtab 2 -minsize 20
  grid columnconfigure $wd.cust.dtab 5 -minsize 20
  pack $wd.cust.dtab -padx 5 -pady 5

  pack $wd.tech $wd.cust -padx 5 -pady 3 -fill both
  pack $wd -padx 5 -pady 20 -fill both

  dvalSetState $wd
  gat_setGateTechDelays $edgat_tech

  helpon $wd.tech.b [m ho.techbut]
  helpon $wd.cust.b [m ho.custbut]
}


proc edgatBASIC {w} {
  global edgat_extbar

  frame $w.extbar
  checkbutton $w.extbar.state -text [m db.gate.extbar] -variable edgat_extbar
  pack $w.extbar.state -padx 5 -pady 5 -anchor w
  pack $w.extbar -fill both -padx 5 -pady 20

  helpon $w.extbar.state [m ho.edgat.extbar]
}

proc edgatSwitch {w} {
  global edgat_switch

  frame $w.switch
  checkbutton $w.switch.state -text [m db.gate.butstate] -variable edgat_switch
  pack $w.switch.state -padx 5 -pady 5 -anchor w
  pack $w.switch -fill both -padx 5 -pady 20

  helpon $w.switch.state [m ho.edgat.swstate]
}

proc edgatDip {w} {
  global edgat_dip

  frame $w.dip
  label $w.dip.label -text "[m db.gate.dipval]:"
  entry $w.dip.state -textvariable edgat_dip
  pack $w.dip.label $w.dip.state -padx 5 -pady 5 -side left -anchor w
  bind $w.dip.state <KeyPress-Return> "edgatOK"
  pack $w.dip -fill both -padx 5 -pady 20

  helpon $w.dip.label [m ho.edgat.dipstate]
}

proc edgatTap {w} {
  global edgat_tap

  frame $w.tap
  label $w.tap.label -text "Bit Range:"
  entry $w.tap.state -textvariable edgat_tap
  pack $w.tap.label $w.tap.state -padx 5 -pady 5 -side left -anchor w
  pack $w.tap -fill both -padx 5 -pady 20
  bind $w.tap.state <KeyPress-Return> "edgatOK"

  helpon $w.tap.label [m ho.edgat.range]
}

proc edgatMem {w} {
  global edgat_memFile edgatmem_w

  set edgatmem_w $w.mem
  frame $w.mem
  label $w.mem.label -text "[m db.gate.memfilenam]:"
  entry $w.mem.file -textvariable edgat_memFile
  button $w.mem.browse -text [m b.browse]  -command {
    global mem_filter mem_filetypes edgate_memFile edgatmem_w
    set file [tk_getOpenFile -defaultextension $mem_filter -filetypes $mem_filetypes -parent .edgat]
    if { $file != "" } { 
      set edgat_memFile $file
      $edgatmem_w.file icursor end
      $edgatmem_w.file xview end
    }
  }

  pack $w.mem.label $w.mem.file $w.mem.browse -padx 5 -pady 5 -side left -anchor w
  pack $w.mem -fill both -padx 5 -pady 20
  bind $w.mem.file <KeyPress-Return> "edgatOK"

  helpon $w.mem.label [m ho.edgat.memfile]
}


proc edgatFF {w} {
  labelframe $w.fftype [m db.gate.fftype]

  set wraplength 130

  imageRadioButton $w.fftype.normal -onimage [gifIb ff.gif] -offimage [gifIb Uff.gif] -wraplength $wraplength \
      -variable edgat_ffmirror -value 0 -label [m db.gate.ffnormal.hdr] -description [m db.gate.ffnormal.exp]

  imageRadioButton $w.fftype.reverse -onimage [gifIb rff.gif] -offimage [gifIb Urff.gif] -wraplength $wraplength \
      -variable edgat_ffmirror -value 1 -label [m db.gate.ffreverse.hdr] -description [m db.gate.ffreverse.exp]

  frame $w.fftype.toppad -height 10
  frame $w.fftype.botpad -height 5
  pack $w.fftype.toppad
  pack $w.fftype.botpad -side bottom
  pack $w.fftype.normal $w.fftype.reverse -padx 4 -side left

  pack $w.fftype -fill both -padx 5 -pady 20
}

proc edgatMUX {w} {
    global edgat_type

    if { $edgat_type == "MUX" } {
      set prefix db.gate.mux
      set ord1 [gifIb muxord1.gif]
      set ord2 [gifIb muxord2.gif]
      set sel1 [gifIb muxsel1.gif]
      set sel2 [gifIb muxsel2.gif]

      set uord1 [gifIb Umuxord1.gif]
      set uord2 [gifIb Umuxord2.gif]
      set usel1 [gifIb Umuxsel1.gif]
      set usel2 [gifIb Umuxsel2.gif]
    } else {
      set prefix db.gate.demux
      set ord1 [gifIb demuxord1.gif]
      set ord2 [gifIb demuxord2.gif]
      set sel1 [gifIb demuxsel1.gif]
      set sel2 [gifIb demuxsel2.gif]

      set uord1 [gifIb Udemuxord1.gif]
      set uord2 [gifIb Udemuxord2.gif]
      set usel1 [gifIb Udemuxsel1.gif]
      set usel2 [gifIb Udemuxsel2.gif]
    }

    set wraplength 130

    #############################################################################
    labelframe $w.dataord [m $prefix.dataorder]

    imageRadioButton $w.dataord.ascend -onimage $ord1 -offimage $uord1 -wraplength $wraplength \
	-variable edgat_dataOrder -value 0 -label [m $prefix.ord1.hdr] -description [m $prefix.ord1.exp]

    imageRadioButton $w.dataord.descend -onimage $ord2 -offimage $uord2 -wraplength $wraplength \
	-variable edgat_dataOrder -value 1 -label [m $prefix.ord2.hdr] -description [m $prefix.ord2.exp]

    frame $w.dataord.toppad -height 10
    frame $w.dataord.botpad -height 5
    pack $w.dataord.toppad
    pack $w.dataord.botpad -side bottom
    pack $w.dataord.ascend $w.dataord.descend -padx 4 -side left

    #############################################################################
    labelframe $w.selsty [m $prefix.select]


    imageRadioButton $w.selsty.onleft -onimage $sel1 -offimage $usel1 -wraplength $wraplength \
	-variable edgat_selectSide -value 0 -label [m $prefix.sel1.hdr] -description [m $prefix.sel1.exp]

    imageRadioButton $w.selsty.onright -onimage $sel2 -offimage $usel2 -wraplength $wraplength \
	-variable edgat_selectSide -value 1 -label [m $prefix.sel2.hdr] -description [m $prefix.sel2.exp]

    frame $w.selsty.toppad -height 10
    frame $w.selsty.botpad -height 5
    pack $w.selsty.toppad
    pack $w.selsty.botpad -side bottom
    pack $w.selsty.onleft $w.selsty.onright -padx 4 -side left

    #############################################################################

    frame $w.pad -height 10
    frame $w.pad2 -height 10

    pack $w.pad
    pack $w.dataord -anchor w -fill both -padx 5
    pack $w.pad2
    pack $w.selsty -anchor w -fill both -padx 5
}

proc edgatModule {w} {
  global edgat_newBlock

  frame $w.mod
  label $w.mod.lab -text "[m db.gate.modname]" -width 12 -anchor e
  entry $w.mod.ent -width 15 -textvariable edgat_blockFunc
  bind $w.mod.ent <KeyPress-Return> "edgatOK"
  pack $w.mod.lab -padx 5 -pady 5 -side left 
  pack $w.mod.ent -padx 5 -pady 5 -side left -fill both -expand 1
  pack $w.mod -anchor w
  if { $edgat_newBlock } {
    $w.mod.ent selection range 0 end
    focus $w.mod.ent
  }
  helpon $w.mod.lab [m ho.edgat.func]
  pack $w.mod -fill both -padx 5 -pady 20
}

proc edgatFrame {w} {
  global edgat_newBlock

  frame $w.frm
  label $w.frm.lab -text "[m b.label]:" -anchor e
  entry $w.frm.ent -width 30 -textvariable edgat_frameLabel
  bind $w.frm.ent <KeyPress-Return> "edgatOK"
  pack $w.frm.lab -padx 5 -pady 5 -side left
  pack $w.frm.ent -padx 5 -pady 5 -side left -fill both -expand 1
  pack $w.frm -anchor w
  if { $edgat_newBlock } {
    $w.frm.ent selection range 0 end
    focus $w.frm.ent
  }
  helpon $w.frm.lab [m ho.edgat.frame]
  pack $w.frm -fill both -padx 5 -pady 20
}

#############################################################################
#
# Gate property tab for setting LED properties.
#
proc edgatLED {w} {
    global edgat_newBlock

    set wraplength 130

    labelframe $w.led [m db.gate.led.type]

    imageRadioButton $w.led.bit -onimage [gifIb led_bit.gif] -offimage [gifIb Uled_bit.gif] -wraplength $wraplength \
	-variable edgat_ledType -value 0 -label [m db.gate.led.bit.hdr] -description [m db.gate.led.bit.exp]

    imageRadioButton $w.led.bar -onimage [gifIb led_bar.gif] -offimage [gifIb Uled_bar.gif] -wraplength $wraplength \
	-variable edgat_ledType -value 1 -label [m db.gate.led.bar.hdr] -description [m db.gate.led.bar.exp]

    imageRadioButton $w.led.hex -onimage [gifIb led_hex.gif] -offimage [gifIb Uled_hex.gif] -wraplength $wraplength \
	-variable edgat_ledType -value 2 -label [m db.gate.led.hex.hdr] -description [m db.gate.led.hex.exp]

    imageRadioButton $w.led.dec -onimage [gifIb led_dec.gif] -offimage [gifIb Uled_dec.gif] -wraplength $wraplength \
	-variable edgat_ledType -value 3 -label [m db.gate.led.dec.hdr] -description [m db.gate.led.dec.exp]

    imageRadioButton $w.led.seg -onimage [gifIb led_direct.gif] -offimage [gifIb Uled_direct.gif] -wraplength $wraplength \
	-variable edgat_ledType -value 4 -label [m db.gate.led.seg.hdr] -description [m db.gate.led.seg.exp]


    frame $w.led.pad1 -height 10
    frame $w.led.pad2 -height 10
    frame $w.led.pad3 -height 10
    frame $w.led.pad4 -height 10

    grid $w.led.pad1 -row 0 -column 0
    grid $w.led.bit  -row 1 -column 0 -sticky w
    grid $w.led.bar  -row 1 -column 1 -sticky w

    grid $w.led.pad2 -row 2 -column 0
    grid $w.led.hex  -row 3 -column 0 -sticky w
    grid $w.led.dec  -row 3 -column 1 -sticky w

    grid $w.led.pad3 -row 4 -column 0
    grid $w.led.seg  -row 5 -column 0 -sticky w

    grid $w.led.pad4 -row 6 -column 0

    pack $w.led -fill both -padx 5 -pady 20
}

proc edgatLED_old {w} {
  global edgat_newBlock

  frame $w.led

  label $w.led.lab -text "[m db.led.type]:" -anchor e
  radiobutton $w.led.bit -text [m db.led.bit] -variable edgat_ledType -value 0
  radiobutton $w.led.bar -text [m db.led.bar] -variable edgat_ledType -value 1
  radiobutton $w.led.hex -text [m db.led.hex] -variable edgat_ledType -value 2
  radiobutton $w.led.dec -text [m db.led.dec] -variable edgat_ledType -value 3
  radiobutton $w.led.seg -text [m db.led.seg] -variable edgat_ledType -value 4

  grid $w.led.lab -row 0 -column 0 -columnspan 2 -sticky w
  grid $w.led.bit -row 1 -column 0 -sticky w
  grid $w.led.bar -row 1 -column 1 -sticky w
  grid $w.led.hex -row 2 -column 0 -sticky w
  grid $w.led.dec -row 2 -column 1 -sticky w
  grid $w.led.seg -row 3 -column 0 -sticky w

  pack $w.led -fill both -padx 5 -pady 20
}

proc edgatOK {} { global edgat_ok; set edgat_ok 1; destroy .edgat }

proc edgatConfirm {w} {
  global edgat_ok
  frame $w.confirm -relief raised -bd 2
  button $w.confirm.ok -text [m b.ok] -command " edgatOK"
  button $w.confirm.cancel -text [m b.cancel] -command "set edgat_ok 0; destroy $w"
  pack $w.confirm.ok -side left -padx 5 -pady 5
  pack $w.confirm.cancel -side right -padx 5 -pady 5
  pack $w.confirm -fill both
}

proc tkg_saveComment {w} {
  global edgat_commentLen edgat_commentLines edgat_ok

  for { set i 1 } { [$w.f.t compare $i.end < end] } { incr i } {
    set x [$w.f.t get $i.0 $i.end]
    set j [expr $i - 1]
    set edgat_commentLines($j) [iconv decode $x]
  }
  set edgat_commentLen [expr $i - 1]
  set edgat_ok 1
  destroy $w
}

proc tkg_discardComment {w} {
  global edgat_ok
  set edgat_ok 0
  destroy $w
}

#
# Dialog for editing comments
#
proc tkg_editCommentGate {} {
  global edgat_geom edgat_commentLen edgat_commentLines edgat_ok

  set w .edgat
  toplevel $w
  wm title $w "TKGate: Comment Text"
  wm geometry $w $edgat_geom
  wm minsize $w 350 300
  wm transient $w .

  edgatBasic $w -raised

  frame $w.prop -relief raised -bd 2
  checkbutton $w.prop.dolink -text [m db.gate.islink] -variable edgat_dolink
  label $w.prop.t -text "[m db.gate.link]: "
  entry $w.prop.link -textvariable edgat_link
  bind $w.prop.link <KeyPress-Return> "tkg_saveComment $w"

  pack $w.prop.dolink -anchor w -padx 5 -pady 3
  pack $w.prop.t -anchor w -padx 5 -pady 5 -side left
  pack $w.prop.link -anchor w -padx 5 -pady 5 -side left -fill both -expand 1
  pack $w.prop -fill both

  okcancel $w.ok "tkg_saveComment $w" "tkg_discardComment $w"
  pack $w.ok -fill both -side bottom

  frame $w.f -relief raised -bd 2
  text $w.f.t -yscrollcommand "$w.f.vb set" -xscrollcommand "$w.f.hb set" -width 80 -height 15
  scrollbar $w.f.vb -command "$w.f.t yview"
  scrollbar $w.f.hb -command "$w.f.t xview" -orient horizontal

  grid rowconfig $w.f 0  -weight 1 -minsize 0
  grid columnconfig $w.f 0 -weight 1 -minsize 0

  grid $w.f.t -row 0 -column 0 -sticky news
  grid $w.f.vb -row 0 -column 1 -sticky news
  grid $w.f.hb -row 1 -column 0 -sticky news
  pack $w.f -ipadx 5 -ipady 5 -fill both -expand 1

  for {set i 0 } { $i < $edgat_commentLen } { incr i } {
    if { $i > 0 } { $w.f.t insert end "\n" }
    $w.f.t insert end  [iconv encode $edgat_commentLines($i)]
  }


  focus $w.f.t

  update
  grab set $w
  tkwait window $w
  grab release $w
}

proc editgate_tab {w tab} {
  global edgat_type edgat_name edgat_hideName edgat_geom edgat_wires edgat_wops
  global ecpOmega ecpPhi ecpDuty

  frame $w

  switch $tab {
    General {
      edgatBasic $w
    }
    Ports {
      edgatIO $w
    }
    Delay {
      edgatDelay $w
    }

    Clock { edgatClockParms $w $ecpOmega $ecpPhi $ecpDuty }
    Switch { edgatSwitch $w }
    DIP { edgatDip $w }
    Tran { edgatTap $w }
    RAM { edgatMem $w }
    ROM { edgatMem $w }
    Module  { edgatModule $w }
    Frame { edgatFrame $w }
    LED { edgatLED $w }
    BASIC { edgatBASIC $w }
    MUX {  edgatMUX $w   }
    DEMUX { edgatMUX $w }
    FF { edgatFF $w }
  }
}

proc tkg_editGate args {
  global edgat_type edgat_name edgat_hideName edgat_geom edgat_wires edgat_wops edgat_dtype
  global ecpOmega ecpPhi ecpDuty

  set edgat_wops {}

  if { $edgat_type == "COMMENT" } {
    tkg_editCommentGate
    return;
  }

  set start_page General

  if { $args != "" } {
    set start_page $args
  }


  set w .edgat
  if { [catch { toplevel $w }] } { return }
  wm resizable $w 0 0
  wm title $w "TKGate: Gate Parameters"
  wm geometry $w $edgat_geom
  wm transient $w .

  set tabs { General }
  set labels [list [m db.gate.general]]

  if { $edgat_type != "Frame" } {
    lappend tabs Ports
    lappend labels [m db.gate.ports]
  }

  if { $edgat_type == "Clock" }   { lappend tabs Clock; lappend labels [m db.gate.details] }
  if { $edgat_type == "Switch" }  { lappend tabs Switch; lappend labels [m db.gate.details] }
  if { $edgat_type == "DIP" }     { lappend tabs DIP; lappend labels [m db.gate.details] }
  if { $edgat_type == "Tran" }    { lappend tabs Tran; lappend labels [m db.gate.details] }
  if { $edgat_type == "RAM" }     { lappend tabs RAM; lappend labels [m db.gate.details] }
  if { $edgat_type == "ROM" }     { lappend tabs ROM; lappend labels [m db.gate.details] }
  if { $edgat_type == "Module" }  { lappend tabs Module; lappend labels [m db.gate.details] }
  if { $edgat_type == "Frame" }   { lappend tabs Frame; lappend labels [m db.gate.details] }
  if { $edgat_type == "LED" }     { lappend tabs LED; lappend labels [m db.gate.details] }
  if { $edgat_type == "COMMENT" } { lappend tabs COMMENT; lappend labels [m db.gate.details] }
  if { $edgat_type == "AND" }	  { lappend tabs BASIC; lappend labels [m db.gate.details] }
  if { $edgat_type == "OR" }	  { lappend tabs BASIC; lappend labels [m db.gate.details] }
  if { $edgat_type == "XOR" }	  { lappend tabs BASIC; lappend labels [m db.gate.details] }
  if { $edgat_type == "MUX" }	  { lappend tabs MUX; lappend labels [m db.gate.details] }
  if { $edgat_type == "DEMUX" }	  { lappend tabs DEMUX; lappend labels [m db.gate.details] }
  if { $edgat_type == "Flip-Flop" }  { lappend tabs FF; lappend labels [m db.gate.details] }

  if { $edgat_dtype != "none" } {
    lappend tabs Delay
    lappend labels [m db.gate.delay]
  }

  frame $w.f -relief raised -bd 2
  tabbox $w.f.tbox -width 425 -height 350 -tabwidth 75 -command editgate_tab -tabs $tabs -tablabels $labels -startpage $start_page
  pack $w.f.tbox -padx 5 -pady 5
  pack $w.f -fill both

  edgatConfirm $w

  trace variable ecpOmega w edgatClockPUpdate
  trace variable ecpPhi w edgatClockPUpdate
  trace variable ecpDuty w edgatClockPUpdate

  update
  grab set $w
  tkwait window $w
  grab release $w

  trace vdelete ecpOmega w edgatClockPUpdate
  trace vdelete ecpPhi w edgatClockPUpdate
  trace vdelete ecpDuty w edgatClockPUpdate
}

#
# In a future version of tkgate, this will get a list of matches 500ms
# after the last keypress in the search string window. 
#
proc tkg_getFindList {} {
  global find_target

  set w .finder

  puts "tkg_getFindList  $find_target"
}

proc tkg_reqFindList {} {
  global reqListEv

  catch { after cancel $reqListEv }
  set reqListEv [after 500 tkg_getFindList]
}

proc tkg_findObject {} {
  global find_type find_target simOn

  if { $simOn } {
    errmsg "'Find' not supported in simulation mode."
    return
  }

  set w .finder

  if { [catch { toplevel $w }] } {
    action Find { gat_find $find_type $find_target }
    return
  }
 
  wm resizable $w 0 0
  wm title $w "TKGate: Find Object"
  wm geometry $w [offsetgeometry . 50 50 ]
  wm transient $w .

  frame $w.t -relief raised -bd 2
  label $w.t.l -text "[m b.find]:"
  entry $w.t.e -textvariable find_target
  pack $w.t.l $w.t.e -side left -padx 5 -pady 5

  frame $w.rb -relief raised -bd 2
  radiobutton $w.rb.wandg -text [m db.gate.findw] -variable find_type -value 1
  radiobutton $w.rb.gonly -text [m db.gate.findg] -variable find_type -value 2
  radiobutton $w.rb.wonly -text [m db.gate.findwg] -variable find_type -value 3
  pack $w.rb.wandg $w.rb.gonly $w.rb.wonly -pady 2 -anchor w

  frame $w.ok -relief raised -bd 2
  button $w.ok.find -text [m b.find] -command { action Find { gat_find $find_type $find_target } }
  button $w.ok.clear -text [m b.clear] -command { set find_target ""; }
  button $w.ok.close -text [m b.close] -command { destroy .finder  }
  frame $w.ok.pad1
  frame $w.ok.pad2
  pack $w.ok.find -side left -pady 5 -padx 5 -fill x
  pack $w.ok.pad1 -side left -pady 5 -padx 5 -fill x -expand 1
  pack $w.ok.clear -side left -pady 5 -padx 5 -fill x
  pack $w.ok.pad2 -side left -pady 5 -padx 5 -fill x -expand 1
  pack $w.ok.close -side left -pady 5 -padx 5 -fill x

#
# This will be used in a future release.
#
#  frame $w.l -relief raised -bd 2
#  listbox $w.l.lb -xscrollcommand "$w.l.hb set" -yscrollcommand "$w.l.vb set" -width 40
#  scrollbar $w.l.vb -orient vertical -command "$w.l.lb yview"
#  scrollbar $w.l.hb -orient horizontal -command "$w.l.lb xview"
#  grid $w.l.lb -row 0 -column 0 -sticky nsew -padx 3 -pady 3
#  grid $w.l.vb -row 0 -column 1 -sticky nsew -padx 3 -pady 3
#  grid $w.l.hb -row 1 -column 0 -sticky nsew -padx 3 -pady 3
#  bind $w <KeyPress> tkg_reqFindList

  pack $w.t  -fill both -ipadx 5 -ipady 5
  pack $w.rb -fill both -ipadx 5 -ipady 5
#  pack $w.l  -fill both -ipadx 5 -ipady 5
  pack $w.ok -fill both -ipadx 5 -ipady 5


  bind $w <KeyPress-Return> { .finder.ok.find invoke }

  $w.t.e selection range 0 end
  focus $w.t.e
}

trace variable edgat_tech w trace_edgat_tech
