#-------------------------------------------------------------------
# padlist.tcl
#
# This TCL script, to be run under magic with the "source" command,
# automates the following tasks:
#
# 1) Ennumerates all pads in a design
# 2) Generates a pin list summary
# 3) Allows editing each pin name
#
# (to be done)
#
# 3) Creates a "DUT" symbol in XCircuit.
#
#-------------------------------------------------------------------

# Procedure to be used with magic "search" command (TCL only).
# this procedure ennumerates all pads and returns a list of
# unique nodes.

proc list_pads {llx lly urx ury ttype} {
   global nodelist
   global padlocate
   if {[llength $ttype] == 1} {
      box values $llx $lly $urx $ury
      select box $ttype
      set newnode [getnode]
      if {[lsearch $nodelist $newnode] < 0} {
	 lappend nodelist $newnode
	 set padlocate($newnode) [concat [magic::box values] $ttype]
      }
   }
}

proc magic::quickpadupdate { mgrpath } {
   global nodelist
   global padlocate
   [lindex [magic::windownames] 0] update suspend
   for {set i 0} {$i < [${mgrpath}.pads index end]} {incr i} {
      set pin [${mgrpath}.pads get $i] 
      set pos $padlocate($pin)
      box values [lindex $pos 0] [lindex $pos 1] [lindex $pos 2] [lindex $pos 3]
      select box [lindex $pos 4]
      if {[set newpin [magic::findlabel]] == {}} {
	 set newpin [getnode]
      }
      if {$pin != $newpin && $newpin != {}} {
	 ${mgrpath}.pads delete $i
	 ${mgrpath}.pads insert $i $newpin
	 set padlocate($newpin) $pos
	 unset padlocate($pin)
      }
   }
   [lindex [magic::windownames] 0] update resume
}

proc magic::padlabel { mgrpath } {
   global padlocate

   set selentry [${mgrpath}.pads index anchor]
   set oldlabel [${mgrpath}.pads get $selentry]
   if {![catch {frame ${mgrpath}.pade}]} {
      label ${mgrpath}.pade.msg -text "Enter new pad name:"
      entry ${mgrpath}.pade.ent -background white
      pack ${mgrpath}.pade.msg -side left
      pack ${mgrpath}.pade.ent -side left
      bind ${mgrpath}.pade.ent <Return> [subst {
	 set selentry \[${mgrpath}.pads index anchor\]
	 set oldlabel \[${mgrpath}.pads get \$selentry\]
         \[lindex \[magic::windownames\] 0\] update suspend
	 set pos \$padlocate(\$oldlabel)
	 box values \[lindex \$pos 0\] \[lindex \$pos 1\] \[lindex \$pos 2\] \[lindex \$pos 3\]
	 set layer \[lindex \$pos 4\]
	 select box \$layer
	 zoom 4
	 erase label
         paint \$layer
         set newlabel \[${mgrpath}.pade.ent get\]
         label "\$newlabel" n \$layer
         [lindex [magic::windownames] 0] update resume
         grid forget ${mgrpath}.pade
         ${mgrpath}.pads delete $selentry
         ${mgrpath}.pads insert $selentry \$newlabel
	 set padlocate(\$newlabel) \$pos
	 unset padlocate(\$oldlabel)
      }]
   }
   grid ${mgrpath}.pade -row 4 -column 0 -columnspan 2 -sticky news
   ${mgrpath}.pade.ent delete 0 end
   ${mgrpath}.pade.ent insert 0 $oldlabel
}

proc magic::padsearch {{layer pad}} {
   global nodelist

   puts stdout ""
   puts stdout "Finding and enumerating pads in design"
   puts stdout "(please be patient)"
   [lindex [magic::windownames] 0] update suspend
   view
   select top cell
   expand
   set nodelist {}
   getnode alias off		;#  only want one name per node!
   getnode globals on		;#  can be much faster this way!
   search $layer list_pads
   [lindex [magic::windownames] 0] update resume
   magic::padmanager update
}

proc magic::makepadmanager { mgrpath } {
   global nodelist

   toplevel ${mgrpath}
   set project [windowcaption]
   label ${mgrpath}.padm -text "Project [lindex $project 0] pinouts" \
		-foreground blue
   listbox ${mgrpath}.pads -yscrollcommand "${mgrpath}.pady set" -xscrollcommand \
	"${mgrpath}.padx set" -foreground brown4 -selectmode single
   scrollbar ${mgrpath}.padx -orient horizontal -command "${mgrpath}.pads xview"
   scrollbar ${mgrpath}.pady -orient vertical -command "${mgrpath}.pads yview"

   frame ${mgrpath}.padb
   button ${mgrpath}.padb.update -text Update \
	-command "magic::quickpadupdate ${mgrpath}"
   button ${mgrpath}.padb.change -text Edit \
	-command "magic::padlabel ${mgrpath}"
   button ${mgrpath}.padb.search -text Search \
	-command "magic::padsearch"
   pack ${mgrpath}.padb.update -side left
   pack ${mgrpath}.padb.change -side left
   pack ${mgrpath}.padb.search -side left

   grid ${mgrpath}.padm -row 0 -column 0 -columnspan 2 -sticky news
   grid ${mgrpath}.pads -column 0 -row 1 -sticky news
   grid ${mgrpath}.pady -column 1 -row 1 -sticky ns
   grid ${mgrpath}.padx -column 0 -row 2 -sticky ew
   grid ${mgrpath}.padb -row 3 -column 0 -columnspan 2 -sticky news

   grid rowconfigure ${mgrpath} 1 -weight 1
   grid columnconfigure ${mgrpath} 0 -weight 1

   # Bind this to a pinout click:
   bind ${mgrpath}.pads <Button-1> {
      global padlocate

      [lindex [magic::windownames] 0] update suspend
      set item [%W get [%W nearest %y]]
      set pos $padlocate($item)
      box values [lindex $pos 0] [lindex $pos 1] [lindex $pos 2] [lindex $pos 3]
      set layer [lindex $pos 4]
      findbox zoom
      zoom 4
      [lindex [magic::windownames] 0] update resume
   }
}

proc magic::padmanager {{option "create"}} {
   global nodelist
   global padlocate

   set mgrpath .padlist

   # Check for the existance of the padlist widget
   if {[catch {wm state ${mgrpath}}]} {
      if {$option == "create"} {
	 magic::makepadmanager ${mgrpath}
      } else {
	 return
      }
   } elseif { $option == "create"} {
      return
   }

   # (option "update" code goes here)

   set project [windowcaption]
   ${mgrpath}.padm configure -text "Project [lindex $project 0] pinouts"

   if {![catch {set nodelist}]} {
      ${mgrpath}.pads delete 0 end
      foreach i $nodelist {
         ${mgrpath}.pads insert 0 $i
      }
   } else {
      set nodelist {}
      array set padlocate {}
   }
}

# Need that "generate DUT" button. . .
