# This is the "Magic wrapper".
# It's main purpose is to redefine the "openwindow" command in magic so that
# opening a new window creates a window wrapped by a GUI interface.
#
# Written by Tim Edwards, August 23, 2002.

# revision A: proof-of-concept.  Add whatever you want to this basic wrapper.
# revision B: Adds Tk scrollbars and caption
# revision C: Adds a layer manager toolbar on the left side
# revision D: Adds a menubar on top with cell and tech manager tools

set MagicBLT 0
if {! [catch {package require BLT}]} {set MagicBLT 1}

# Simple console commands (like TkCon, but much simpler)

if {[lsearch [namespace children] ::tkshell] < 0} {
   catch {::source ${CAD_HOME}/lib/magic/tcl/tkshell.tcl}
}

# Menu button callback functions

proc magic::promptload {type} {
   switch $type {
      cif { set Layoutfilename [ ::tk_getOpenFile -filetypes \
		{{CIF {.cif {.cif}}} {"All files" {*}}}]
	    if {$Layoutfilename != ""} {
		magic::loadcell $Layoutfilename
		magic::cif read $Layoutfilename
	    }
	  }
      gds { set Layoutfilename [ ::tk_getOpenFile -filetypes \
		{{GDS {.gds .strm .cal {.gds .strm .cal}}} {"All files" {*}}}]
	    if {$Layoutfilename != ""} {
		magic::loadcell $Layoutfilename
		magic::calma read $Layoutfilename
	    }
	  }
      magic { set Layoutfilename [ ::tk_getOpenFile -filetypes \
		{{Magic {.mag {.mag}}} {"All files" {*}}}]
	    if {$Layoutfilename != ""} {
		magic::loadcell $Layoutfilename

		# Append path to cell search path if it's not there already

		if {[string index $Layoutfilename 0] != "/"} {
		   set $Layoutfilename "./$Layoutfilename"
		}
		set sidx [string last "/" $Layoutfilename]
		if {$sidx > 0} {
		   set cellpath [string range $Layoutfilename 0 $sidx]
		   magic::path cell +$cellpath
		}
	    }
	  }
   }
}

proc magic::promptsave {type} {
   switch $type {
      cif { set Layoutfilename [ ::tk_getSaveFile -filetypes \
		{{CIF {.cif {.cif}}} {"All files" {*}}}]
	    if {$Layoutfilename != ""} {
	       magic::cif write $Layoutfilename
	    }
	  }
      gds { set Layoutfilename [ ::tk_getSaveFile -filetypes \
		{{GDS {.gds .strm .cal {.gds .strm .cal}}} {"All files" {*}}}]
	    if {$Layoutfilename != ""} {
		magic::calma write $Layoutfilename
	    }
	  }
      magic {
	    set CellList [ magic::cellname list window ]
	    if {[lsearch $CellList "(UNNAMED)"] >= 0} {
	       set Layoutfilename [ ::tk_getSaveFile -filetypes \
		   {{Magic {.mag {.mag}}} {"All files" {*}}}]
	       if {$Layoutfilename != ""} {
		   set cellpath [file dirname $Layoutfilename]
		   if {$cellpath == [pwd]} {
		      set Layoutfilename [file tail $Layoutfilename]
		   } else {
		      magic::path cell +$cellpath
		   }
		   magic::save $Layoutfilename
	       }
	    }
	    magic::writeall
	  }
   }
}

# Callback to the cell manager

proc magic::instcallback {command} {
   set rpath [join [.cellmgr.box.view get -full anchor]]
   set rootdef [lindex $rpath 0]
   set cellpath [lrange $rpath 1 end]

   if { $cellpath == {} } {
      switch $command {
	 load {magic::loadcell $rootdef}
	 default {
	    magic::select top cell
	    switch $command {
	       edit {magic::expand; magic::editcell}
	       expand {magic::expand}
	       zoom {magic::view}
	    }
	 }
      }
   } else {
      set celluse [join $cellpath "/"]
      set celldef [magic::instance list celldef $celluse]

      set curpath [magic::windowcaption]
      set curname [lindex $curpath 2]
      set curroot [lindex $curpath 0]

      switch $command {
         load {magic::loadcell $celldef}
         default {
	    # Here: need to check first for the select cell belonging to the
	    # current loaded root cell (get the first use).
	    set defpath [list $rootdef]
	    foreach i $cellpath {
	       lappend defpath [magic::instance list celldef $i]
	    }
	    set rootpos [lsearch $defpath $curroot]
	    if {$rootpos < 0} {
	       magic::loadcell $rootdef
	       set rootpos 0
	    }
	    set usepath [join [lrange $cellpath $rootpos end] "/"]
	    magic::select cell ${usepath}

	    switch $command {
	       edit {magic::expand; magic::editcell}
	       expand {magic::expand toggle}
	       zoom {magic::findbox zoom}
	    }
	 }
      }
   }
}

# The cell manager

if {$MagicBLT} {
   toplevel .cellmgr
   wm withdraw .cellmgr
   frame .cellmgr.menubar
   frame .cellmgr.actionbar
   frame .cellmgr.box
   blt::hiertable .cellmgr.box.view -bg white -allowduplicates false -hideroot true \
	-yscrollcommand {.cellmgr.box.vert set} \
	-xscrollcommand {.cellmgr.box.vert set}
   scrollbar .cellmgr.box.vert -orient vertical -command {.cellmgr.box.view yview}

   pack .cellmgr.actionbar -side top -fill x
   pack .cellmgr.box.view -side left -fill both -expand true
   pack .cellmgr.box.vert -side right -fill y
   pack .cellmgr.box -side top -fill both -expand true
   pack .cellmgr.menubar -side top -fill x

   button .cellmgr.menubar.cb -text "Close" \
	-command "wm withdraw .cellmgr"
   pack .cellmgr.menubar.cb

   button .cellmgr.actionbar.done -text "Zoom" -command {magic::instcallback zoom}
   button .cellmgr.actionbar.edit -text "Edit" -command {magic::instcallback edit}
   button .cellmgr.actionbar.load -text "Load" -command {magic::instcallback load}
   button .cellmgr.actionbar.expand -text "Expand" -command {magic::instcallback expand}

   pack .cellmgr.actionbar.load -side left
   pack .cellmgr.actionbar.edit -side left
   pack .cellmgr.actionbar.expand -side left
   pack .cellmgr.actionbar.done -side right
}

proc magic::addlistinstance {instin} {
   set hierinst [join [lrange $instin 1 end] "/"]
   set defname [magic::instance list celldef $hierinst]
   set instnum [lindex [split [lindex $instin end] _ ] end]
   .cellmgr.box.view insert end $instin -label "${defname} (${instnum})"

   set sublist [magic::instance list children $hierinst]
   foreach i $sublist {
      set instout [concat $instin $i]
      magic::addlistinstance $instout
   }
}

proc magic::cellmanager {} {
   global MagicBLT
   if {$MagicBLT} {
      # determine the full cell heirarchy
      set tl [magic::cellname list topcells]
      # remove the previous entry and create a new one
      .cellmgr.box.view delete all
      foreach i $tl {
	 if { [file extension $i] == ".mag" } {
	    set nameroot [file rootname $i]
	 } else {
	    set nameroot $i
	 }
	 set nameroot [file tail $nameroot]
	 .cellmgr.box.view insert end $i -foreground red -label $nameroot

	 set cd [magic::cellname list childinst $i]
	 foreach j $cd {
	    set ci [concat $i $j]
	    magic::addlistinstance $ci
	 }
      }
   }
}

# Technology manager callback functions

proc magic::techparseunits {} {
   set techlambda [magic::tech lambda]
   set tech1 [lindex $techlambda 1]
   set tech0 [lindex $techlambda 0]

   set target0 [.techmgr.lambda1.lval0 get]
   set target1 [.techmgr.lambda1.lval1 get]

   set newval0 [expr {$target0 * $tech0}]
   set newval1 [expr {$target1 * $tech1}]

   magic::scalegrid $newval1 $newval0
   magic::techmanager update
}

# The technology manager

toplevel .techmgr
wm withdraw .techmgr

frame .techmgr.title
label .techmgr.title.tlab -text "Technology: "
menubutton .techmgr.title.tname -text "(none)" -foreground red3 \
	-menu .techmgr.title.tname.menu
label .techmgr.title.tvers -text "" -foreground blue
label .techmgr.subtitle -text "" -foreground sienna4

frame .techmgr.lambda0
label .techmgr.lambda0.llab -text "Microns per lambda (CIF): "
label .techmgr.lambda0.lval -text "1" -foreground blue

frame .techmgr.lambda1
label .techmgr.lambda1.llab -text "Internal units per lambda: "
entry .techmgr.lambda1.lval0 -foreground red3 -background white -width 3
label .techmgr.lambda1.ldiv -text " / "
entry .techmgr.lambda1.lval1 -foreground red3 -background white -width 3

frame .techmgr.cif0
label .techmgr.cif0.llab -text "CIF input style: "
menubutton .techmgr.cif0.lstyle -text "" -foreground blue \
	-menu .techmgr.cif0.lstyle.menu
label .techmgr.cif0.llab2 -text " Microns/lambda="
label .techmgr.cif0.llambda -text "" -foreground red3

frame .techmgr.cif1
label .techmgr.cif1.llab -text "CIF output style: "
menubutton .techmgr.cif1.lstyle -text "" -foreground blue \
	-menu .techmgr.cif1.lstyle.menu
label .techmgr.cif1.llab2 -text " Microns/lambda="
label .techmgr.cif1.llambda -text "" -foreground red3

frame .techmgr.extract
label .techmgr.extract.llab -text "Extract style: "
menubutton .techmgr.extract.lstyle -text "" -foreground blue \
	-menu .techmgr.extract.lstyle.menu

frame .techmgr.menubar
button .techmgr.menubar.cb -text "Close" \
	-command "wm withdraw .techmgr"

pack .techmgr.title.tlab -side left
pack .techmgr.title.tname -side left
pack .techmgr.title.tvers -side left
pack .techmgr.lambda0.llab -side left
pack .techmgr.lambda0.lval -side left
pack .techmgr.lambda1.llab -side left
pack .techmgr.lambda1.lval0 -side left
pack .techmgr.lambda1.ldiv -side left
pack .techmgr.lambda1.lval1 -side left
pack .techmgr.cif0.llab -side left
pack .techmgr.cif0.lstyle -side left
pack .techmgr.cif0.llab2 -side left
pack .techmgr.cif0.llambda -side left
pack .techmgr.cif1.llab -side left
pack .techmgr.cif1.lstyle -side left
pack .techmgr.cif1.llab2 -side left
pack .techmgr.cif1.llambda -side left
pack .techmgr.extract.llab -side left
pack .techmgr.extract.lstyle -side left
pack .techmgr.menubar.cb

pack .techmgr.title -side top -fill x
pack .techmgr.subtitle -side top -fill x
pack .techmgr.lambda0 -side top -fill x
pack .techmgr.lambda1 -side top -fill x
pack .techmgr.cif0 -side top -fill x
pack .techmgr.cif1 -side top -fill x
pack .techmgr.extract -side top -fill x
pack .techmgr.menubar -side bottom -fill x

bind .techmgr.lambda1.lval0 <Return> magic::techparseunits
bind .techmgr.lambda1.lval1 <Return> magic::techparseunits

# Create or redisplay the technology manager

proc magic::techmanager {{option "update"}} {
   global tcl_precision
   global CAD_HOME
   if {$option == "initall"} {
      set m [menu .techmgr.title.tname.menu -tearoff 0]
      set dirlist [subst [magic::path sys]]
      set tlist {}
      foreach i $dirlist {
	 lappend tlist [glob -nocomplain ${i}/*.tech27]
      }
      foreach i [join $tlist] {
	 set j [file tail [file rootname ${i}]]
	 $m add command -label $j -command \
		"magic::tech load $j ; magic::techmanager update"
      }

      menu .techmgr.cif0.lstyle.menu -tearoff 0
      menu .techmgr.cif1.lstyle.menu -tearoff 0
      menu .techmgr.extract.lstyle.menu -tearoff 0
    
   }

   if {$option == "init"} {
	.techmgr.cif0.lstyle.menu delete 0 end
	.techmgr.cif1.lstyle.menu delete 0 end
	.techmgr.extract.lstyle.menu delete 0 end
   }

   if {$option == "init" || $option == "initall"} {
      set tlist [magic::cif listall istyle]
      foreach i $tlist {
	 .techmgr.cif0.lstyle.menu add command -label $i -command \
		"magic::cif istyle $i ; \
		 magic::techmanager update"
      }

      set tlist [magic::cif listall ostyle]
      foreach i $tlist {
	 .techmgr.cif1.lstyle.menu add command -label $i -command \
		"magic::cif ostyle $i ; \
		 magic::techmanager update"
      }

      set tlist [magic::extract listall style]
      foreach i $tlist {
	 .techmgr.extract.lstyle.menu add command -label $i -command \
		"magic::extract style $i ; \
		 magic::techmanager update"
      }
   }

   set psave $tcl_precision
   set tcl_precision 3

   set techlambda [magic::tech lambda]
   set tech1 [lindex $techlambda 1]
   set tech0 [lindex $techlambda 0]
   set tscale [expr {$tech1 / $tech0}]

   .techmgr.title.tname configure -text [magic::tech name]
   set techstuff [magic::tech version]
   .techmgr.title.tvers configure -text "(version [lindex $techstuff 0])"
   .techmgr.subtitle configure -text [lindex $techstuff 1]
   .techmgr.lambda0.lval configure -text [expr {[magic::cif lambda output] * $tscale}]
   .techmgr.cif0.lstyle configure -text [magic::cif list istyle]
   .techmgr.cif0.llambda configure -text [expr {[magic::cif lambda input] * $tscale}]
   .techmgr.cif1.lstyle configure -text [magic::cif list ostyle]
   .techmgr.cif1.llambda configure -text [expr {[magic::cif lambda output] * $tscale}]
   .techmgr.extract.lstyle configure -text [magic::extract list style]

   .techmgr.lambda1.lval0 delete 0 end
   .techmgr.lambda1.lval1 delete 0 end
   .techmgr.lambda1.lval0 insert end $tech1
   .techmgr.lambda1.lval1 insert end $tech0

   set tcl_precision $psave
}

proc magic::caption {winpath} {
   set framename [winfo parent $winpath]
   set caption [$winpath windowcaption]
   set subcaption1 [lindex $caption 0]
   if {[lindex $caption 1] == "EDITING"} {
      set subcaption2 [lindex $caption 2]
   } else {
      set subcaption2 [join [lrange $caption 1 end]]
   }
   ${framename}.titlebar.caption configure -text \
	"Loaded: ${subcaption1} Editing: ${subcaption2}"
}

# Allow captioning in the title window by tagging the "load" and "edit" commands
# Note that the "box" tag doesn't apply to mouse-button events, so this function
# is duplicated by Tk binding of mouse events in the layout window.

magic::tag loadcell "magic::cellmanager; magic::caption %W"
magic::tag editcell "magic::caption %W"
magic::tag save "magic::caption %W"
magic::tag box "magic::boxview %W"
magic::tag move "magic::boxview %W"
magic::tag scroll "magic::scrollupdate %W"
magic::tag view "magic::scrollupdate %W"
magic::tag zoom "magic::scrollupdate %W"
magic::tag findbox "magic::scrollupdate %W"
magic::tag see "magic::toolupdate %W %1 %2"
magic::tag tech "magic::techrebuild %W %1"
if {$MagicBLT} {
   magic::tag select "magic::mgrselect %R"
   magic::tag cif "magic::mgrupdate %W %1"
   magic::tag calma "magic::mgrupdate %W %1"
}

# This should be a list. . . do be done later
set windowsopen 0

# Repainting function for scrollbars, title, etc., to match the magic
# Change the colormap (most useful in 8-bit PseudoColor)

proc magic::repaintwrapper { win } {
   set bgcolor [magic::magiccolor -]
   ${win}.xscroll configure -background $bgcolor
   ${win}.xscroll configure -activebackground [magic::magiccolor t]
   ${win}.xscroll configure -highlightbackground $bgcolor
   ${win}.xscroll configure -troughcolor [magic::magiccolor T]
   ${win}.xscroll configure -highlightcolor [magic::magiccolor K]

   ${win}.yscroll configure -background $bgcolor
   ${win}.yscroll configure -activebackground [magic::magiccolor t]
   ${win}.yscroll configure -highlightbackground $bgcolor
   ${win}.yscroll configure -troughcolor [magic::magiccolor T]
   ${win}.yscroll configure -highlightcolor [magic::magiccolor K]

   ${win}.titlebar.caption configure -background [magic::magiccolor w]
   ${win}.titlebar.caption configure -foreground [magic::magiccolor c]

   ${win}.titlebar.message configure -background [magic::magiccolor w]
   ${win}.titlebar.message configure -foreground [magic::magiccolor c]

   ${win}.titlebar.pos configure -background [magic::magiccolor w]
   ${win}.titlebar.pos configure -foreground [magic::magiccolor c]

}

# Scrollbar callback function

proc magic::scrollview { win dir cmd val {units "fraction"}} {
   # puts "scrollview $win $dir $cmd $val $units"
   switch -glob -- $cmd {
      scroll {
	 switch -glob -- $units {
	    pages {$win magic::scroll $dir $val}
	    units {$win magic::scroll $dir [expr $val * 0.1]}
	 }
      }
      moveto {
	 switch -glob -- $dir {
	    e {set tot [winfo width $win]
	       set pps [winfo pointerx $win]
	       set rps [winfo rootx $win]
	       set frx [expr (${pps}.00 - $rps) / $tot]
	       # puts "fraction horizontal $frx"
	       $win magic::center horizontal $frx
            }
	    s {set tot [winfo height $win]
	       set pps [winfo pointery $win]
	       set rps [winfo rooty $win]
	       set fry [expr 1 - ((${pps}.00 - $rps) / $tot)]
	       # puts "fraction vertical $fry"
	       $win magic::center vertical $fry
	    }
	 }
      }
   }
}

# Coordinate diaplay callback function
# Because "box" calls "box", use the "info level" command to avoid
# infinite recursion.

proc magic::boxview {win} {
   if {[info level] <= 1} {
      set framename [winfo parent $win]
      ${framename}.titlebar.pos configure -text "[${win} box values]"
   }
}

# Procedure to update scrollbars in response to an internal command
# "view" calls "view", so avoid infinite recursion.

proc magic::scrollupdate {win} {
   if {[info level] <= 1} {
      set framename [winfo parent $win]
      set svalues [${win} view get]
      ${framename}.xscroll set [lindex $svalues 0] [lindex $svalues 1]
      ${framename}.yscroll set [lindex $svalues 2] [lindex $svalues 3]
   }
}

proc magic::toolupdate {win {yesno "yes"} {layerlist "none"}} {
   set framename [winfo parent $win]
   if {$layerlist == "none"} {
	set layerlist $yesno
	set yesno "yes"
   }
   if {$layerlist == "*"} {
      set layerlist [magic::tech layer "*"]
   }
   foreach layer $layerlist {
      switch $layer {
	 none {}
	 errors {set canon $layer}
	 subcell {set canon $layer}
	 labels {set canon $layer}
	 default {set canon [magic::tech layer $layer]}
      }
      if {$layer != "none"} {
         if {$yesno == "yes"} {
	    ${framename}.toolbar.b$canon configure -image img_$canon 
         } else {
	    ${framename}.toolbar.b$canon configure -image img_space
	 }
      }
   }
}

# Redirect and reformat Tcl output of "select" command

if {$MagicBLT} {
   proc magic::mgrselect {{sstr ""}} {
      if {$sstr == ""} return
      set savetag [magic::tag select]
      magic::tag select ""
      .cellmgr.box.view selection clearall
      if {[llength $sstr] == 5} {
	 # sstr is "Topmost cell in the window"
	 set clist [magic::cellname list window]
	 set isrch [magic::cellname list instances $clist]
	 foreach i $isrch {
	    if {[llength $i] != 5} {
	       set gsrch $i
	       break
	    } else {
	       set gsrch $clist
	    }
         }
         set idx [lindex [.cellmgr.box.view find -glob -full *${gsrch}*] 0]
	 set cdef $clist
      } else {
	 regsub -all {\[.*\]} $sstr {[^a-z]+} newstr
         set gsrch [string map {"/" " "} ".*${newstr}\$"]
	 set cdef [magic::instance list celldef $sstr]
         set idx [.cellmgr.box.view find -regexp -full "$gsrch"]
      }
      if {$idx != "" } {
         .cellmgr.box.view open $idx
         if {[wm state .cellmgr] == "normal"} { .cellmgr.box.view see $idx }
         .cellmgr.box.view selection anchor $idx
         .cellmgr.box.view selection set $idx
         if {$sstr != ""} {
	    puts stdout "Selected cell is $cdef ($sstr)"
	 }
      }
      magic::tag select $savetag
   }

   # Update cell manager in response to a cif or calma read command

   proc magic::mgrupdate {win {cmdstr ""}} {
      if {${cmdstr} == "read"} {
	 magic::cellmanager
	 magic::caption $win
      }
   }
}

# Generate the toolbar for the wrapper

proc magic::maketoolbar { framename } {

   # Make sure that window has been created so we will get the correct
   # height value.

   update idletasks
   set winheight [expr {[winfo height ${framename}] - \
		[winfo height ${framename}.titlebar]}]

   # Generate a layer image for "space" that will be used when layers are
   # invisible.

   image create layer img_space -name none

   # Generate layer images and buttons for toolbar

   set all_layers [concat {errors labels subcell} [magic::tech layer "*"]]
   foreach layername $all_layers {
      image create layer img_$layername -name $layername
      button ${framename}.toolbar.b$layername -image img_$layername -command \
		"::magic::see $layername"

      # Bindings:  Entering the button puts the canonical layer name in the 
      # message window.
      bind ${framename}.toolbar.b$layername <Enter> \
		[subst {focus %W ; ${framename}.titlebar.message configure \
		 -text "$layername"}]
      bind ${framename}.toolbar.b$layername <Leave> \
		[subst {${framename}.titlebar.message configure -text ""}]

      # 3rd mouse button makes layer invisible; 1st mouse button restores it.
      # 2nd mouse button paints the layer color.  Key "p" also does paint, esp.
      # for users with 2-button mice.  Key "e" erases, as does Shift-Button-2.

      bind ${framename}.toolbar.b$layername <ButtonPress-2> \
		"::magic::paint $layername"
      bind ${framename}.toolbar.b$layername <KeyPress-p> \
		"::magic::paint $layername"
      bind ${framename}.toolbar.b$layername <Shift-ButtonPress-2> \
		"::magic::erase $layername"
      bind ${framename}.toolbar.b$layername <KeyPress-e> \
		"::magic::erase $layername"
      bind ${framename}.toolbar.b$layername <ButtonPress-3> \
		"::magic::see no $layername"
      bind ${framename}.toolbar.b$layername <KeyPress-s> \
		"::magic::select more area $layername"
      bind ${framename}.toolbar.b$layername <KeyPress-S> \
		"::magic::select less area $layername"
   }

   # Figure out how many columns we need to fit all the layer buttons inside
   # the toolbar without going outside the window area.

   set ncols 1
   while {1} {
      incr ncols
      set i 0
      set j 0
      foreach layername $all_layers {
         ::grid ${framename}.toolbar.b$layername -row $i -column $j -sticky news
         incr j
         if {$j == $ncols} {
	    set j 0
	    incr i
         }
      }
      # tkwait visibility ${framename}.toolbar
      update idletasks
      set toolheight [lindex [::grid bbox ${framename}.toolbar] 3]
      if {$toolheight <= $winheight} {break}
   }
}

# Delete and rebuild the toolbar buttons in response to a "tech load"
# command.

proc magic::techrebuild {winpath {cmdstr ""}} {
   set framename [winfo parent $winpath]
   if {${cmdstr} == "load"} {
      set alltools [winfo children ${framename}.toolbar]
      foreach i $alltools {
         destroy $i
      }
      maketoolbar ${framename}

      magic::techmanager init
   }
}

# Create the wrapper and open up a layout window in it.

proc magic::openwrapper { {cell ""} } {
   global windowsopen
   
   incr windowsopen 
   set framename .layout${windowsopen}
   set winname ${framename}.magic
   
   toplevel $framename
   tkwait visibility $framename

   # Disallow scrollbars and title caption on windows---we'll do these ourselves
   windowcaption off
   windowscrollbars off

   scrollbar ${framename}.xscroll -orient horizontal -width 13 -jump true -command \
	"magic::scrollview $winname e"
   scrollbar ${framename}.yscroll -orient vertical -width 13 -jump true -command \
	"magic::scrollview $winname s"
   frame ${framename}.titlebar
   ::label ${framename}.titlebar.caption -text "Loaded: none Editing: none" \
	-foreground white -background sienna4 -anchor w -padx 15
   ::label ${framename}.titlebar.message -text "" -foreground white \
	-background sienna4 -anchor w -padx 5
   ::label ${framename}.titlebar.pos -text "" -foreground white \
	-background sienna4 -anchor w -padx 5

   # Menu buttons

   menubutton ${framename}.titlebar.filebutton -text File -menu \
		${framename}.titlebar.filebutton.filemenu -borderwidth 2
   button ${framename}.titlebar.cellbutton -text Cell -relief flat \
		-command "wm deiconify .cellmgr ; raise .cellmgr"
   button ${framename}.titlebar.techbutton -text Tech -relief flat \
		-command "wm deiconify .techmgr ; raise .techmgr"

   ::magic::openwindow $cell $winname

   # Create toolbar frame.  Make sure it has the same visual and depth as
   # the layout window, so there will be no problem using the GCs from the
   # layout window to paint into the toolbar.
   frame ${framename}.toolbar \
	-visual "[winfo visual ${winname}] [winfo depth ${winname}]"

   # Repaint to magic colors
   ::magic::repaintwrapper ${framename}

   ::grid ${framename}.titlebar -row 0 -column 0 -columnspan 3 -sticky news
   ::grid ${framename}.yscroll -row 1 -column 0 -sticky ns
   ::grid $winname -row 1 -column 1 -sticky news
   ::grid ${framename}.xscroll -row 2 -column 1 -sticky ew
   ::grid ${framename}.toolbar -row 1 -column 2 -rowspan 2 -sticky new

   ::grid rowconfigure ${framename} 1 -weight 1
   ::grid columnconfigure ${framename} 1 -weight 1

   ::grid ${framename}.titlebar.filebutton -row 0 -column 0 -sticky news
   ::grid ${framename}.titlebar.cellbutton -row 0 -column 1 -sticky news
   ::grid ${framename}.titlebar.techbutton -row 0 -column 2 -sticky news
   ::grid ${framename}.titlebar.caption -row 0 -column 3 -sticky news
   ::grid ${framename}.titlebar.message -row 0 -column 4 -sticky news
   ::grid ${framename}.titlebar.pos -row 0 -column 5 -sticky news
   ::grid columnconfigure ${framename}.titlebar 3 -weight 1

   bind $winname <Enter> {focus %W}

   # Button press events bypass the normal command mechanism, so any tag features
   # required on button presses/releases need to be duplicated.

   bind ${winname} <ButtonRelease> "::magic::boxview ${winname}"

   # Resize the window to be 3/4 of the screen size.
   set winwidth [expr 3 * [winfo screenwidth $framename] / 4]
   set winheight [expr 3 * [winfo screenheight $framename] / 4]
   wm geometry $framename ${winwidth}x${winheight}+100+100

   # Generate the toolbar

   magic::maketoolbar ${framename}

   # Generate the menus

   set m [menu ${framename}.titlebar.filebutton.filemenu -tearoff 0]
   $m add command -label "New window" -command "magic::openwrapper \
		[${winname} cellname list window]"
   $m add command -label "Close" -command "magic::closewrapper ${framename}"
   $m add separator
   $m add command -label "Load layout" -command {magic::promptload magic}
   $m add command -label "Read CIF" -command {magic::promptload cif}
   $m add command -label "Read GDS" -command {magic::promptload gds}
   $m add separator
   $m add command -label "Save layout" -command {magic::promptsave magic}
   $m add command -label "Write CIF" -command {magic::promptsave cif}
   $m add command -label "Write GDS" -command {magic::promptsave gds}
   $m add separator
   $m add command -label "Flush current" -command {magic::flushcell}
   $m add separator
   $m add command -label "Quit" -command {magic::quit}

   ${winname} ::magic::view

   # Create or update the cell manager
   magic::cellmanager
   magic::caption ${winname}

   # Rename "open" macro by rebinding
   magic::macro o "magic::openwrapper"
   magic::macro O "magic::closewrapper"

   return ${winname}
}

# Delete the wrapper and the layout window in it.

proc magic::closewrapper { framename } {
   ${framename}.magic ::magic::closewindow
   destroy $framename
}

# This procedure adds a command-line entry window to the bottom of
# a wrapper window (rudimentary functionality---incomplete)

proc magic::addcommandentry { framename } {
   global CAD_HOME
   if {![winfo exists ${framename}.eval]} {
      tkshell::YScrolled_Text ${framename}.eval -height 5
      tkshell::MakeEvaluator ${framename}.eval.text \
		"${framename}> " "${framename}.magic "
      tkshell::MainInit
   }
   ::set rc [::grid size ${framename}]  
   ::set cols [lindex $rc 0]
   ::grid ${framename}.eval -row 3 -column 0 -columnspan $cols -sticky ew
   bind ${framename}.eval.text <Enter> {focus %W}
}

# Remove the command entry window from the bottom of a frame.

proc magic::deletecommandentry { framename } {
   ::grid forget ${framename}.eval
}

namespace import ::magic::openwrapper
puts "Use openwrapper to create a new GUI-based layout window"
namespace import ::magic::closewrapper
puts "Use closewrapper to remove a new GUI-based layout window"
